aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Avatar
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs367
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs92
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs616
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs18
-rw-r--r--OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs97
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs293
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs67
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs5
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs169
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs17
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs58
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGStatusNotifier.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs20
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs213
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs19
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs31
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs69
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs297
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModuleTst.cs229
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs132
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/XMuteModule.cs239
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs297
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs38
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs48
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs217
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs120
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs84
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs60
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs74
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs236
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs178
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs30
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs986
40 files changed, 3755 insertions, 1697 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 2f67c4e..9f52a14 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -41,6 +41,8 @@ using OpenSim.Region.Framework;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Region.Framework.Scenes.Serialization; 43using OpenSim.Region.Framework.Scenes.Serialization;
44using OpenSim.Services.Interfaces;
45using PermissionMask = OpenSim.Framework.PermissionMask;
44 46
45namespace OpenSim.Region.CoreModules.Avatar.Attachments 47namespace OpenSim.Region.CoreModules.Avatar.Attachments
46{ 48{
@@ -60,7 +62,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
60 /// A value of 0 will apply no pause. The pause is specified in milliseconds. 62 /// A value of 0 will apply no pause. The pause is specified in milliseconds.
61 /// </remarks> 63 /// </remarks>
62 public int ThrottlePer100PrimsRezzed { get; set; } 64 public int ThrottlePer100PrimsRezzed { get; set; }
63 65
64 private Scene m_scene; 66 private Scene m_scene;
65 private IInventoryAccessModule m_invAccessModule; 67 private IInventoryAccessModule m_invAccessModule;
66 68
@@ -68,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
68 /// Are attachments enabled? 70 /// Are attachments enabled?
69 /// </summary> 71 /// </summary>
70 public bool Enabled { get; private set; } 72 public bool Enabled { get; private set; }
71 73
72 public string Name { get { return "Attachments Module"; } } 74 public string Name { get { return "Attachments Module"; } }
73 public Type ReplaceableInterface { get { return null; } } 75 public Type ReplaceableInterface { get { return null; } }
74 76
@@ -86,14 +88,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
86 Enabled = true; 88 Enabled = true;
87 } 89 }
88 } 90 }
89 91
90 public void AddRegion(Scene scene) 92 public void AddRegion(Scene scene)
91 { 93 {
92 m_scene = scene; 94 m_scene = scene;
93 if (Enabled) 95 if (Enabled)
94 { 96 {
95 // Only register module with scene if it is enabled. All callers check for a null attachments module. 97 // Only register module with scene if it is enabled. All callers check for a null attachments module.
96 // Ideally, there should be a null attachments module for when this core attachments module has been 98 // Ideally, there should be a null attachments module for when this core attachments module has been
97 // disabled. Registering only when enabled allows for other attachments module implementations. 99 // disabled. Registering only when enabled allows for other attachments module implementations.
98 m_scene.RegisterModuleInterface<IAttachmentsModule>(this); 100 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
99 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 101 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
@@ -180,7 +182,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
180 private void HandleScriptStateChange(uint localID, bool started) 182 private void HandleScriptStateChange(uint localID, bool started)
181 { 183 {
182 SceneObjectGroup sog = m_scene.GetGroupByPrim(localID); 184 SceneObjectGroup sog = m_scene.GetGroupByPrim(localID);
183 if (sog != null && sog.IsAttachment) 185 if (sog != null && sog.IsAttachment)
184 { 186 {
185 if (!started) 187 if (!started)
186 { 188 {
@@ -197,21 +199,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
197 } 199 }
198 } 200 }
199 } 201 }
200 202
201 public void RemoveRegion(Scene scene) 203 public void RemoveRegion(Scene scene)
202 { 204 {
203 m_scene.UnregisterModuleInterface<IAttachmentsModule>(this); 205 m_scene.UnregisterModuleInterface<IAttachmentsModule>(this);
204 206
205 if (Enabled) 207 if (Enabled)
206 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents; 208 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents;
207 } 209 }
208 210
209 public void RegionLoaded(Scene scene) 211 public void RegionLoaded(Scene scene)
210 { 212 {
211 m_invAccessModule = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 213 m_invAccessModule = m_scene.RequestModuleInterface<IInventoryAccessModule>();
212 } 214 }
213 215
214 public void Close() 216 public void Close()
215 { 217 {
216 RemoveRegion(m_scene); 218 RemoveRegion(m_scene);
217 } 219 }
@@ -269,7 +271,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
269 ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule(); 271 ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule();
270 272
271// m_log.DebugFormat( 273// m_log.DebugFormat(
272// "[ATTACHMENTS MODULE]: Copying script state with {0} bytes for object {1} for {2} in {3}", 274// "[ATTACHMENTS MODULE]: Copying script state with {0} bytes for object {1} for {2} in {3}",
273// ad.AttachmentObjectStates[i].Length, so.Name, sp.Name, m_scene.Name); 275// ad.AttachmentObjectStates[i].Length, so.Name, sp.Name, m_scene.Name);
274 276
275 so.SetState(ad.AttachmentObjectStates[i++], m_scene); 277 so.SetState(ad.AttachmentObjectStates[i++], m_scene);
@@ -294,7 +296,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
294 { 296 {
295 if (DebugLevel > 0) 297 if (DebugLevel > 0)
296 m_log.DebugFormat( 298 m_log.DebugFormat(
297 "[ATTACHMENTS MODULE]: Not doing simulator-side attachment rez for {0} in {1} as their viewer has already rezzed attachments", 299 "[ATTACHMENTS MODULE]: Not doing simulator-side attachment rez for {0} in {1} as their viewer has already rezzed attachments",
298 m_scene.Name, sp.Name); 300 m_scene.Name, sp.Name);
299 301
300 return; 302 return;
@@ -303,6 +305,41 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
303 if (DebugLevel > 0) 305 if (DebugLevel > 0)
304 m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name); 306 m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name);
305 307
308 XmlDocument doc = new XmlDocument();
309 doc.XmlResolver=null;
310 string stateData = String.Empty;
311
312 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
313 if (attServ != null)
314 {
315 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
316 stateData = attServ.Get(sp.UUID.ToString());
317 if (stateData != String.Empty)
318 {
319 try
320 {
321 doc.LoadXml(stateData);
322 }
323 catch { }
324 }
325 }
326
327 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
328
329 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
330 if (nodes.Count > 0)
331 {
332 foreach (XmlNode n in nodes)
333 {
334 XmlElement elem = (XmlElement)n;
335 string itemID = elem.GetAttribute("ItemID");
336 string xml = elem.InnerXml;
337
338 itemData[new UUID(itemID)] = xml;
339 }
340 }
341
342
306 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); 343 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
307 344
308 // Let's get all items at once, so they get cached 345 // Let's get all items at once, so they get cached
@@ -322,7 +359,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
322 359
323 // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down 360 // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down
324 // But they're not used anyway, the item is being looked up for now, so let's proceed. 361 // But they're not used anyway, the item is being looked up for now, so let's proceed.
325 //if (UUID.Zero == assetID) 362 //if (UUID.Zero == assetID)
326 //{ 363 //{
327 // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID); 364 // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID);
328 // continue; 365 // continue;
@@ -330,10 +367,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
330 367
331 try 368 try
332 { 369 {
370 string xmlData;
371 XmlDocument d = null;
372 UUID asset;
373 if (itemData.TryGetValue(attach.ItemID, out xmlData))
374 {
375 d = new XmlDocument();
376 d.XmlResolver=null;
377 d.LoadXml(xmlData);
378 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", attach.ItemID);
379 }
380
333 // If we're an NPC then skip all the item checks and manipulations since we don't have an 381 // If we're an NPC then skip all the item checks and manipulations since we don't have an
334 // inventory right now. 382 // inventory right now.
335 RezSingleAttachmentFromInventoryInternal( 383 RezSingleAttachmentFromInventoryInternal(
336 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true); 384 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true, d);
337 } 385 }
338 catch (Exception e) 386 catch (Exception e)
339 { 387 {
@@ -361,26 +409,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
361 409
362 Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>(); 410 Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>();
363 411
364 foreach (SceneObjectGroup so in attachments) 412
413 if (sp.PresenceType != PresenceType.Npc)
365 { 414 {
366 // Scripts MUST be snapshotted before the object is 415 foreach (SceneObjectGroup so in attachments)
367 // removed from the scene because doing otherwise will 416 {
368 // clobber the run flag 417 // Scripts MUST be snapshotted before the object is
369 // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from 418 // removed from the scene because doing otherwise will
370 // scripts performing attachment operations at the same time. Getting object states stops the scripts. 419 // clobber the run flag
371 scriptStates[so] = PrepareScriptInstanceForSave(so, false); 420 // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from
421 // scripts performing attachment operations at the same time. Getting object states stops the scripts.
422 scriptStates[so] = PrepareScriptInstanceForSave(so, false);
423 }
372 424
373// m_log.DebugFormat( 425 lock (sp.AttachmentsSyncLock)
374// "[ATTACHMENTS MODULE]: For object {0} for {1} in {2} got saved state {3}", 426 {
375// so.Name, sp.Name, m_scene.Name, scriptStates[so]); 427 foreach (SceneObjectGroup so in attachments)
428 UpdateDetachedObject(sp, so, scriptStates[so]);
429 sp.ClearAttachments();
430 }
376 } 431 }
377 432 else
378 lock (sp.AttachmentsSyncLock)
379 { 433 {
380 foreach (SceneObjectGroup so in attachments) 434 lock (sp.AttachmentsSyncLock)
381 UpdateDetachedObject(sp, so, scriptStates[so]); 435 {
382 436 foreach (SceneObjectGroup so in attachments)
383 sp.ClearAttachments(); 437 UpdateDetachedObject(sp, so, String.Empty);
438 sp.ClearAttachments();
439 }
384 } 440 }
385 } 441 }
386 442
@@ -392,7 +448,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
392 if (DebugLevel > 0) 448 if (DebugLevel > 0)
393 m_log.DebugFormat( 449 m_log.DebugFormat(
394 "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}", 450 "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
395 m_scene.RegionInfo.RegionName, sp.Name, silent); 451 m_scene.RegionInfo.RegionName, sp.Name, silent);
396 452
397 foreach (SceneObjectGroup sop in sp.GetAttachments()) 453 foreach (SceneObjectGroup sop in sp.GetAttachments())
398 { 454 {
@@ -401,21 +457,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
401 457
402 sp.ClearAttachments(); 458 sp.ClearAttachments();
403 } 459 }
404 460
405 public bool AttachObject( 461 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent,
406 IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool append) 462 bool addToInventory, bool append)
407 { 463 {
408 if (!Enabled) 464 if (!Enabled)
409 return false; 465 return false;
410 466
411 group.DetachFromBackup(); 467 return AttachObjectInternal(sp, group, attachmentPt, silent, addToInventory, false, append);
412
413 bool success = AttachObjectInternal(sp, group, attachmentPt, silent, addToInventory, false, append);
414
415 if (!success)
416 group.AttachToBackup();
417
418 return success;
419 } 468 }
420 469
421 /// <summary> 470 /// <summary>
@@ -428,10 +477,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
428 /// <param name='silent'></param> 477 /// <param name='silent'></param>
429 /// <param name='addToInventory'>If true then add object to user inventory.</param> 478 /// <param name='addToInventory'>If true then add object to user inventory.</param>
430 /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param> 479 /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param>
431 /// <param name='append'>Append to attachment point rather than replace.</param> 480 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt,
432 private bool AttachObjectInternal( 481 bool silent, bool addToInventory, bool resumeScripts, bool append)
433 IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool resumeScripts, bool append)
434 { 482 {
483// m_log.DebugFormat(
484// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
485// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
486
487
435 if (group.GetSittingAvatarsCount() != 0) 488 if (group.GetSittingAvatarsCount() != 0)
436 { 489 {
437 if (DebugLevel > 0) 490 if (DebugLevel > 0)
@@ -442,7 +495,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
442 return false; 495 return false;
443 } 496 }
444 497
498 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
499 if (attachments.Contains(group))
500 {
501// if (DebugLevel > 0)
502// m_log.WarnFormat(
503// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
504// group.Name, group.LocalId, sp.Name, attachmentPt);
505
506 return false;
507 }
508
445 Vector3 attachPos = group.AbsolutePosition; 509 Vector3 attachPos = group.AbsolutePosition;
510
511 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
512 // be removed when that functionality is implemented in opensim
513 attachmentPt &= 0x7f;
514
446 // If the attachment point isn't the same as the one previously used 515 // If the attachment point isn't the same as the one previously used
447 // set it's offset position = 0 so that it appears on the attachment point 516 // set it's offset position = 0 so that it appears on the attachment point
448 // and not in a weird location somewhere unknown. 517 // and not in a weird location somewhere unknown.
@@ -470,7 +539,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
470 { 539 {
471 attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint; 540 attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint;
472 attachPos = group.RootPart.AttachedPos; 541 attachPos = group.RootPart.AttachedPos;
473 group.HasGroupChanged = true;
474 } 542 }
475 543
476 // if we still didn't find a suitable attachment point....... 544 // if we still didn't find a suitable attachment point.......
@@ -481,21 +549,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
481 attachPos = Vector3.Zero; 549 attachPos = Vector3.Zero;
482 } 550 }
483 551
484 group.AttachmentPoint = attachmentPt;
485 group.AbsolutePosition = attachPos;
486
487 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
488
489 if (attachments.Contains(group))
490 {
491 if (DebugLevel > 0)
492 m_log.WarnFormat(
493 "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
494 group.Name, group.LocalId, sp.Name, attachmentPt);
495
496 return false;
497 }
498
499 // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones 552 // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones
500 while (attachments.Count >= 5) 553 while (attachments.Count >= 5)
501 { 554 {
@@ -514,11 +567,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
514 } 567 }
515 } 568 }
516 569
570 group.DetachFromBackup();
571
517 lock (sp.AttachmentsSyncLock) 572 lock (sp.AttachmentsSyncLock)
518 { 573 {
574 group.AttachmentPoint = attachmentPt;
575 group.RootPart.AttachedPos = attachPos;
576
519 if (addToInventory && sp.PresenceType != PresenceType.Npc) 577 if (addToInventory && sp.PresenceType != PresenceType.Npc)
520 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append); 578 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append);
521 579
522 AttachToAgent(sp, group, attachmentPt, attachPos, silent); 580 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
523 581
524 if (resumeScripts) 582 if (resumeScripts)
@@ -529,8 +587,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
529 group.ResumeScripts(); 587 group.ResumeScripts();
530 } 588 }
531 589
590 else
532 // Do this last so that event listeners have access to all the effects of the attachment 591 // Do this last so that event listeners have access to all the effects of the attachment
533 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); 592 // this can't be done when creating scripts:
593 // scripts do internal enqueue of attach event
594 // and not all scripts are loaded at this point
595 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID);
534 } 596 }
535 597
536 return true; 598 return true;
@@ -546,7 +608,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
546 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append); 608 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append);
547 } 609 }
548 610
549 public SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) 611 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
612 {
613 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, null);
614 }
615
616 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt, XmlDocument doc)
550 { 617 {
551 if (!Enabled) 618 if (!Enabled)
552 return null; 619 return null;
@@ -557,8 +624,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
557 (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name); 624 (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name);
558 625
559 // We check the attachments in the avatar appearance here rather than the objects attached to the 626 // We check the attachments in the avatar appearance here rather than the objects attached to the
560 // ScenePresence itself so that we can ignore calls by viewer 2/3 to attach objects on startup. We are 627 // ScenePresence itself so that we can ignore calls by viewer 2/3 to attach objects on startup. We are
561 // already doing this in ScenePresence.MakeRootAgent(). Simulator-side attaching needs to be done 628 // already doing this in ScenePresence.MakeRootAgent(). Simulator-side attaching needs to be done
562 // because pre-outfit folder viewers (most version 1 viewers) require it. 629 // because pre-outfit folder viewers (most version 1 viewers) require it.
563 bool alreadyOn = false; 630 bool alreadyOn = false;
564 List<AvatarAttachment> existingAttachments = sp.Appearance.GetAttachments(); 631 List<AvatarAttachment> existingAttachments = sp.Appearance.GetAttachments();
@@ -584,7 +651,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
584 bool append = (AttachmentPt & 0x80) != 0; 651 bool append = (AttachmentPt & 0x80) != 0;
585 AttachmentPt &= 0x7f; 652 AttachmentPt &= 0x7f;
586 653
587 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append); 654 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append, doc);
588 } 655 }
589 656
590 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) 657 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
@@ -594,7 +661,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
594 661
595 if (DebugLevel > 0) 662 if (DebugLevel > 0)
596 m_log.DebugFormat( 663 m_log.DebugFormat(
597 "[ATTACHMENTS MODULE]: Rezzing {0} attachments from inventory for {1} in {2}", 664 "[ATTACHMENTS MODULE]: Rezzing {0} attachments from inventory for {1} in {2}",
598 rezlist.Count, sp.Name, m_scene.Name); 665 rezlist.Count, sp.Name, m_scene.Name);
599 666
600 foreach (KeyValuePair<UUID, uint> rez in rezlist) 667 foreach (KeyValuePair<UUID, uint> rez in rezlist)
@@ -605,7 +672,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
605 672
606 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) 673 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId)
607 { 674 {
608 DetachSingleAttachmentToGround(sp, soLocalId, sp.AbsolutePosition, Quaternion.Identity); 675 Vector3 pos = new Vector3(2.5f, 0f, 0f);
676 pos *= ((ScenePresence)sp).Rotation;
677 pos += sp.AbsolutePosition;
678 DetachSingleAttachmentToGround(sp, soLocalId, pos, Quaternion.Identity);
609 } 679 }
610 680
611 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot) 681 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot)
@@ -649,26 +719,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
649 if (changed && m_scene.AvatarFactory != null) 719 if (changed && m_scene.AvatarFactory != null)
650 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 720 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
651 721
722 so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint;
723
652 sp.RemoveAttachment(so); 724 sp.RemoveAttachment(so);
653 so.FromItemID = UUID.Zero; 725 so.FromItemID = UUID.Zero;
654 726
727 so.AttachedAvatar = UUID.Zero;
728 so.ClearPartAttachmentData();
729
655 SceneObjectPart rootPart = so.RootPart; 730 SceneObjectPart rootPart = so.RootPart;
731
732 rootPart.SetParentLocalId(0);
656 so.AbsolutePosition = absolutePos; 733 so.AbsolutePosition = absolutePos;
657 if (absoluteRot != Quaternion.Identity) 734 if (absoluteRot != Quaternion.Identity)
658 { 735 {
659 so.UpdateGroupRotationR(absoluteRot); 736 so.UpdateGroupRotationR(absoluteRot);
660 } 737 }
661 so.AttachedAvatar = UUID.Zero; 738
662 rootPart.SetParentLocalId(0);
663 so.ClearPartAttachmentData();
664 rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive);
665 so.HasGroupChanged = true;
666 so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint;
667 rootPart.Rezzed = DateTime.Now;
668 rootPart.RemFlag(PrimFlags.TemporaryOnRez); 739 rootPart.RemFlag(PrimFlags.TemporaryOnRez);
740
741 so.ApplyPhysics();
742
743 rootPart.Rezzed = DateTime.Now;
669 so.AttachToBackup(); 744 so.AttachToBackup();
670 m_scene.EventManager.TriggerParcelPrimCountTainted(); 745 m_scene.EventManager.TriggerParcelPrimCountTainted();
671 rootPart.ScheduleFullUpdate(); 746
672 rootPart.ClearUndoState(); 747 rootPart.ClearUndoState();
673 748
674 List<UUID> uuids = new List<UUID>(); 749 List<UUID> uuids = new List<UUID>();
@@ -678,6 +753,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
678 } 753 }
679 754
680 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); 755 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
756
757 // Attach (NULL) stops scripts. We don't want that. Resume them.
758 so.ResumeScripts();
759 so.HasGroupChanged = true;
760 so.RootPart.ScheduleFullUpdate();
761 so.ScheduleGroupForTerseUpdate();
681 } 762 }
682 763
683 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) 764 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so)
@@ -691,9 +772,32 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
691 return; 772 return;
692 } 773 }
693 774
775 // If this didn't come from inventory, it also shouldn't go there
776 // on detach. It's likely a temp attachment.
777 if (so.FromItemID == UUID.Zero)
778 {
779 // Retirn value is ignored
780 PrepareScriptInstanceForSave(so, true);
781
782 lock (sp.AttachmentsSyncLock)
783 {
784 bool changed = sp.Appearance.DetachAttachment(so.FromItemID);
785 if (changed && m_scene.AvatarFactory != null)
786 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
787
788 sp.RemoveAttachment(so);
789 }
790
791 m_scene.DeleteSceneObject(so, false, false);
792 so.RemoveScriptInstances(true);
793 so.Clear();
794
795 return;
796 }
797
694 if (DebugLevel > 0) 798 if (DebugLevel > 0)
695 m_log.DebugFormat( 799 m_log.DebugFormat(
696 "[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}", 800 "[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}",
697 so.Name, so.LocalId, so.FromItemID, sp.Name, m_scene.Name); 801 so.Name, so.LocalId, so.FromItemID, sp.Name, m_scene.Name);
698 802
699 // Scripts MUST be snapshotted before the object is 803 // Scripts MUST be snapshotted before the object is
@@ -716,14 +820,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
716 UpdateDetachedObject(sp, so, scriptedState); 820 UpdateDetachedObject(sp, so, scriptedState);
717 } 821 }
718 } 822 }
719 823
720 public void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos) 824 public void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos)
721 { 825 {
722 if (!Enabled) 826 if (!Enabled)
723 return; 827 return;
724 828
725 sog.UpdateGroupPosition(pos); 829 sog.UpdateGroupPosition(pos);
726 sog.HasGroupChanged = true; 830 sog.HasGroupChanged = true;
727 } 831 }
728 832
729 #endregion 833 #endregion
@@ -732,7 +836,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
732 836
733 // This is public but is not part of the IAttachmentsModule interface. 837 // This is public but is not part of the IAttachmentsModule interface.
734 // RegionCombiner module needs to poke at it to deliver client events. 838 // RegionCombiner module needs to poke at it to deliver client events.
735 // This breaks the encapsulation of the module and should get fixed somehow. 839 // This breaks the encapsulation of the module and should get fixed somehow.
736 public void SubscribeToClientEvents(IClientAPI client) 840 public void SubscribeToClientEvents(IClientAPI client)
737 { 841 {
738 client.OnRezSingleAttachmentFromInv += Client_OnRezSingleAttachmentFromInv; 842 client.OnRezSingleAttachmentFromInv += Client_OnRezSingleAttachmentFromInv;
@@ -745,7 +849,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
745 849
746 // This is public but is not part of the IAttachmentsModule interface. 850 // This is public but is not part of the IAttachmentsModule interface.
747 // RegionCombiner module needs to poke at it to deliver client events. 851 // RegionCombiner module needs to poke at it to deliver client events.
748 // This breaks the encapsulation of the module and should get fixed somehow. 852 // This breaks the encapsulation of the module and should get fixed somehow.
749 public void UnsubscribeFromClientEvents(IClientAPI client) 853 public void UnsubscribeFromClientEvents(IClientAPI client)
750 { 854 {
751 client.OnRezSingleAttachmentFromInv -= Client_OnRezSingleAttachmentFromInv; 855 client.OnRezSingleAttachmentFromInv -= Client_OnRezSingleAttachmentFromInv;
@@ -791,11 +895,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
791 895
792 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); 896 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState);
793 897
794 InventoryItemBase item = new InventoryItemBase(grp.FromItemID, sp.UUID); 898 InventoryItemBase item = m_scene.InventoryService.GetItem(sp.UUID, grp.FromItemID);
795 item = m_scene.InventoryService.GetItem(item);
796 899
797 if (item != null) 900 if (item != null)
798 { 901 {
902 // attach is rez, need to update permissions
903 item.Flags &= ~(uint)(InventoryItemFlags.ObjectSlamPerm | InventoryItemFlags.ObjectOverwriteBase |
904 InventoryItemFlags.ObjectOverwriteOwner | InventoryItemFlags.ObjectOverwriteGroup |
905 InventoryItemFlags.ObjectOverwriteEveryone | InventoryItemFlags.ObjectOverwriteNextOwner);
906
907 uint permsBase = (uint)(PermissionMask.Copy | PermissionMask.Transfer |
908 PermissionMask.Modify | PermissionMask.Move |
909 PermissionMask.Export | PermissionMask.FoldedMask);
910
911 permsBase &= grp.CurrentAndFoldedNextPermissions();
912 permsBase |= (uint)PermissionMask.Move;
913 item.BasePermissions = permsBase;
914 item.CurrentPermissions = permsBase;
915 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask | (uint)PermissionMask.Move;
916 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
917 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
918 item.CurrentPermissions &=
919 ((uint)PermissionMask.Copy |
920 (uint)PermissionMask.Transfer |
921 (uint)PermissionMask.Modify |
922 (uint)PermissionMask.Move |
923 (uint)PermissionMask.Export |
924 (uint)PermissionMask.FoldedMask); // Preserve folded permissions ??
925
799 AssetBase asset = m_scene.CreateAsset( 926 AssetBase asset = m_scene.CreateAsset(
800 grp.GetPartName(grp.LocalId), 927 grp.GetPartName(grp.LocalId),
801 grp.GetPartDescription(grp.LocalId), 928 grp.GetPartDescription(grp.LocalId),
@@ -826,7 +953,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
826 /// Attach this scene object to the given avatar. 953 /// Attach this scene object to the given avatar.
827 /// </summary> 954 /// </summary>
828 /// <remarks> 955 /// <remarks>
829 /// This isn't publicly available since attachments should always perform the corresponding inventory 956 /// This isn't publicly available since attachments should always perform the corresponding inventory
830 /// operation (to show the attach in user inventory and update the asset with positional information). 957 /// operation (to show the attach in user inventory and update the asset with positional information).
831 /// </remarks> 958 /// </remarks>
832 /// <param name="sp"></param> 959 /// <param name="sp"></param>
@@ -846,16 +973,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
846 m_scene.DeleteFromStorage(so.UUID); 973 m_scene.DeleteFromStorage(so.UUID);
847 m_scene.EventManager.TriggerParcelPrimCountTainted(); 974 m_scene.EventManager.TriggerParcelPrimCountTainted();
848 975
849 so.AttachedAvatar = sp.UUID;
850 976
851 if (so.RootPart.PhysActor != null) 977 foreach (SceneObjectPart part in so.Parts)
852 so.RootPart.RemoveFromPhysics(); 978 {
979// if (part.KeyframeMotion != null)
980// part.KeyframeMotion.Suspend();
981
982 if (part.PhysActor != null)
983 {
984 part.RemoveFromPhysics();
985 }
986 }
853 987
854 so.AbsolutePosition = attachOffset;
855 so.RootPart.AttachedPos = attachOffset;
856 so.IsAttachment = true;
857 so.RootPart.SetParentLocalId(sp.LocalId); 988 so.RootPart.SetParentLocalId(sp.LocalId);
989 so.AttachedAvatar = sp.UUID;
858 so.AttachmentPoint = attachmentpoint; 990 so.AttachmentPoint = attachmentpoint;
991 so.RootPart.AttachedPos = attachOffset;
992 so.AbsolutePosition = attachOffset;
993 so.IsAttachment = true;
859 994
860 sp.AddAttachment(so); 995 sp.AddAttachment(so);
861 996
@@ -879,7 +1014,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
879 1014
880 // Fudge below is an extremely unhelpful comment. It's probably here so that the scheduled full update 1015 // Fudge below is an extremely unhelpful comment. It's probably here so that the scheduled full update
881 // will succeed, as that will not update if an attachment is selected. 1016 // will succeed, as that will not update if an attachment is selected.
882 so.IsSelected = false; // fudge.... 1017 so.IsSelected = false; // fudge....
883 1018
884 so.ScheduleGroupForFullUpdate(); 1019 so.ScheduleGroupForFullUpdate();
885 } 1020 }
@@ -923,7 +1058,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
923 /// </summary> 1058 /// </summary>
924 /// <remarks> 1059 /// <remarks>
925 /// This involves triggering the detach event and getting the script state (which also stops the script) 1060 /// This involves triggering the detach event and getting the script state (which also stops the script)
926 /// This MUST be done outside sp.AttachmentsSyncLock, since otherwise there is a chance of deadlock if a 1061 /// This MUST be done outside sp.AttachmentsSyncLock, since otherwise there is a chance of deadlock if a
927 /// running script is performing attachment operations. 1062 /// running script is performing attachment operations.
928 /// </remarks> 1063 /// </remarks>
929 /// <returns> 1064 /// <returns>
@@ -939,7 +1074,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
939 if (fireDetachEvent) 1074 if (fireDetachEvent)
940 { 1075 {
941 m_scene.EventManager.TriggerOnAttach(grp.LocalId, grp.FromItemID, UUID.Zero); 1076 m_scene.EventManager.TriggerOnAttach(grp.LocalId, grp.FromItemID, UUID.Zero);
942
943 // Allow detach event time to do some work before stopping the script 1077 // Allow detach event time to do some work before stopping the script
944 Thread.Sleep(2); 1078 Thread.Sleep(2);
945 } 1079 }
@@ -971,6 +1105,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
971 // Remove the object from the scene so no more updates 1105 // Remove the object from the scene so no more updates
972 // are sent. Doing this before the below changes will ensure 1106 // are sent. Doing this before the below changes will ensure
973 // updates can't cause "HUD artefacts" 1107 // updates can't cause "HUD artefacts"
1108
974 m_scene.DeleteSceneObject(so, false, false); 1109 m_scene.DeleteSceneObject(so, false, false);
975 1110
976 // Prepare sog for storage 1111 // Prepare sog for storage
@@ -989,23 +1124,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
989 1124
990 // Now, remove the scripts 1125 // Now, remove the scripts
991 so.RemoveScriptInstances(true); 1126 so.RemoveScriptInstances(true);
1127 so.Clear();
992 } 1128 }
993 1129
994 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 1130 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
995 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append) 1131 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append, XmlDocument doc)
996 { 1132 {
997 if (m_invAccessModule == null) 1133 if (m_invAccessModule == null)
998 return null; 1134 return null;
999 1135
1000 SceneObjectGroup objatt; 1136 SceneObjectGroup objatt;
1001 1137
1138 UUID rezGroupID;
1139
1140 // This will fail if the user aborts login. sp will exist
1141 // but ControllintClient will be null.
1142 try
1143 {
1144 rezGroupID = sp.ControllingClient.ActiveGroupId;
1145 }
1146 catch
1147 {
1148 return null;
1149 }
1150
1002 if (itemID != UUID.Zero) 1151 if (itemID != UUID.Zero)
1003 objatt = m_invAccessModule.RezObject(sp.ControllingClient, 1152 objatt = m_invAccessModule.RezObject(sp.ControllingClient,
1004 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, 1153 itemID, rezGroupID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
1005 false, false, sp.UUID, true); 1154 false, false, sp.UUID, true);
1006 else 1155 else
1007 objatt = m_invAccessModule.RezObject(sp.ControllingClient, 1156 objatt = m_invAccessModule.RezObject(sp.ControllingClient,
1008 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, 1157 null, rezGroupID, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
1009 false, false, sp.UUID, true); 1158 false, false, sp.UUID, true);
1010 1159
1011 if (objatt == null) 1160 if (objatt == null)
@@ -1018,7 +1167,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1018 } 1167 }
1019 else if (itemID == UUID.Zero) 1168 else if (itemID == UUID.Zero)
1020 { 1169 {
1021 // We need to have a FromItemID for multiple attachments on a single attach point to appear. This is 1170 // We need to have a FromItemID for multiple attachments on a single attach point to appear. This is
1022 // true on Singularity 1.8.5 and quite possibly other viewers as well. As NPCs don't have an inventory 1171 // true on Singularity 1.8.5 and quite possibly other viewers as well. As NPCs don't have an inventory
1023 // we will satisfy this requirement by inserting a random UUID. 1172 // we will satisfy this requirement by inserting a random UUID.
1024 objatt.FromItemID = UUID.Random(); 1173 objatt.FromItemID = UUID.Random();
@@ -1043,6 +1192,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1043 // This will throw if the attachment fails 1192 // This will throw if the attachment fails
1044 try 1193 try
1045 { 1194 {
1195 if (doc != null)
1196 {
1197 objatt.LoadScriptState(doc);
1198 objatt.ResetOwnerChangeFlag();
1199 }
1200
1046 AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, append); 1201 AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, append);
1047 } 1202 }
1048 catch (Exception e) 1203 catch (Exception e)
@@ -1058,7 +1213,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1058 } 1213 }
1059 1214
1060 if (tainted) 1215 if (tainted)
1061 objatt.HasGroupChanged = true; 1216 objatt.HasGroupChanged = true;
1062 1217
1063 if (ThrottlePer100PrimsRezzed > 0) 1218 if (ThrottlePer100PrimsRezzed > 0)
1064 { 1219 {
@@ -1100,8 +1255,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1100 return; 1255 return;
1101 } 1256 }
1102 1257
1103 InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID); 1258 InventoryItemBase item = m_scene.InventoryService.GetItem(sp.UUID, itemID);
1104 item = m_scene.InventoryService.GetItem(item);
1105 if (item == null) 1259 if (item == null)
1106 return; 1260 return;
1107 1261
@@ -1185,7 +1339,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1185 if (part == null) 1339 if (part == null)
1186 return; 1340 return;
1187 1341
1188 if (!m_scene.Permissions.CanTakeObject(part.UUID, remoteClient.AgentId)) 1342 SceneObjectGroup group = part.ParentGroup;
1343
1344 if (!m_scene.Permissions.CanTakeObject(group, sp))
1189 { 1345 {
1190 remoteClient.SendAgentAlertMessage( 1346 remoteClient.SendAgentAlertMessage(
1191 "You don't have sufficient permissions to attach this object", false); 1347 "You don't have sufficient permissions to attach this object", false);
@@ -1197,7 +1353,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1197 AttachmentPt &= 0x7f; 1353 AttachmentPt &= 0x7f;
1198 1354
1199 // Calls attach with a Zero position 1355 // Calls attach with a Zero position
1200 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, append)) 1356 if (AttachObject(sp, group , AttachmentPt, false, true, append))
1201 { 1357 {
1202 if (DebugLevel > 0) 1358 if (DebugLevel > 0)
1203 m_log.Debug( 1359 m_log.Debug(
@@ -1205,7 +1361,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1205 + ", AttachmentPoint: " + AttachmentPt); 1361 + ", AttachmentPoint: " + AttachmentPt);
1206 1362
1207 // Save avatar attachment information 1363 // Save avatar attachment information
1208 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId); 1364 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
1209 } 1365 }
1210 } 1366 }
1211 catch (Exception e) 1367 catch (Exception e)
@@ -1222,7 +1378,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1222 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); 1378 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
1223 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); 1379 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID);
1224 1380
1225 if (sp != null && group != null && group.FromItemID != UUID.Zero) 1381 if (sp != null && group != null)
1226 DetachSingleAttachmentToInv(sp, group); 1382 DetachSingleAttachmentToInv(sp, group);
1227 } 1383 }
1228 1384
@@ -1256,7 +1412,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1256 if (sp != null) 1412 if (sp != null)
1257 DetachSingleAttachmentToGround(sp, soLocalId); 1413 DetachSingleAttachmentToGround(sp, soLocalId);
1258 } 1414 }
1259
1260 #endregion 1415 #endregion
1261 } 1416 }
1262} 1417}
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 0ac3add..941853c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -55,6 +55,7 @@ using OpenSim.Tests.Common;
55 55
56namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests 56namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
57{ 57{
58/*
58 /// <summary> 59 /// <summary>
59 /// Attachment tests 60 /// Attachment tests
60 /// </summary> 61 /// </summary>
@@ -200,7 +201,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
200 Assert.That(so.Backup, Is.True); 201 Assert.That(so.Backup, Is.True);
201 202
202 m_numberOfAttachEventsFired = 0; 203 m_numberOfAttachEventsFired = 0;
203 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false); 204 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false);
204 205
205 // Check status on scene presence 206 // Check status on scene presence
206 Assert.That(sp.HasAttachments(), Is.True); 207 Assert.That(sp.HasAttachments(), Is.True);
@@ -215,11 +216,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
215 Assert.That(attSo.Backup, Is.False); 216 Assert.That(attSo.Backup, Is.False);
216 217
217 // Check item status 218 // Check item status
218 Assert.That( 219// Assert.That(
219 sp.Appearance.GetAttachpoint(attSo.FromItemID), 220// sp.Appearance.GetAttachpoint(attSo.FromItemID),
220 Is.EqualTo((int)AttachmentPoint.Chest)); 221// Is.EqualTo((int)AttachmentPoint.Chest));
221 222
222 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); 223 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(sp.UUID, attSo.FromItemID);
223 Assert.That(attachmentItem, Is.Not.Null); 224 Assert.That(attachmentItem, Is.Not.Null);
224 Assert.That(attachmentItem.Name, Is.EqualTo(attName)); 225 Assert.That(attachmentItem.Name, Is.EqualTo(attName));
225 226
@@ -262,11 +263,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
262 Assert.That(attSo.IsTemporary, Is.False); 263 Assert.That(attSo.IsTemporary, Is.False);
263 264
264 // Check item status 265 // Check item status
265 Assert.That( 266// Assert.That(
266 sp.Appearance.GetAttachpoint(attSo.FromItemID), 267// sp.Appearance.GetAttachpoint(attSo.FromItemID),
267 Is.EqualTo((int)AttachmentPoint.LeftHand)); 268// Is.EqualTo((int)AttachmentPoint.LeftHand));
268 269
269 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); 270 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(sp.UUID, attSo.FromItemID);
270 Assert.That(attachmentItem, Is.Not.Null); 271 Assert.That(attachmentItem, Is.Not.Null);
271 Assert.That(attachmentItem.Name, Is.EqualTo(so.Name)); 272 Assert.That(attachmentItem.Name, Is.EqualTo(so.Name));
272 273
@@ -281,7 +282,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
281 282
282 // Test wearing a different attachment from the ground. 283 // Test wearing a different attachment from the ground.
283 { 284 {
284 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false); 285 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false);
285 286
286 // Check status on scene presence 287 // Check status on scene presence
287 Assert.That(sp.HasAttachments(), Is.True); 288 Assert.That(sp.HasAttachments(), Is.True);
@@ -295,11 +296,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
295 Assert.That(attSo.IsTemporary, Is.False); 296 Assert.That(attSo.IsTemporary, Is.False);
296 297
297 // Check item status 298 // Check item status
298 Assert.That( 299// Assert.That(
299 sp.Appearance.GetAttachpoint(attSo.FromItemID), 300// sp.Appearance.GetAttachpoint(attSo.FromItemID),
300 Is.EqualTo((int)AttachmentPoint.LeftHand)); 301// Is.EqualTo((int)AttachmentPoint.LeftHand));
301 302
302 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); 303 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(sp.UUID, attSo.FromItemID);
303 Assert.That(attachmentItem, Is.Not.Null); 304 Assert.That(attachmentItem, Is.Not.Null);
304 Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name)); 305 Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name));
305 306
@@ -314,7 +315,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
314 315
315 // Test rewearing an already worn attachment from ground. Nothing should happen. 316 // Test rewearing an already worn attachment from ground. Nothing should happen.
316 { 317 {
317 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false); 318 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false);
318 319
319 // Check status on scene presence 320 // Check status on scene presence
320 Assert.That(sp.HasAttachments(), Is.True); 321 Assert.That(sp.HasAttachments(), Is.True);
@@ -328,11 +329,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
328 Assert.That(attSo.IsTemporary, Is.False); 329 Assert.That(attSo.IsTemporary, Is.False);
329 330
330 // Check item status 331 // Check item status
331 Assert.That( 332// Assert.That(
332 sp.Appearance.GetAttachpoint(attSo.FromItemID), 333// sp.Appearance.GetAttachpoint(attSo.FromItemID),
333 Is.EqualTo((int)AttachmentPoint.LeftHand)); 334// Is.EqualTo((int)AttachmentPoint.LeftHand));
334 335
335 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); 336 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(sp.UUID, attSo.FromItemID);
336 Assert.That(attachmentItem, Is.Not.Null); 337 Assert.That(attachmentItem, Is.Not.Null);
337 Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name)); 338 Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name));
338 339
@@ -372,7 +373,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
372 sp2.AbsolutePosition = new Vector3(0, 0, 0); 373 sp2.AbsolutePosition = new Vector3(0, 0, 0);
373 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); 374 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
374 375
375 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false); 376 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false);
376 377
377 Assert.That(sp.HasAttachments(), Is.False); 378 Assert.That(sp.HasAttachments(), Is.False);
378 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 379 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
@@ -410,8 +411,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
410 Assert.IsFalse(attSo.Backup); 411 Assert.IsFalse(attSo.Backup);
411 412
412 // Check appearance status 413 // Check appearance status
413 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); 414// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
414 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); 415// Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
415 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 416 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
416 417
417 // Check events 418 // Check events
@@ -435,8 +436,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
435 Assert.That(attSo.IsTemporary, Is.False); 436 Assert.That(attSo.IsTemporary, Is.False);
436 437
437 // Check appearance status 438 // Check appearance status
438 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); 439// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
439 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); 440// Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
440 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 441 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
441 442
442 // Check events 443 // Check events
@@ -474,8 +475,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
474 Assert.That(attSo.IsAttachment); 475 Assert.That(attSo.IsAttachment);
475 476
476 // Check appearance status 477 // Check appearance status
477 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); 478// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
478 Assert.That(sp.Appearance.GetAttachpoint(attItem1.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); 479// Assert.That(sp.Appearance.GetAttachpoint(attItem1.ID), Is.EqualTo((int)AttachmentPoint.LeftHand));
479 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 480 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
480 481
481 // Check events 482 // Check events
@@ -484,7 +485,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
484 485
485 // Test wearing a second attachment at the same position 486 // Test wearing a second attachment at the same position
486 // Until multiple attachments at one point is implemented, this will remove the first attachment 487 // Until multiple attachments at one point is implemented, this will remove the first attachment
487 // This test relies on both attachments having the same default attachment point (in this case LeftHand 488 // This test relies on both attachments having the same default attachment point (in this case LeftHand
488 // since none other has been set). 489 // since none other has been set).
489 { 490 {
490 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default); 491 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default);
@@ -499,8 +500,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
499 Assert.That(attSo.IsAttachment); 500 Assert.That(attSo.IsAttachment);
500 501
501 // Check appearance status 502 // Check appearance status
502 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); 503// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
503 Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); 504// Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand));
504 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 505 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
505 506
506 // Check events 507 // Check events
@@ -521,8 +522,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
521 Assert.That(attSo.IsAttachment); 522 Assert.That(attSo.IsAttachment);
522 523
523 // Check appearance status 524 // Check appearance status
524 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); 525// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
525 Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); 526// Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand));
526 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 527 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
527 528
528 // Check events 529 // Check events
@@ -556,6 +557,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
556 // In the future, we need to be able to do this programatically more predicably. 557 // In the future, we need to be able to do this programatically more predicably.
557 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 558 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
558 559
560 m_chatEvent.Reset();
559 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 561 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest);
560 562
561 m_chatEvent.WaitOne(60000); 563 m_chatEvent.WaitOne(60000);
@@ -596,10 +598,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
596 Assert.That(attachments.Count, Is.EqualTo(0)); 598 Assert.That(attachments.Count, Is.EqualTo(0));
597 599
598 // Check appearance status 600 // Check appearance status
599 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(0)); 601// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(0));
600 602
601 // Check item status 603 // Check item status
602 Assert.That(scene.InventoryService.GetItem(new InventoryItemBase(attItem.ID)), Is.Null); 604 Assert.That(scene.InventoryService.GetItem(sp.UUID, attItem.ID), Is.Null);
603 605
604 // Check object in scene 606 // Check object in scene
605 SceneObjectGroup soInScene = scene.GetSceneObjectGroup("att"); 607 SceneObjectGroup soInScene = scene.GetSceneObjectGroup("att");
@@ -634,7 +636,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
634 Assert.That(attachments.Count, Is.EqualTo(0)); 636 Assert.That(attachments.Count, Is.EqualTo(0));
635 637
636 // Check item status 638 // Check item status
637 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); 639// Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0));
638 640
639 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0)); 641 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0));
640 642
@@ -669,15 +671,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
669 // In the future, we need to be able to do this programatically more predicably. 671 // In the future, we need to be able to do this programatically more predicably.
670 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 672 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
671 673
674 m_chatEvent.Reset();
672 SceneObjectGroup rezzedSo 675 SceneObjectGroup rezzedSo
673 = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 676 = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
674 677
675 // Wait for chat to signal rezzed script has been started. 678 // Wait for chat to signal rezzed script has been started.
676 m_chatEvent.WaitOne(60000); 679 m_chatEvent.WaitOne(60000);
677 680
678 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, rezzedSo); 681 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, rezzedSo);
679 682
680 InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem); 683 InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem.Owner, userItem.ID);
681 AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString()); 684 AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString());
682 685
683 // TODO: It would probably be better here to check script state via the saving and retrieval of state 686 // TODO: It would probably be better here to check script state via the saving and retrieval of state
@@ -689,7 +692,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
689 Assert.That(scriptStateNodes.Count, Is.EqualTo(1)); 692 Assert.That(scriptStateNodes.Count, Is.EqualTo(1));
690 693
691 // Re-rez the attachment to check script running state 694 // Re-rez the attachment to check script running state
692 SceneObjectGroup reRezzedSo = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 695 SceneObjectGroup reRezzedSo = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
693 696
694 // Wait for chat to signal rezzed script has been started. 697 // Wait for chat to signal rezzed script has been started.
695 m_chatEvent.WaitOne(60000); 698 m_chatEvent.WaitOne(60000);
@@ -719,13 +722,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
719 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); 722 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
720 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); 723 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
721 724
722 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; 725 UUID rezzedAttID = presence.GetAttachments()[0].UUID;
723 726
724 m_numberOfAttachEventsFired = 0; 727 m_numberOfAttachEventsFired = 0;
725 scene.CloseAgent(presence.UUID, false); 728 scene.CloseAgent(presence.UUID, false);
726 729
727 // Check that we can't retrieve this attachment from the scene. 730 // Check that we can't retrieve this attachment from the scene.
728 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); 731 Assert.That(scene.GetSceneObjectGroup(rezzedAttID), Is.Null);
729 732
730 // Check events 733 // Check events
731 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); 734 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
@@ -802,7 +805,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
802 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); 805 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
803 } 806 }
804 807
805/* 808
806 [Test] 809 [Test]
807 public void TestSameSimulatorNeighbouringRegionsTeleportV1() 810 public void TestSameSimulatorNeighbouringRegionsTeleportV1()
808 { 811 {
@@ -842,7 +845,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
842 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule()); 845 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule());
843 846
844 // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour 847 // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour
845 lscm.ServiceVersion = 0.1f; 848 //lscm.ServiceVersion = 0.1f;
846 849
847 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1); 850 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1);
848 851
@@ -910,7 +913,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
910 // Check events 913 // Check events
911 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); 914 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
912 } 915 }
913*/ 916
914 917
915 [Test] 918 [Test]
916 public void TestSameSimulatorNeighbouringRegionsTeleportV2() 919 public void TestSameSimulatorNeighbouringRegionsTeleportV2()
@@ -972,8 +975,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
972 // Both these operations will occur on different threads and will wait for each other. 975 // Both these operations will occur on different threads and will wait for each other.
973 // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1 976 // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1
974 // test protocol, where we are trying to avoid unpredictable async operations in regression tests. 977 // test protocol, where we are trying to avoid unpredictable async operations in regression tests.
975 tc.OnTestClientSendRegionTeleport 978 tc.OnTestClientSendRegionTeleport
976 += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL) 979 += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL)
977 => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null); 980 => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null);
978 981
979 m_numberOfAttachEventsFired = 0; 982 m_numberOfAttachEventsFired = 0;
@@ -1023,4 +1026,5 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
1023 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); 1026 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
1024 } 1027 }
1025 } 1028 }
1029*/
1026} 1030}
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index cfb082b..4abac43 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -75,7 +75,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
75 m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime))); 75 m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime)));
76 m_sendtime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime))); 76 m_sendtime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime)));
77 m_reusetextures = appearanceConfig.GetBoolean("ReuseTextures",m_reusetextures); 77 m_reusetextures = appearanceConfig.GetBoolean("ReuseTextures",m_reusetextures);
78 78
79 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime); 79 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime);
80 } 80 }
81 81
@@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
166 } 166 }
167 167
168 /// <summary> 168 /// <summary>
169 /// Set appearance data (texture asset IDs and slider settings) 169 /// Set appearance data (texture asset IDs and slider settings)
170 /// </summary> 170 /// </summary>
171 /// <param name="sp"></param> 171 /// <param name="sp"></param>
172 /// <param name="texture"></param> 172 /// <param name="texture"></param>
@@ -188,29 +188,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
188 // Process the visual params, this may change height as well 188 // Process the visual params, this may change height as well
189 if (visualParams != null) 189 if (visualParams != null)
190 { 190 {
191 // string[] visualParamsStrings = new string[visualParams.Length];
192 // for (int i = 0; i < visualParams.Length; i++)
193 // visualParamsStrings[i] = visualParams[i].ToString();
194 // m_log.DebugFormat(
195 // "[AVFACTORY]: Setting visual params for {0} to {1}",
196 // client.Name, string.Join(", ", visualParamsStrings));
197/*
198 float oldHeight = sp.Appearance.AvatarHeight;
199 changed = sp.Appearance.SetVisualParams(visualParams);
200
201 if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0)
202 ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight);
203 */
204// float oldoff = sp.Appearance.AvatarFeetOffset;
205// Vector3 oldbox = sp.Appearance.AvatarBoxSize;
206 changed = sp.Appearance.SetVisualParams(visualParams); 191 changed = sp.Appearance.SetVisualParams(visualParams);
207// float off = sp.Appearance.AvatarFeetOffset;
208// Vector3 box = sp.Appearance.AvatarBoxSize;
209// if(oldoff != off || oldbox != box)
210// ((ScenePresence)sp).SetSize(box,off);
211
212 } 192 }
213 193
214 // Process the baked texture array 194 // Process the baked texture array
215 if (textureEntry != null) 195 if (textureEntry != null)
216 { 196 {
@@ -222,9 +202,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
222 202
223// WriteBakedTexturesReport(sp, m_log.DebugFormat); 203// WriteBakedTexturesReport(sp, m_log.DebugFormat);
224 204
225 // If bake textures are missing and this is not an NPC, request a rebake from client 205 UpdateBakedTextureCache(sp, cacheItems);
226 if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc))
227 RequestRebake(sp, true);
228 206
229 // This appears to be set only in the final stage of the appearance 207 // This appears to be set only in the final stage of the appearance
230 // update transaction. In theory, we should be able to do an immediate 208 // update transaction. In theory, we should be able to do an immediate
@@ -251,7 +229,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
251 private void SendAppearance(ScenePresence sp) 229 private void SendAppearance(ScenePresence sp)
252 { 230 {
253 // Send the appearance to everyone in the scene 231 // Send the appearance to everyone in the scene
254 sp.SendAppearanceToAllOtherClients(); 232 sp.SendAppearanceToAllOtherAgents();
255 233
256 // Send animations back to the avatar as well 234 // Send animations back to the avatar as well
257 sp.Animator.SendAnimPack(); 235 sp.Animator.SendAnimPack();
@@ -289,7 +267,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
289 WearableCacheItem[] items = sp.Appearance.WearableCacheItems; 267 WearableCacheItem[] items = sp.Appearance.WearableCacheItems;
290 //foreach (WearableCacheItem item in items) 268 //foreach (WearableCacheItem item in items)
291 //{ 269 //{
292 270
293 //} 271 //}
294 return items; 272 return items;
295 } 273 }
@@ -310,23 +288,25 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
310 if (bakedTextures.Count == 0) 288 if (bakedTextures.Count == 0)
311 return false; 289 return false;
312 290
291 IAssetCache cache = sp.Scene.RequestModuleInterface<IAssetCache>();
292 if(cache == null)
293 return true; // no baked local caching so nothing to do
294
313 foreach (BakeType bakeType in bakedTextures.Keys) 295 foreach (BakeType bakeType in bakedTextures.Keys)
314 { 296 {
315 Primitive.TextureEntryFace bakedTextureFace = bakedTextures[bakeType]; 297 Primitive.TextureEntryFace bakedTextureFace = bakedTextures[bakeType];
316 298
317 if (bakedTextureFace == null) 299 if (bakedTextureFace == null)
318 {
319 // This can happen legitimately, since some baked textures might not exist
320 //m_log.WarnFormat(
321 // "[AV FACTORY]: No texture ID set for {0} for {1} in {2} not found when trying to save permanently",
322 // bakeType, sp.Name, m_scene.RegionInfo.RegionName);
323 continue; 300 continue;
324 }
325 301
326 AssetBase asset = m_scene.AssetService.Get(bakedTextureFace.TextureID.ToString()); 302 AssetBase asset;
303 cache.Get(bakedTextureFace.TextureID.ToString(), out asset);
327 304
328 if (asset != null) 305 if (asset != null && asset.Local)
329 { 306 {
307 // cache does not update asset contents
308 cache.Expire(bakedTextureFace.TextureID.ToString());
309
330 // Replace an HG ID with the simple asset ID so that we can persist textures for foreign HG avatars 310 // Replace an HG ID with the simple asset ID so that we can persist textures for foreign HG avatars
331 asset.ID = asset.FullID.ToString(); 311 asset.ID = asset.FullID.ToString();
332 312
@@ -334,7 +314,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
334 asset.Local = false; 314 asset.Local = false;
335 m_scene.AssetService.Store(asset); 315 m_scene.AssetService.Store(asset);
336 } 316 }
337 else 317
318 if (asset == null)
338 { 319 {
339 m_log.WarnFormat( 320 m_log.WarnFormat(
340 "[AV FACTORY]: Baked texture id {0} not found for bake {1} for avatar {2} in {3} when trying to save permanently", 321 "[AV FACTORY]: Baked texture id {0} not found for bake {1} for avatar {2} in {3} when trying to save permanently",
@@ -377,116 +358,366 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
377 } 358 }
378 } 359 }
379 360
380 public bool ValidateBakedTextureCache(IScenePresence sp) 361 // called on textures update
362 public bool UpdateBakedTextureCache(IScenePresence sp, WearableCacheItem[] cacheItems)
381 { 363 {
382 bool defonly = true; // are we only using default textures 364 if(cacheItems == null)
383 IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); 365 return false;
384 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); 366
385 WearableCacheItem[] wearableCache = null; 367 // npcs dont have baked cache
386 368 if (((ScenePresence)sp).IsNPC)
387 // Cache wearable data for teleport. 369 return true;
388 // Only makes sense if there's a bake module and a cache module 370
389 if (bakedModule != null && cache != null) 371 // uploaded baked textures will be in assets local cache
372 IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
373 IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
374
375 int validDirtyBakes = 0;
376 int hits = 0;
377
378 // our main cacheIDs mapper is p.Appearance.WearableCacheItems
379 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
380
381 if (wearableCache == null)
382 {
383 wearableCache = WearableCacheItem.GetDefaultCacheItem();
384 }
385
386 List<UUID> missing = new List<UUID>();
387
388 bool haveSkirt = (wearableCache[19].TextureID != UUID.Zero);
389 bool haveNewSkirt = false;
390
391 // Process received baked textures
392 for (int i = 0; i < cacheItems.Length; i++)
390 { 393 {
391 try 394 int idx = (int)cacheItems[i].TextureIndex;
395 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
396
397 // No face
398 if (face == null)
392 { 399 {
393 wearableCache = bakedModule.Get(sp.UUID); 400 // for some reason viewer is cleaning this
401 if(idx != 19) // skirt is optional
402 {
403 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx);
404 sp.Appearance.Texture.FaceTextures[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
405 }
406 wearableCache[idx].CacheId = UUID.Zero;
407 wearableCache[idx].TextureID = UUID.Zero;
408 wearableCache[idx].TextureAsset = null;
409 continue;
394 } 410 }
395 catch (Exception) 411 else
396 { 412 {
413 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
414 {
415 wearableCache[idx].CacheId = UUID.Zero;
416 wearableCache[idx].TextureID = UUID.Zero;
417 wearableCache[idx].TextureAsset = null;
418 continue;
419 }
397 420
398 } 421 if(idx == 19)
399 if (wearableCache != null) 422 haveNewSkirt = true;
400 { 423/*
401 for (int i = 0; i < wearableCache.Length; i++) 424 if (face.TextureID == wearableCache[idx].TextureID && m_BakedTextureModule != null)
402 { 425 {
403 cache.Cache(wearableCache[i].TextureAsset); 426 if (wearableCache[idx].CacheId != cacheItems[i].CacheId)
427 {
428 wearableCache[idx].CacheId = cacheItems[i].CacheId;
429 validDirtyBakes++;
430
431 //assuming this can only happen if asset is in cache
432 }
433 hits++;
434 continue;
435 }
436*/
437 wearableCache[idx].TextureAsset = null;
438 if (cache != null)
439 {
440 AssetBase asb = null;
441 cache.Get(face.TextureID.ToString(), out asb);
442 wearableCache[idx].TextureAsset = asb;
443 }
444
445 if (wearableCache[idx].TextureAsset != null)
446 {
447 if ( wearableCache[idx].TextureID != face.TextureID ||
448 wearableCache[idx].CacheId != cacheItems[i].CacheId)
449 validDirtyBakes++;
450
451 wearableCache[idx].TextureID = face.TextureID;
452 wearableCache[idx].CacheId = cacheItems[i].CacheId;
453 hits++;
454 }
455 else
456 {
457 wearableCache[idx].CacheId = UUID.Zero;
458 wearableCache[idx].TextureID = UUID.Zero;
459 wearableCache[idx].TextureAsset = null;
460 missing.Add(face.TextureID);
461 continue;
404 } 462 }
405 } 463 }
406 } 464 }
407 /* 465
408 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); 466 // handle optional skirt case
409 if (invService.GetRootFolder(userID) != null) 467 if(!haveNewSkirt && haveSkirt)
468 {
469 wearableCache[19].CacheId = UUID.Zero;
470 wearableCache[19].TextureID = UUID.Zero;
471 wearableCache[19].TextureAsset = null;
472 validDirtyBakes++;
473 }
474
475 sp.Appearance.WearableCacheItems = wearableCache;
476
477 if (missing.Count > 0)
410 { 478 {
411 WearableCacheItem[] wearableCache = null; 479 foreach (UUID id in missing)
412 if (bakedModule != null) 480 sp.ControllingClient.SendRebakeAvatarTextures(id);
481 }
482
483 if (validDirtyBakes > 0 && hits == cacheItems.Length)
484 {
485 // if we got a full set of baked textures save all in BakedTextureModule
486 if (m_BakedTextureModule != null)
413 { 487 {
414 try 488 m_log.DebugFormat("[UpdateBakedCache] Uploading to Bakes Server: cache hits: {0} changed entries: {1} rebakes {2}",
489 hits.ToString(), validDirtyBakes.ToString(), missing.Count);
490
491 m_BakedTextureModule.Store(sp.UUID, wearableCache);
492 }
493 }
494 else
495 m_log.DebugFormat("[UpdateBakedCache] cache hits: {0} changed entries: {1} rebakes {2}",
496 hits.ToString(), validDirtyBakes.ToString(), missing.Count);
497
498 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
499 {
500 int j = AvatarAppearance.BAKE_INDICES[iter];
501 sp.Appearance.WearableCacheItems[j].TextureAsset = null;
502// m_log.Debug("[UpdateBCache] {" + iter + "/" +
503// sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" +
504// sp.Appearance.WearableCacheItems[j].CacheId + ", t-" +
505// sp.Appearance.WearableCacheItems[j].TextureID);
506 }
507
508 return (hits == cacheItems.Length);
509 }
510
511 // called when we get a new root avatar
512 public bool ValidateBakedTextureCache(IScenePresence sp)
513 {
514 int hits = 0;
515
516 if (((ScenePresence)sp).IsNPC)
517 return true;
518
519 lock (m_setAppearanceLock)
520 {
521 IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
522 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
523 WearableCacheItem[] bakedModuleCache = null;
524
525 if (cache == null)
526 return false;
527
528 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
529
530 // big debug
531 //m_log.DebugFormat("[AVFACTORY]: ValidateBakedTextureCache start for {0} {1}", sp.Name, sp.UUID);
532/*
533 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
534 {
535 int j = AvatarAppearance.BAKE_INDICES[iter];
536 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[j];
537 if (wearableCache == null)
538 {
539 if (face != null)
540 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t- " + face.TextureID);
541 else
542 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t- No texture");
543 }
544 else
545 {
546 if (face != null)
547 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " ft- " + face.TextureID +
548 "}: cc-" +
549 wearableCache[j].CacheId + ", ct-" +
550 wearableCache[j].TextureID
551 );
552 else
553 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t - No texture" +
554 "}: cc-" +
555 wearableCache[j].CacheId + ", ct-" +
556 wearableCache[j].TextureID
557 );
558 }
559 }
560*/
561
562 bool wearableCacheValid = false;
563 if (wearableCache == null)
564 {
565 wearableCache = WearableCacheItem.GetDefaultCacheItem();
566 }
567 else
568 {
569 // we may have received a full cache
570 // check same coerence and store
571 wearableCacheValid = true;
572 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
415 { 573 {
416 wearableCache = bakedModule.Get(userID); 574 int idx = AvatarAppearance.BAKE_INDICES[i];
417 appearance.WearableCacheItems = wearableCache; 575 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
418 appearance.WearableCacheItemsDirty = false; 576 if (face != null)
419 foreach (WearableCacheItem item in wearableCache)
420 { 577 {
421 appearance.Texture.FaceTextures[item.TextureIndex].TextureID = item.TextureID; 578 if (face.TextureID == wearableCache[idx].TextureID &&
579 face.TextureID != UUID.Zero)
580 {
581 if (wearableCache[idx].TextureAsset != null)
582 {
583 hits++;
584 wearableCache[idx].TextureAsset.Temporary = true;
585 wearableCache[idx].TextureAsset.Local = true;
586 cache.Cache(wearableCache[idx].TextureAsset);
587 wearableCache[idx].TextureAsset = null;
588 continue;
589 }
590
591 if (cache.Check((wearableCache[idx].TextureID).ToString()))
592 {
593 hits++;
594 continue;
595 }
596 }
597 wearableCacheValid = false;
422 } 598 }
423 } 599 }
424 catch (Exception) 600
601 wearableCacheValid = (wearableCacheValid && (hits >= AvatarAppearance.BAKE_INDICES.Length - 1));
602 if (wearableCacheValid)
425 { 603 {
426 604 //m_log.Debug("[ValidateBakedCache] have valid local cache");
427 } 605 }
606 else
607 wearableCache[19].TextureAsset = null; // clear optional skirt
428 } 608 }
429 */
430 609
431 // Process the texture entry 610 bool checkExternal = false;
432 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
433 {
434 int idx = AvatarAppearance.BAKE_INDICES[i];
435 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
436 611
437 // No face, so lets check our baked service cache, teleport or login. 612 if (!wearableCacheValid)
438 if (face == null)
439 { 613 {
440 if (wearableCache != null) 614 hits = 0;
615 // only use external bake module on login condition check
616// ScenePresence ssp = null;
617// if (sp is ScenePresence)
441 { 618 {
442 // If we find the an appearance item, set it as the textureentry and the face 619// ssp = (ScenePresence)sp;
443 WearableCacheItem searchitem = WearableCacheItem.SearchTextureIndex((uint) idx, wearableCache); 620// checkExternal = (((uint)ssp.TeleportFlags & (uint)TeleportFlags.ViaLogin) != 0) &&
444 if (searchitem != null) 621// bakedModule != null;
445 { 622
446 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx); 623 // or do it anytime we dont have the cache
447 sp.Appearance.Texture.FaceTextures[idx].TextureID = searchitem.TextureID; 624 checkExternal = bakedModule != null;
448 face = sp.Appearance.Texture.FaceTextures[idx]; 625 }
449 } 626 }
450 else 627
628 if (checkExternal)
629 {
630 bool gotbacked = false;
631
632 m_log.Debug("[ValidateBakedCache] local cache invalid, checking bakedModule");
633 try
634 {
635 bakedModuleCache = bakedModule.Get(sp.UUID);
636 }
637 catch (Exception e)
638 {
639 m_log.ErrorFormat(e.ToString());
640 bakedModuleCache = null;
641 }
642
643 if (bakedModuleCache != null)
644 {
645 //m_log.Debug("[ValidateBakedCache] got bakedModule " + bakedModuleCache.Length + " cached textures");
646
647 for (int i = 0; i < bakedModuleCache.Length; i++)
451 { 648 {
452 // if there is no texture entry and no baked cache, skip it 649 int j = (int)bakedModuleCache[i].TextureIndex;
453 continue; 650
651 if (bakedModuleCache[i].TextureAsset != null)
652 {
653 wearableCache[j].TextureID = bakedModuleCache[i].TextureID;
654 wearableCache[j].CacheId = bakedModuleCache[i].CacheId;
655 wearableCache[j].TextureAsset = bakedModuleCache[i].TextureAsset;
656 bakedModuleCache[i].TextureAsset.Temporary = true;
657 bakedModuleCache[i].TextureAsset.Local = true;
658 cache.Cache(bakedModuleCache[i].TextureAsset);
659 }
454 } 660 }
661 gotbacked = true;
455 } 662 }
456 else 663
664 if (gotbacked)
457 { 665 {
458 //No texture entry face and no cache. Skip this face. 666 // force the ones we got
459 continue; 667 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
668 {
669 int idx = AvatarAppearance.BAKE_INDICES[i];
670 if(wearableCache[idx].TextureAsset == null)
671 {
672 if(idx == 19)
673 {
674 sp.Appearance.Texture.FaceTextures[idx] = null;
675 hits++;
676 }
677 continue;
678 }
679
680 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
681
682 if (face == null)
683 {
684 face = sp.Appearance.Texture.CreateFace((uint)idx);
685 sp.Appearance.Texture.FaceTextures[idx] = face;
686 }
687
688 face.TextureID = wearableCache[idx].TextureID;
689 hits++;
690 wearableCache[idx].TextureAsset = null;
691 }
460 } 692 }
461 } 693 }
462
463// m_log.DebugFormat(
464// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
465// face.TextureID, idx, client.Name, client.AgentId);
466 694
467 // if the texture is one of the "defaults" then skip it 695 sp.Appearance.WearableCacheItems = wearableCache;
468 // this should probably be more intelligent (skirt texture doesnt matter
469 // if the avatar isnt wearing a skirt) but if any of the main baked
470 // textures is default then the rest should be as well
471 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
472 continue;
473
474 defonly = false; // found a non-default texture reference
475 696
476 if (m_scene.AssetService.Get(face.TextureID.ToString()) == null)
477 return false;
478 } 697 }
479 698
480// m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); 699 // debug
481 700 //m_log.DebugFormat("[ValidateBakedCache]: Completed texture check for {0} {1} with {2} hits", sp.Name, sp.UUID, hits);
482 // If we only found default textures, then the appearance is not cached 701/*
483 return (defonly ? false : true); 702 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
703 {
704 int j = AvatarAppearance.BAKE_INDICES[iter];
705 m_log.Debug("[ValidateBakedCache] {" + iter + "/" +
706 sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" +
707 sp.Appearance.WearableCacheItems[j].CacheId + ", t-" +
708 sp.Appearance.WearableCacheItems[j].TextureID);
709 }
710*/
711 return (hits >= AvatarAppearance.BAKE_INDICES.Length - 1); // skirt is optional
484 } 712 }
485 713
486 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) 714 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly)
487 { 715 {
716 if (((ScenePresence)sp).IsNPC)
717 return 0;
718
488 int texturesRebaked = 0; 719 int texturesRebaked = 0;
489// IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); 720 IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
490 721
491 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) 722 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
492 { 723 {
@@ -497,31 +728,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
497 if (face == null) 728 if (face == null)
498 continue; 729 continue;
499 730
500// m_log.DebugFormat(
501// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
502// face.TextureID, idx, client.Name, client.AgentId);
503
504 // if the texture is one of the "defaults" then skip it
505 // this should probably be more intelligent (skirt texture doesnt matter
506 // if the avatar isnt wearing a skirt) but if any of the main baked
507 // textures is default then the rest should be as well
508 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE) 731 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
509 continue; 732 continue;
510 733
511 if (missingTexturesOnly) 734 if (missingTexturesOnly)
512 { 735 {
513 if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) 736 if (cache != null && cache.Check(face.TextureID.ToString()))
514 { 737 {
515 continue; 738 continue;
516 } 739 }
517 else 740 else
518 { 741 {
519 // On inter-simulator teleports, this occurs if baked textures are not being stored by the
520 // grid asset service (which means that they are not available to the new region and so have
521 // to be re-requested from the client).
522 //
523 // The only available core OpenSimulator behaviour right now
524 // is not to store these textures, temporarily or otherwise.
525 m_log.DebugFormat( 742 m_log.DebugFormat(
526 "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", 743 "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.",
527 face.TextureID, idx, sp.Name); 744 face.TextureID, idx, sp.Name);
@@ -605,7 +822,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
605 foreach (KeyValuePair<UUID, long> kvp in saves) 822 foreach (KeyValuePair<UUID, long> kvp in saves)
606 { 823 {
607 // We have to load the key and value into local parameters to avoid a race condition if we loop 824 // We have to load the key and value into local parameters to avoid a race condition if we loop
608 // around and load kvp with a different value before FireAndForget has launched its thread. 825 // around and load kvp with a different value before FireAndForget has launched its thread.
609 UUID avatarID = kvp.Key; 826 UUID avatarID = kvp.Key;
610 long sendTime = kvp.Value; 827 long sendTime = kvp.Value;
611 828
@@ -658,13 +875,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
658 875
659 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); 876 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
660 877
661 // Trigger this here because it's the final step in the set/queue/save process for appearance setting. 878 // Trigger this here because it's the final step in the set/queue/save process for appearance setting.
662 // Everything has been updated and stored. Ensures bakes have been persisted (if option is set to persist bakes). 879 // Everything has been updated and stored. Ensures bakes have been persisted (if option is set to persist bakes).
663 m_scene.EventManager.TriggerAvatarAppearanceChanged(sp); 880 m_scene.EventManager.TriggerAvatarAppearanceChanged(sp);
664 } 881 }
665 882
666 /// <summary> 883 /// <summary>
667 /// For a given set of appearance items, check whether the items are valid and add their asset IDs to 884 /// For a given set of appearance items, check whether the items are valid and add their asset IDs to
668 /// appearance data. 885 /// appearance data.
669 /// </summary> 886 /// </summary>
670 /// <param name='userID'></param> 887 /// <param name='userID'></param>
@@ -675,25 +892,27 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
675 892
676 if (invService.GetRootFolder(userID) != null) 893 if (invService.GetRootFolder(userID) != null)
677 { 894 {
678 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 895 for (int i = 0; i < appearance.Wearables.Length; i++)
679 { 896 {
680 for (int j = 0; j < appearance.Wearables[i].Count; j++) 897 for (int j = 0; j < appearance.Wearables[i].Count; j++)
681 { 898 {
682 if (appearance.Wearables[i][j].ItemID == UUID.Zero) 899 if (appearance.Wearables[i][j].ItemID == UUID.Zero)
683 { 900 {
684 m_log.WarnFormat( 901 m_log.WarnFormat(
685 "[AVFACTORY]: Wearable item {0}:{1} for user {2} unexpectedly UUID.Zero. Ignoring.", 902 "[AVFACTORY]: Wearable item {0}:{1} for user {2} unexpectedly UUID.Zero. Ignoring.",
686 i, j, userID); 903 i, j, userID);
687 904
688 continue; 905 continue;
689 } 906 }
690 907
691 // Ignore ruth's assets 908 // Ignore ruth's assets
692 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) 909 if (i < AvatarWearable.DefaultWearables.Length)
693 continue; 910 {
911 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID)
912 continue;
913 }
694 914
695 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); 915 InventoryItemBase baseItem = invService.GetItem(userID, appearance.Wearables[i][j].ItemID);
696 baseItem = invService.GetItem(baseItem);
697 916
698 if (baseItem != null) 917 if (baseItem != null)
699 { 918 {
@@ -754,7 +973,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
754// case WearableType.Skin: 973// case WearableType.Skin:
755// //case WearableType.Underpants: 974// //case WearableType.Underpants:
756// TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); 975// TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
757// 976//
758// m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i); 977// m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i);
759// resetwearable = true; 978// resetwearable = true;
760// break; 979// break;
@@ -762,7 +981,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
762// } 981// }
763// continue; 982// continue;
764// } 983// }
765// 984//
766// InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); 985// InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
767// baseItem = invService.GetItem(baseItem); 986// baseItem = invService.GetItem(baseItem);
768// 987//
@@ -789,7 +1008,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
789// 1008//
790// TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); 1009// TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
791// resetwearable = true; 1010// resetwearable = true;
792// 1011//
793// } 1012// }
794// } 1013// }
795// } 1014// }
@@ -798,7 +1017,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
798// if (appearance.Wearables[(int) WearableType.Eyes] == null) 1017// if (appearance.Wearables[(int) WearableType.Eyes] == null)
799// { 1018// {
800// m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes)); 1019// m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes));
801// 1020//
802// TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); 1021// TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance);
803// resetwearable = true; 1022// resetwearable = true;
804// } 1023// }
@@ -902,85 +1121,45 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
902 { 1121 {
903 UUID newInvItem = UUID.Random(); 1122 UUID newInvItem = UUID.Random();
904 InventoryItemBase itembase = new InventoryItemBase(newInvItem, userID) 1123 InventoryItemBase itembase = new InventoryItemBase(newInvItem, userID)
905 { 1124 {
906 AssetID = 1125 AssetID = defaultwearable,
907 defaultwearable, 1126 AssetType = (int)FolderType.BodyPart,
908 AssetType 1127 CreatorId = userID.ToString(),
909 = 1128 //InvType = (int)InventoryType.Wearable,
910 (int) 1129 Description = "Failed Wearable Replacement",
911 FolderType 1130 Folder = invService.GetFolderForType(userID, FolderType.BodyPart).ID,
912 .BodyPart, 1131 Flags = (uint) type, Name = Enum.GetName(typeof (WearableType), type),
913 CreatorId 1132 BasePermissions = (uint) PermissionMask.Copy,
914 = 1133 CurrentPermissions = (uint) PermissionMask.Copy,
915 userID 1134 EveryOnePermissions = (uint) PermissionMask.Copy,
916 .ToString 1135 GroupPermissions = (uint) PermissionMask.Copy,
917 (), 1136 NextPermissions = (uint) PermissionMask.Copy
918 //InvType = (int)InventoryType.Wearable, 1137 };
919
920 Description
921 =
922 "Failed Wearable Replacement",
923 Folder =
924 invService
925 .GetFolderForType
926 (userID,
927 FolderType
928 .BodyPart)
929 .ID,
930 Flags = (uint) type,
931 Name = Enum.GetName(typeof (WearableType), type),
932 BasePermissions = (uint) PermissionMask.Copy,
933 CurrentPermissions = (uint) PermissionMask.Copy,
934 EveryOnePermissions = (uint) PermissionMask.Copy,
935 GroupPermissions = (uint) PermissionMask.Copy,
936 NextPermissions = (uint) PermissionMask.Copy
937 };
938 invService.AddItem(itembase); 1138 invService.AddItem(itembase);
939 UUID LinkInvItem = UUID.Random(); 1139 UUID LinkInvItem = UUID.Random();
940 itembase = new InventoryItemBase(LinkInvItem, userID) 1140 itembase = new InventoryItemBase(LinkInvItem, userID)
941 { 1141 {
942 AssetID = 1142 AssetID = newInvItem,
943 newInvItem, 1143 AssetType = (int)AssetType.Link,
944 AssetType 1144 CreatorId = userID.ToString(),
945 = 1145 InvType = (int) InventoryType.Wearable,
946 (int) 1146 Description = "Failed Wearable Replacement",
947 AssetType 1147 Folder = invService.GetFolderForType(userID, FolderType.CurrentOutfit).ID,
948 .Link, 1148 Flags = (uint) type,
949 CreatorId 1149 Name = Enum.GetName(typeof (WearableType), type),
950 = 1150 BasePermissions = (uint) PermissionMask.Copy,
951 userID 1151 CurrentPermissions = (uint) PermissionMask.Copy,
952 .ToString 1152 EveryOnePermissions = (uint) PermissionMask.Copy,
953 (), 1153 GroupPermissions = (uint) PermissionMask.Copy,
954 InvType = (int) InventoryType.Wearable, 1154 NextPermissions = (uint) PermissionMask.Copy
955 1155 };
956 Description
957 =
958 "Failed Wearable Replacement",
959 Folder =
960 invService
961 .GetFolderForType
962 (userID,
963 FolderType
964 .CurrentOutfit)
965 .ID,
966 Flags = (uint) type,
967 Name = Enum.GetName(typeof (WearableType), type),
968 BasePermissions = (uint) PermissionMask.Copy,
969 CurrentPermissions = (uint) PermissionMask.Copy,
970 EveryOnePermissions = (uint) PermissionMask.Copy,
971 GroupPermissions = (uint) PermissionMask.Copy,
972 NextPermissions = (uint) PermissionMask.Copy
973 };
974 invService.AddItem(itembase); 1156 invService.AddItem(itembase);
975 appearance.Wearables[(int)type] = new AvatarWearable(newInvItem, GetDefaultItem(type)); 1157 appearance.Wearables[(int)type] = new AvatarWearable(newInvItem, GetDefaultItem(type));
976 ScenePresence presence = null; 1158 ScenePresence presence = null;
977 if (m_scene.TryGetScenePresence(userID, out presence)) 1159 if (m_scene.TryGetScenePresence(userID, out presence))
978 { 1160 {
979 m_scene.SendInventoryUpdate(presence.ControllingClient, 1161 m_scene.SendInventoryUpdate(presence.ControllingClient,
980 invService.GetFolderForType(userID, 1162 invService.GetFolderForType(userID, FolderType.CurrentOutfit), false, true);
981 FolderType
982 .CurrentOutfit),
983 false, true);
984 } 1163 }
985 } 1164 }
986 } 1165 }
@@ -1040,7 +1219,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1040 m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId); 1219 m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId);
1041 }, null, "AvatarFactoryModule.OnClientRequestWearables"); 1220 }, null, "AvatarFactoryModule.OnClientRequestWearables");
1042 } 1221 }
1043 1222
1044 /// <summary> 1223 /// <summary>
1045 /// Set appearance data (texture asset IDs and slider settings) received from a client 1224 /// Set appearance data (texture asset IDs and slider settings) received from a client
1046 /// </summary> 1225 /// </summary>
@@ -1080,8 +1259,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1080 1259
1081 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) 1260 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
1082 { 1261 {
1083 if (wear.Type < AvatarWearable.MAX_WEARABLES) 1262 // If the wearable type is larger than the current array, expand it
1084 avatAppearance.Wearables[wear.Type].Add(wear.ItemID, UUID.Zero); 1263 if (avatAppearance.Wearables.Length <= wear.Type)
1264 {
1265 int currentLength = avatAppearance.Wearables.Length;
1266 AvatarWearable[] wears = avatAppearance.Wearables;
1267 Array.Resize(ref wears, wear.Type + 1);
1268 for (int i = currentLength ; i <= wear.Type ; i++)
1269 wears[i] = new AvatarWearable();
1270 avatAppearance.Wearables = wears;
1271 }
1272 avatAppearance.Wearables[wear.Type].Add(wear.ItemID, UUID.Zero);
1085 } 1273 }
1086 1274
1087 avatAppearance.GetAssetsFrom(sp.Appearance); 1275 avatAppearance.GetAssetsFrom(sp.Appearance);
@@ -1117,12 +1305,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1117 { 1305 {
1118 UUID texture = UUID.Zero; 1306 UUID texture = UUID.Zero;
1119 int index = request.BakedTextureIndex; 1307 int index = request.BakedTextureIndex;
1120 1308
1121 if (m_reusetextures) 1309 if (m_reusetextures)
1122 { 1310 {
1123 // this is the most insanely dumb way to do this... however it seems to 1311 // this is the most insanely dumb way to do this... however it seems to
1124 // actually work. if the appearance has been reset because wearables have 1312 // actually work. if the appearance has been reset because wearables have
1125 // changed then the texture entries are zero'd out until the bakes are 1313 // changed then the texture entries are zero'd out until the bakes are
1126 // uploaded. on login, if the textures exist in the cache (eg if you logged 1314 // uploaded. on login, if the textures exist in the cache (eg if you logged
1127 // into the simulator recently, then the appearance will pull those and send 1315 // into the simulator recently, then the appearance will pull those and send
1128 // them back in the packet and you won't have to rebake. if the textures aren't 1316 // them back in the packet and you won't have to rebake. if the textures aren't
@@ -1138,7 +1326,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1138 1326
1139 // m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index); 1327 // m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index);
1140 } 1328 }
1141 1329
1142 CachedTextureResponseArg response = new CachedTextureResponseArg(); 1330 CachedTextureResponseArg response = new CachedTextureResponseArg();
1143 response.BakedTextureIndex = index; 1331 response.BakedTextureIndex = index;
1144 response.BakedTextureID = texture; 1332 response.BakedTextureID = texture;
@@ -1146,7 +1334,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1146 1334
1147 cachedTextureResponse.Add(response); 1335 cachedTextureResponse.Add(response);
1148 } 1336 }
1149 1337
1150 // m_log.WarnFormat("[AVFACTORY]: serial is {0}",serial); 1338 // m_log.WarnFormat("[AVFACTORY]: serial is {0}",serial);
1151 // The serial number appears to be used to match requests and responses 1339 // The serial number appears to be used to match requests and responses
1152 // in the texture transaction. We just send back the serial number 1340 // in the texture transaction. We just send back the serial number
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
index 9513408..33489d1 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
@@ -55,7 +55,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
55 // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly 55 // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly
56 // to the AssetService, which will then store temporary and local assets permanently 56 // to the AssetService, which will then store temporary and local assets permanently
57 CoreAssetCache assetCache = new CoreAssetCache(); 57 CoreAssetCache assetCache = new CoreAssetCache();
58 58
59 AvatarFactoryModule afm = new AvatarFactoryModule(); 59 AvatarFactoryModule afm = new AvatarFactoryModule();
60 TestScene scene = new SceneHelpers(assetCache).SetupScene(); 60 TestScene scene = new SceneHelpers(assetCache).SetupScene();
61 SceneHelpers.SetupSceneModules(scene, afm); 61 SceneHelpers.SetupSceneModules(scene, afm);
@@ -63,7 +63,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
63 63
64 // TODO: Use the actual BunchOfCaps functionality once we slot in the CapabilitiesModules 64 // TODO: Use the actual BunchOfCaps functionality once we slot in the CapabilitiesModules
65 AssetBase bakedTextureAsset; 65 AssetBase bakedTextureAsset;
66 bakedTextureAsset 66 bakedTextureAsset
67 = new AssetBase( 67 = new AssetBase(
68 bakedTextureID, "Test Baked Texture", (sbyte)AssetType.Texture, userId.ToString()); 68 bakedTextureID, "Test Baked Texture", (sbyte)AssetType.Texture, userId.ToString());
69 bakedTextureAsset.Data = new byte[] { 2 }; // Not necessary to have a genuine JPEG2000 asset here yet 69 bakedTextureAsset.Data = new byte[] { 2 }; // Not necessary to have a genuine JPEG2000 asset here yet
@@ -85,7 +85,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
85 // This is the alpha texture 85 // This is the alpha texture
86 eyesFace.TextureID = bakedTextureID; 86 eyesFace.TextureID = bakedTextureID;
87 afm.SetAppearance(sp, bakedTextureEntry, visualParams, null); 87 afm.SetAppearance(sp, bakedTextureEntry, visualParams, null);
88 88
89 Assert.That(rebakeRequestsReceived, Is.EqualTo(0)); 89 Assert.That(rebakeRequestsReceived, Is.EqualTo(0));
90 90
91 AssetBase eyesBake = scene.AssetService.Get(bakedTextureID.ToString()); 91 AssetBase eyesBake = scene.AssetService.Get(bakedTextureID.ToString());
@@ -98,7 +98,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
98 /// Test appearance setting where the baked texture UUID are library alpha textures. 98 /// Test appearance setting where the baked texture UUID are library alpha textures.
99 /// </summary> 99 /// </summary>
100 /// <remarks> 100 /// <remarks>
101 /// For a mesh avatar, it appears these 'baked textures' are used. So these should not trigger a request to 101 /// For a mesh avatar, it appears these 'baked textures' are used. So these should not trigger a request to
102 /// rebake. 102 /// rebake.
103 /// </remarks> 103 /// </remarks>
104 [Test] 104 [Test]
@@ -113,14 +113,14 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
113 // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly 113 // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly
114 // to the AssetService, which will then store temporary and local assets permanently 114 // to the AssetService, which will then store temporary and local assets permanently
115 CoreAssetCache assetCache = new CoreAssetCache(); 115 CoreAssetCache assetCache = new CoreAssetCache();
116 116
117 AvatarFactoryModule afm = new AvatarFactoryModule(); 117 AvatarFactoryModule afm = new AvatarFactoryModule();
118 TestScene scene = new SceneHelpers(assetCache).SetupScene(); 118 TestScene scene = new SceneHelpers(assetCache).SetupScene();
119 SceneHelpers.SetupSceneModules(scene, afm); 119 SceneHelpers.SetupSceneModules(scene, afm);
120 ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId); 120 ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId);
121 121
122 AssetBase libraryAsset; 122 AssetBase libraryAsset;
123 libraryAsset 123 libraryAsset
124 = new AssetBase( 124 = new AssetBase(
125 alphaTextureID, "Default Alpha Layer Texture", (sbyte)AssetType.Texture, userId.ToString()); 125 alphaTextureID, "Default Alpha Layer Texture", (sbyte)AssetType.Texture, userId.ToString());
126 libraryAsset.Data = new byte[] { 2 }; // Not necessary to have a genuine JPEG2000 asset here yet 126 libraryAsset.Data = new byte[] { 2 }; // Not necessary to have a genuine JPEG2000 asset here yet
@@ -142,7 +142,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
142 // This is the alpha texture 142 // This is the alpha texture
143 eyesFace.TextureID = alphaTextureID; 143 eyesFace.TextureID = alphaTextureID;
144 afm.SetAppearance(sp, bakedTextureEntry, visualParams, null); 144 afm.SetAppearance(sp, bakedTextureEntry, visualParams, null);
145 145
146 Assert.That(rebakeRequestsReceived, Is.EqualTo(0)); 146 Assert.That(rebakeRequestsReceived, Is.EqualTo(0));
147 } 147 }
148 148
@@ -158,7 +158,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
158 // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly 158 // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly
159 // to the AssetService, which will then store temporary and local assets permanently 159 // to the AssetService, which will then store temporary and local assets permanently
160 CoreAssetCache assetCache = new CoreAssetCache(); 160 CoreAssetCache assetCache = new CoreAssetCache();
161 161
162 AvatarFactoryModule afm = new AvatarFactoryModule(); 162 AvatarFactoryModule afm = new AvatarFactoryModule();
163 TestScene scene = new SceneHelpers(assetCache).SetupScene(); 163 TestScene scene = new SceneHelpers(assetCache).SetupScene();
164 SceneHelpers.SetupSceneModules(scene, afm); 164 SceneHelpers.SetupSceneModules(scene, afm);
@@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
181 Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); 181 Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex);
182 eyesFace.TextureID = eyesTextureId; 182 eyesFace.TextureID = eyesTextureId;
183 183
184 afm.SetAppearance(sp, bakedTextureEntry, visualParams, null); 184 afm.SetAppearance(sp, bakedTextureEntry, visualParams, new WearableCacheItem[0]);
185 afm.SaveBakedTextures(userId); 185 afm.SaveBakedTextures(userId);
186// Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId); 186// Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId);
187 187
diff --git a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
index 414f06a..61e461a 100644
--- a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
@@ -53,6 +53,7 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
53 private UTF8Encoding enc = new UTF8Encoding(); 53 private UTF8Encoding enc = new UTF8Encoding();
54 private string m_URL = String.Empty; 54 private string m_URL = String.Empty;
55 private static XmlSerializer m_serializer = new XmlSerializer(typeof(AssetBase)); 55 private static XmlSerializer m_serializer = new XmlSerializer(typeof(AssetBase));
56 private static bool m_enabled = false;
56 57
57 private static IServiceAuth m_Auth; 58 private static IServiceAuth m_Auth;
58 59
@@ -63,11 +64,19 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
63 return; 64 return;
64 65
65 m_URL = config.GetString("URL", String.Empty); 66 m_URL = config.GetString("URL", String.Empty);
67 if (m_URL == String.Empty)
68 return;
69
70 m_enabled = true;
71
66 m_Auth = ServiceAuth.Create(configSource, "XBakes"); 72 m_Auth = ServiceAuth.Create(configSource, "XBakes");
67 } 73 }
68 74
69 public void AddRegion(Scene scene) 75 public void AddRegion(Scene scene)
70 { 76 {
77 if (!m_enabled)
78 return;
79
71 // m_log.InfoFormat("[XBakes]: Enabled for region {0}", scene.RegionInfo.RegionName); 80 // m_log.InfoFormat("[XBakes]: Enabled for region {0}", scene.RegionInfo.RegionName);
72 m_Scene = scene; 81 m_Scene = scene;
73 82
@@ -101,8 +110,6 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
101 if (m_URL == String.Empty) 110 if (m_URL == String.Empty)
102 return null; 111 return null;
103 112
104 int size = 0;
105
106 using (RestClient rc = new RestClient(m_URL)) 113 using (RestClient rc = new RestClient(m_URL))
107 { 114 {
108 List<WearableCacheItem> ret = new List<WearableCacheItem>(); 115 List<WearableCacheItem> ret = new List<WearableCacheItem>();
@@ -113,35 +120,42 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
113 120
114 try 121 try
115 { 122 {
116 Stream s = rc.Request(m_Auth); 123 using(Stream s = rc.Request(m_Auth))
117
118 using (XmlTextReader sr = new XmlTextReader(s))
119 { 124 {
120 sr.ReadStartElement("BakedAppearance"); 125 using(XmlTextReader sr = new XmlTextReader(s))
121 while (sr.LocalName == "BakedTexture")
122 { 126 {
123 string sTextureIndex = sr.GetAttribute("TextureIndex"); 127 sr.ProhibitDtd = true;
124 int lTextureIndex = Convert.ToInt32(sTextureIndex); 128
125 string sCacheId = sr.GetAttribute("CacheId"); 129 sr.ReadStartElement("BakedAppearance");
126 UUID lCacheId = UUID.Zero; 130 while(sr.LocalName == "BakedTexture")
127 if (!(UUID.TryParse(sCacheId, out lCacheId)))
128 { 131 {
132 string sTextureIndex = sr.GetAttribute("TextureIndex");
133 int lTextureIndex = Convert.ToInt32(sTextureIndex);
134 string sCacheId = sr.GetAttribute("CacheId");
135 UUID lCacheId = UUID.Zero;
136 if(!(UUID.TryParse(sCacheId,out lCacheId)))
137 {
129 // ?? Nothing here 138 // ?? Nothing here
139 }
140
141 sr.ReadStartElement("BakedTexture");
142 if(sr.Name=="AssetBase")
143 {
144 AssetBase a = (AssetBase)m_serializer.Deserialize(sr);
145 ret.Add(new WearableCacheItem()
146 {
147 CacheId = lCacheId,
148 TextureIndex = (uint)lTextureIndex,
149 TextureAsset = a,
150 TextureID = a.FullID
151 });
152 sr.ReadEndElement();
153 }
130 } 154 }
131 155 m_log.DebugFormat("[XBakes]: read {0} textures for user {1}",ret.Count,id);
132 ++size;
133
134 sr.ReadStartElement("BakedTexture");
135 AssetBase a = (AssetBase)m_serializer.Deserialize(sr);
136 ret.Add(new WearableCacheItem() { CacheId = lCacheId, TextureIndex = (uint)lTextureIndex, TextureAsset = a, TextureID = a.FullID });
137
138 sr.ReadEndElement();
139 } 156 }
140 157 return ret.ToArray();
141 m_log.DebugFormat("[XBakes]: read {0} textures for user {1}", ret.Count, id);
142 } 158 }
143
144 return ret.ToArray();
145 } 159 }
146 catch (XmlException) 160 catch (XmlException)
147 { 161 {
@@ -150,11 +164,20 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
150 } 164 }
151 } 165 }
152 166
167 public void Store(UUID agentId)
168 {
169 }
170
171 public void UpdateMeshAvatar(UUID agentId)
172 {
173 }
174
153 public void Store(UUID agentId, WearableCacheItem[] data) 175 public void Store(UUID agentId, WearableCacheItem[] data)
154 { 176 {
155 if (m_URL == String.Empty) 177 if (m_URL == String.Empty)
156 return; 178 return;
157 179
180 int numberWears = 0;
158 MemoryStream reqStream; 181 MemoryStream reqStream;
159 182
160 using (MemoryStream bakeStream = new MemoryStream()) 183 using (MemoryStream bakeStream = new MemoryStream())
@@ -164,15 +187,16 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
164 187
165 for (int i = 0; i < data.Length; i++) 188 for (int i = 0; i < data.Length; i++)
166 { 189 {
167 if (data[i] != null) 190 if (data[i] != null && data[i].TextureAsset != null)
168 { 191 {
169 bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty); 192 bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty);
170 bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString()); 193 bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString());
171 bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString()); 194 bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString());
172 if (data[i].TextureAsset != null) 195// if (data[i].TextureAsset != null)
173 m_serializer.Serialize(bakeWriter, data[i].TextureAsset); 196 m_serializer.Serialize(bakeWriter, data[i].TextureAsset);
174 197
175 bakeWriter.WriteEndElement(); 198 bakeWriter.WriteEndElement();
199 numberWears++;
176 } 200 }
177 } 201 }
178 202
@@ -182,19 +206,22 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
182 reqStream = new MemoryStream(bakeStream.ToArray()); 206 reqStream = new MemoryStream(bakeStream.ToArray());
183 } 207 }
184 208
185 RestClient rc = new RestClient(m_URL);
186 rc.AddResourcePath("bakes");
187 rc.AddResourcePath(agentId.ToString());
188
189 rc.RequestMethod = "POST";
190
191 Util.FireAndForget( 209 Util.FireAndForget(
192 delegate 210 delegate
193 { 211 {
194 rc.Request(reqStream, m_Auth); 212 using(RestClient rc = new RestClient(m_URL))
195 m_log.DebugFormat("[XBakes]: stored {0} textures for user {1}", data.Length, agentId); 213 {
214 rc.AddResourcePath("bakes");
215 rc.AddResourcePath(agentId.ToString());
216 rc.RequestMethod = "POST";
217
218 rc.Request(reqStream, m_Auth);
219 m_log.DebugFormat("[XBakes]: stored {0} textures for user {1}", numberWears, agentId);
220 }
221 if(reqStream != null)
222 reqStream.Dispose();
196 }, null, "XBakesModule.Store" 223 }, null, "XBakesModule.Store"
197 ); 224 );
198 } 225 }
199 } 226 }
200} \ No newline at end of file 227}
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index f0b1e67..ea90185 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -45,17 +45,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
45 private static readonly ILog m_log = 45 private static readonly ILog m_log =
46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 private const int DEBUG_CHANNEL = 2147483647; 48 protected const int DEBUG_CHANNEL = 2147483647;
49 49
50 private bool m_enabled = true; 50 protected bool m_enabled = true;
51 private int m_saydistance = 20; 51 protected int m_saydistance = 20;
52 private int m_shoutdistance = 100; 52 protected int m_shoutdistance = 100;
53 private int m_whisperdistance = 10; 53 protected int m_whisperdistance = 10;
54 54 protected List<Scene> m_scenes = new List<Scene>();
55 internal object m_syncy = new object(); 55 protected List<string> FreezeCache = new List<string>();
56 56 protected string m_adminPrefix = "";
57 internal IConfig m_config; 57 protected object m_syncy = new object();
58 58 protected IConfig m_config;
59 #region ISharedRegionModule Members 59 #region ISharedRegionModule Members
60 public virtual void Initialise(IConfigSource config) 60 public virtual void Initialise(IConfigSource config)
61 { 61 {
@@ -69,21 +69,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
69 m_enabled = false; 69 m_enabled = false;
70 return; 70 return;
71 } 71 }
72 }
73 72
74 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); 73 m_whisperdistance = m_config.GetInt("whisper_distance", m_whisperdistance);
75 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); 74 m_saydistance = m_config.GetInt("say_distance", m_saydistance);
76 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); 75 m_shoutdistance = m_config.GetInt("shout_distance", m_shoutdistance);
76 m_adminPrefix = m_config.GetString("admin_prefix", "");
77 }
77 } 78 }
78 79
79 public virtual void AddRegion(Scene scene) 80 public virtual void AddRegion(Scene scene)
80 { 81 {
81 if (!m_enabled) 82 if (!m_enabled) return;
82 return;
83 83
84 scene.EventManager.OnNewClient += OnNewClient; 84 lock (m_syncy)
85 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 85 {
86 scene.EventManager.OnChatBroadcast += OnChatBroadcast; 86 if (!m_scenes.Contains(scene))
87 {
88 m_scenes.Add(scene);
89 scene.EventManager.OnNewClient += OnNewClient;
90 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
91 scene.EventManager.OnChatBroadcast += OnChatBroadcast;
92 }
93 }
87 94
88 m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName, 95 m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName,
89 m_whisperdistance, m_saydistance, m_shoutdistance); 96 m_whisperdistance, m_saydistance, m_shoutdistance);
@@ -103,14 +110,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
103 110
104 public virtual void RemoveRegion(Scene scene) 111 public virtual void RemoveRegion(Scene scene)
105 { 112 {
106 if (!m_enabled) 113 if (!m_enabled) return;
107 return;
108 114
109 scene.EventManager.OnNewClient -= OnNewClient; 115 lock (m_syncy)
110 scene.EventManager.OnChatFromWorld -= OnChatFromWorld; 116 {
111 scene.EventManager.OnChatBroadcast -= OnChatBroadcast; 117 if (m_scenes.Contains(scene))
118 {
119 scene.EventManager.OnNewClient -= OnNewClient;
120 scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
121 scene.EventManager.OnChatBroadcast -= OnChatBroadcast;
122 m_scenes.Remove(scene);
123 }
124 }
112 } 125 }
113 126
114 public virtual void Close() 127 public virtual void Close()
115 { 128 {
116 } 129 }
@@ -119,7 +132,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
119 { 132 {
120 } 133 }
121 134
122 public Type ReplaceableInterface 135 public virtual Type ReplaceableInterface
123 { 136 {
124 get { return null; } 137 get { return null; }
125 } 138 }
@@ -137,7 +150,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
137 client.OnChatFromClient += OnChatFromClient; 150 client.OnChatFromClient += OnChatFromClient;
138 } 151 }
139 152
140 protected OSChatMessage FixPositionOfChatMessage(OSChatMessage c) 153 protected virtual OSChatMessage FixPositionOfChatMessage(OSChatMessage c)
141 { 154 {
142 ScenePresence avatar; 155 ScenePresence avatar;
143 Scene scene = (Scene)c.Scene; 156 Scene scene = (Scene)c.Scene;
@@ -165,7 +178,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
165 return; 178 return;
166 } 179 }
167 180
168 DeliverChatToAvatars(ChatSourceType.Agent, c); 181 if (FreezeCache.Contains(c.Sender.AgentId.ToString()))
182 {
183 if (c.Type != ChatTypeEnum.StartTyping || c.Type != ChatTypeEnum.StopTyping)
184 c.Sender.SendAgentAlertMessage("You may not talk as you are frozen.", false);
185 }
186 else
187 {
188 DeliverChatToAvatars(ChatSourceType.Agent, c);
189 }
169 } 190 }
170 191
171 public virtual void OnChatFromWorld(Object sender, OSChatMessage c) 192 public virtual void OnChatFromWorld(Object sender, OSChatMessage c)
@@ -179,34 +200,63 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
179 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) 200 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c)
180 { 201 {
181 string fromName = c.From; 202 string fromName = c.From;
203 string fromNamePrefix = "";
182 UUID fromID = UUID.Zero; 204 UUID fromID = UUID.Zero;
183 UUID ownerID = UUID.Zero; 205 UUID ownerID = UUID.Zero;
184 UUID targetID = c.TargetUUID;
185 string message = c.Message; 206 string message = c.Message;
186 Scene scene = (Scene)c.Scene; 207 Scene scene = c.Scene as Scene;
208 UUID destination = c.Destination;
187 Vector3 fromPos = c.Position; 209 Vector3 fromPos = c.Position;
188 Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0); 210 Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0);
189 211
212 bool checkParcelHide = false;
213 UUID sourceParcelID = UUID.Zero;
214 Vector3 hidePos = fromPos;
215
190 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel; 216 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel;
191 217
192 switch (sourceType) 218 if(!m_scenes.Contains(scene))
193 { 219 {
194 case ChatSourceType.Agent: 220 m_log.WarnFormat("[CHAT]: message from unkown scene {0} ignored",
195 ScenePresence avatar = scene.GetScenePresence(c.Sender.AgentId); 221 scene.RegionInfo.RegionName);
196 fromPos = avatar.AbsolutePosition; 222 return;
197 fromName = avatar.Name; 223 }
198 fromID = c.Sender.AgentId;
199 ownerID = c.Sender.AgentId;
200 224
201 break; 225 switch (sourceType)
226 {
227 case ChatSourceType.Agent:
228 ScenePresence avatar = (scene as Scene).GetScenePresence(c.Sender.AgentId);
229 fromPos = avatar.AbsolutePosition;
230 fromName = avatar.Name;
231 fromID = c.Sender.AgentId;
232 if (avatar.IsViewerUIGod)
233 { // let gods speak to outside or things may get confusing
234 fromNamePrefix = m_adminPrefix;
235 checkParcelHide = false;
236 }
237 else
238 {
239 checkParcelHide = true;
240 }
241 destination = UUID.Zero; // Avatars cant "SayTo"
242 ownerID = c.Sender.AgentId;
202 243
203 case ChatSourceType.Object: 244 hidePos = fromPos;
204 fromID = c.SenderUUID; 245 break;
205 246
206 if (c.SenderObject != null && c.SenderObject is SceneObjectPart) 247 case ChatSourceType.Object:
207 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; 248 fromID = c.SenderUUID;
208 249
209 break; 250 if (c.SenderObject != null && c.SenderObject is SceneObjectPart)
251 {
252 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID;
253 if (((SceneObjectPart)c.SenderObject).ParentGroup.IsAttachment)
254 {
255 checkParcelHide = true;
256 hidePos = ((SceneObjectPart)c.SenderObject).ParentGroup.AbsolutePosition;
257 }
258 }
259 break;
210 } 260 }
211 261
212 // TODO: iterate over message 262 // TODO: iterate over message
@@ -214,43 +264,66 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
214 message = message.Substring(0, 1000); 264 message = message.Substring(0, 1000);
215 265
216// m_log.DebugFormat( 266// m_log.DebugFormat(
217// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}, targetID {5}", 267// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}",
218// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType, targetID); 268// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType);
219 269
220 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 270 HashSet<UUID> receiverIDs = new HashSet<UUID>();
221 271
222 if (targetID == UUID.Zero) 272 if (checkParcelHide)
223 { 273 {
224 // This should use ForEachClient, but clients don't have a position. 274 checkParcelHide = false;
225 // If camera is moved into client, then camera position can be used 275 if (c.Type < ChatTypeEnum.DebugChannel && destination == UUID.Zero)
226 scene.ForEachScenePresence( 276 {
227 delegate(ScenePresence presence) 277 ILandObject srcland = scene.LandChannel.GetLandObject(hidePos.X, hidePos.Y);
278 if (srcland != null && !srcland.LandData.SeeAVs)
228 { 279 {
229 if (TrySendChatMessage( 280 sourceParcelID = srcland.LandData.GlobalID;
230 presence, fromPos, regionPos, fromID, ownerID, fromName, c.Type, message, sourceType, false)) 281 checkParcelHide = true;
231 receiverIDs.Add(presence.UUID);
232 } 282 }
233 );
234 }
235 else
236 {
237 // This is a send to a specific client eg from llRegionSayTo
238 // no need to check distance etc, jand send is as say
239 ScenePresence presence = scene.GetScenePresence(targetID);
240 if (presence != null && !presence.IsChildAgent)
241 {
242 if (TrySendChatMessage(
243 presence, fromPos, regionPos, fromID, ownerID, fromName, ChatTypeEnum.Say, message, sourceType, true))
244 receiverIDs.Add(presence.UUID);
245 } 283 }
246 } 284 }
247 285
286 scene.ForEachScenePresence(
287 delegate(ScenePresence presence)
288 {
289 if (destination != UUID.Zero && presence.UUID != destination)
290 return;
291
292 if(presence.IsChildAgent)
293 {
294 if(checkParcelHide)
295 return;
296 if (TrySendChatMessage(presence, fromPos, regionPos, fromID,
297 ownerID, fromNamePrefix + fromName, c.Type,
298 message, sourceType, (destination != UUID.Zero)))
299 receiverIDs.Add(presence.UUID);
300 return;
301 }
302
303 ILandObject Presencecheck = scene.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
304 if (Presencecheck != null)
305 {
306 if (checkParcelHide)
307 {
308 if (sourceParcelID != Presencecheck.LandData.GlobalID && !presence.IsViewerUIGod)
309 return;
310 }
311 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true)
312 {
313 if (TrySendChatMessage(presence, fromPos, regionPos, fromID,
314 ownerID, fromNamePrefix + fromName, c.Type,
315 message, sourceType, (destination != UUID.Zero)))
316 receiverIDs.Add(presence.UUID);
317 }
318 }
319 });
320
248 scene.EventManager.TriggerOnChatToClients( 321 scene.EventManager.TriggerOnChatToClients(
249 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); 322 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully);
250 } 323 }
251 324
252 static private Vector3 CenterOfRegion = new Vector3(128, 128, 30); 325 static protected Vector3 CenterOfRegion = new Vector3(128, 128, 30);
253 326
254 public virtual void OnChatBroadcast(Object sender, OSChatMessage c) 327 public virtual void OnChatBroadcast(Object sender, OSChatMessage c)
255 { 328 {
256 if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return; 329 if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return;
@@ -268,7 +341,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
268 // broadcast chat works by redistributing every incoming chat 341 // broadcast chat works by redistributing every incoming chat
269 // message to each avatar in the scene. 342 // message to each avatar in the scene.
270 string fromName = c.From; 343 string fromName = c.From;
271 344
272 UUID fromID = UUID.Zero; 345 UUID fromID = UUID.Zero;
273 UUID ownerID = UUID.Zero; 346 UUID ownerID = UUID.Zero;
274 ChatSourceType sourceType = ChatSourceType.Object; 347 ChatSourceType sourceType = ChatSourceType.Object;
@@ -280,35 +353,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
280 ownerID = c.Sender.AgentId; 353 ownerID = c.Sender.AgentId;
281 sourceType = ChatSourceType.Agent; 354 sourceType = ChatSourceType.Agent;
282 } 355 }
283 else if (c.SenderUUID != UUID.Zero) 356 else if (c.SenderUUID != UUID.Zero)
284 { 357 {
285 fromID = c.SenderUUID; 358 fromID = c.SenderUUID;
286 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; 359 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID;
287 } 360 }
288
289 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
290 361
362 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
291 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 363 HashSet<UUID> receiverIDs = new HashSet<UUID>();
292
293 ((Scene)c.Scene).ForEachRootClient(
294 delegate(IClientAPI client)
295 {
296 // don't forward SayOwner chat from objects to
297 // non-owner agents
298 if ((c.Type == ChatTypeEnum.Owner) &&
299 (null != c.SenderObject) &&
300 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
301 return;
302 364
303 client.SendChatMessage( 365 if (c.Scene != null)
304 c.Message, (byte)cType, CenterOfRegion, fromName, fromID, ownerID, 366 {
305 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 367 ((Scene)c.Scene).ForEachRootClient
306 368 (
307 receiverIDs.Add(client.AgentId); 369 delegate(IClientAPI client)
308 }); 370 {
309 371 // don't forward SayOwner chat from objects to
310 (c.Scene as Scene).EventManager.TriggerOnChatToClients( 372 // non-owner agents
311 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); 373 if ((c.Type == ChatTypeEnum.Owner) &&
374 (null != c.SenderObject) &&
375 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
376 return;
377
378 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID,
379 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
380 receiverIDs.Add(client.AgentId);
381 }
382 );
383 (c.Scene as Scene).EventManager.TriggerOnChatToClients(
384 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully);
385 }
312 } 386 }
313 387
314 /// <summary> 388 /// <summary>
@@ -326,7 +400,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
326 /// <param name="type"></param> 400 /// <param name="type"></param>
327 /// <param name="message"></param> 401 /// <param name="message"></param>
328 /// <param name="src"></param> 402 /// <param name="src"></param>
329 /// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a 403 /// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a
330 /// precondition</returns> 404 /// precondition</returns>
331 protected virtual bool TrySendChatMessage( 405 protected virtual bool TrySendChatMessage(
332 ScenePresence presence, Vector3 fromPos, Vector3 regionPos, 406 ScenePresence presence, Vector3 fromPos, Vector3 regionPos,
@@ -356,15 +430,44 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
356 presence.ControllingClient.SendChatMessage( 430 presence.ControllingClient.SendChatMessage(
357 message, (byte) type, fromPos, fromName, 431 message, (byte) type, fromPos, fromName,
358 fromAgentID, ownerID, (byte)src, (byte)ChatAudibleLevel.Fully); 432 fromAgentID, ownerID, (byte)src, (byte)ChatAudibleLevel.Fully);
359 433
360 return true; 434 return true;
361 } 435 }
362 436
437 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
438 public virtual void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
439 {
440 System.Threading.Timer Timer;
441 if (flags == 0)
442 {
443 FreezeCache.Add(target.ToString());
444 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
445 Timer = new System.Threading.Timer(timeCB, target, 30000, 0);
446 Timers.Add(target, Timer);
447 }
448 else
449 {
450 FreezeCache.Remove(target.ToString());
451 Timers.TryGetValue(target, out Timer);
452 Timers.Remove(target);
453 Timer.Dispose();
454 }
455 }
456
457 protected virtual void OnEndParcelFrozen(object avatar)
458 {
459 UUID target = (UUID)avatar;
460 FreezeCache.Remove(target.ToString());
461 System.Threading.Timer Timer;
462 Timers.TryGetValue(target, out Timer);
463 Timers.Remove(target);
464 Timer.Dispose();
465 }
363 #region SimulatorFeaturesRequest 466 #region SimulatorFeaturesRequest
364 467
365 static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange; 468 protected static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange;
366 469
367 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features) 470 protected virtual void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
368 { 471 {
369 OSD extras = new OSDMap(); 472 OSD extras = new OSDMap();
370 if (features.ContainsKey("OpenSimExtras")) 473 if (features.ContainsKey("OpenSimExtras"))
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs
index 3018d94..5457dc3 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs
@@ -41,12 +41,13 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Services.Interfaces; 42using OpenSim.Services.Interfaces;
43using OpenSim.Tests.Common; 43using OpenSim.Tests.Common;
44using System.Threading;
44 45
45namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests 46namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
46{ 47{
47 [TestFixture] 48 [TestFixture]
48 public class ChatModuleTests : OpenSimTestCase 49 public class ChatModuleTests : OpenSimTestCase
49 { 50 {
50 [TestFixtureSetUp] 51 [TestFixtureSetUp]
51 public void FixtureInit() 52 public void FixtureInit()
52 { 53 {
@@ -65,14 +66,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
65 } 66 }
66 67
67 private void SetupNeighbourRegions(TestScene sceneA, TestScene sceneB) 68 private void SetupNeighbourRegions(TestScene sceneA, TestScene sceneB)
68 { 69 {
69 // XXX: HTTP server is not (and should not be) necessary for this test, though it's absence makes the 70 // XXX: HTTP server is not (and should not be) necessary for this test, though it's absence makes the
70 // CapabilitiesModule complain when it can't set up HTTP endpoints. 71 // CapabilitiesModule complain when it can't set up HTTP endpoints.
71 // BaseHttpServer httpServer = new BaseHttpServer(99999); 72 BaseHttpServer httpServer = new BaseHttpServer(99999);
72 // MainServer.AddHttpServer(httpServer); 73 MainServer.AddHttpServer(httpServer);
73 // MainServer.Instance = httpServer; 74 MainServer.Instance = httpServer;
74 75
75 // We need entity transfer modules so that when sp2 logs into the east region, the region calls 76 // We need entity transfer modules so that when sp2 logs into the east region, the region calls
76 // EntityTransferModuleto set up a child agent on the west region. 77 // EntityTransferModuleto set up a child agent on the west region.
77 // XXX: However, this is not an entity transfer so is misleading. 78 // XXX: However, this is not an entity transfer so is misleading.
78 EntityTransferModule etmA = new EntityTransferModule(); 79 EntityTransferModule etmA = new EntityTransferModule();
@@ -86,7 +87,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
86 modulesConfig.Set("SimulationServices", lscm.Name); 87 modulesConfig.Set("SimulationServices", lscm.Name);
87 88
88 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); 89 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
89 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA, new ChatModule()); 90 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA, new ChatModule());
90 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB, new ChatModule()); 91 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB, new ChatModule());
91 } 92 }
92 93
@@ -110,8 +111,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
110 Vector3 sp2Position = new Vector3(250, 128, 20); 111 Vector3 sp2Position = new Vector3(250, 128, 20);
111 112
112 SceneHelpers sh = new SceneHelpers(); 113 SceneHelpers sh = new SceneHelpers();
113 TestScene sceneWest = sh.SetupScene("sceneWest", TestHelpers.ParseTail(0x1), 1000, 1000); 114 TestScene sceneWest = sh.SetupScene("sceneWest", TestHelpers.ParseTail(0x1), 1000, 1000);
114 TestScene sceneEast = sh.SetupScene("sceneEast", TestHelpers.ParseTail(0x2), 1001, 1000); 115 TestScene sceneEast = sh.SetupScene("sceneEast", TestHelpers.ParseTail(0x2), 1001, 1000);
115 116
116 SetupNeighbourRegions(sceneWest, sceneEast); 117 SetupNeighbourRegions(sceneWest, sceneEast);
117 118
@@ -123,12 +124,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
123 // physics is irrelevant to this test. 124 // physics is irrelevant to this test.
124 sp1.Flying = true; 125 sp1.Flying = true;
125 126
126 // When sp1 logs in to sceneEast, it sets up a child agent in sceneWest and informs the sp2 client to 127 // When sp1 logs in to sceneEast, it sets up a child agent in sceneWest and informs the sp2 client to
127 // make the connection. For this test, will simplify this chain by making the connection directly. 128 // make the connection. For this test, will simplify this chain by making the connection directly.
128 ScenePresence sp1Child = SceneHelpers.AddChildScenePresence(sceneWest, sp1Uuid); 129 ScenePresence sp1Child = SceneHelpers.AddChildScenePresence(sceneWest, sp1Uuid);
129 TestClient sp1ChildClient = (TestClient)sp1Child.ControllingClient; 130 TestClient sp1ChildClient = (TestClient)sp1Child.ControllingClient;
130 131
131 sp1.AbsolutePosition = sp1Position; 132 sp1.AbsolutePosition = sp1Position;
132 133
133 ScenePresence sp2 = SceneHelpers.AddScenePresence(sceneWest, sp2Uuid); 134 ScenePresence sp2 = SceneHelpers.AddScenePresence(sceneWest, sp2Uuid);
134 TestClient sp2Client = (TestClient)sp2.ControllingClient; 135 TestClient sp2Client = (TestClient)sp2.ControllingClient;
@@ -137,7 +138,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
137 ScenePresence sp2Child = SceneHelpers.AddChildScenePresence(sceneEast, sp2Uuid); 138 ScenePresence sp2Child = SceneHelpers.AddChildScenePresence(sceneEast, sp2Uuid);
138 TestClient sp2ChildClient = (TestClient)sp2Child.ControllingClient; 139 TestClient sp2ChildClient = (TestClient)sp2Child.ControllingClient;
139 140
140 sp2.AbsolutePosition = sp2Position; 141 sp2.AbsolutePosition = sp2Position;
141 142
142 // We must update the scenes in order to make the root new root agents trigger position updates in their 143 // We must update the scenes in order to make the root new root agents trigger position updates in their
143 // children. 144 // children.
@@ -146,19 +147,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
146 147
147 // Check child positions are correct. 148 // Check child positions are correct.
148 Assert.AreEqual( 149 Assert.AreEqual(
149 new Vector3(sp1Position.X + sceneEast.RegionInfo.RegionSizeX, sp1Position.Y, sp1Position.Z), 150 new Vector3(sp1Position.X + sceneEast.RegionInfo.RegionSizeX, sp1Position.Y, sp1Position.Z),
150 sp1ChildClient.SceneAgent.AbsolutePosition); 151 sp1ChildClient.SceneAgent.AbsolutePosition);
151 152
152 Assert.AreEqual( 153 Assert.AreEqual(
153 new Vector3(sp2Position.X - sceneWest.RegionInfo.RegionSizeX, sp2Position.Y, sp2Position.Z), 154 new Vector3(sp2Position.X - sceneWest.RegionInfo.RegionSizeX, sp2Position.Y, sp2Position.Z),
154 sp2ChildClient.SceneAgent.AbsolutePosition); 155 sp2ChildClient.SceneAgent.AbsolutePosition);
155 156
156 string receivedSp1ChatMessage = ""; 157 string receivedSp1ChatMessage = "";
157 string receivedSp2ChatMessage = ""; 158 string receivedSp2ChatMessage = "";
158 159
159 sp1ChildClient.OnReceivedChatMessage 160 sp1ChildClient.OnReceivedChatMessage
160 += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp1ChatMessage = message; 161 += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp1ChatMessage = message;
161 sp2ChildClient.OnReceivedChatMessage 162 sp2ChildClient.OnReceivedChatMessage
162 += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp2ChatMessage = message; 163 += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp2ChatMessage = message;
163 164
164 TestUserInRange(sp1Client, "ello darling", ref receivedSp2ChatMessage); 165 TestUserInRange(sp1Client, "ello darling", ref receivedSp2ChatMessage);
@@ -166,11 +167,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
166 167
167 sp1Position = new Vector3(30, 128, 20); 168 sp1Position = new Vector3(30, 128, 20);
168 sp1.AbsolutePosition = sp1Position; 169 sp1.AbsolutePosition = sp1Position;
170 sceneWest.Update(1);
169 sceneEast.Update(1); 171 sceneEast.Update(1);
172 Thread.Sleep(12000); // child updates are now time limited
173 sceneWest.Update(5);
174 sceneEast.Update(5);
170 175
171 // Check child position is correct. 176 // Check child position is correct.
172 Assert.AreEqual( 177 Assert.AreEqual(
173 new Vector3(sp1Position.X + sceneEast.RegionInfo.RegionSizeX, sp1Position.Y, sp1Position.Z), 178 new Vector3(sp1Position.X + sceneEast.RegionInfo.RegionSizeX, sp1Position.Y, sp1Position.Z),
174 sp1ChildClient.SceneAgent.AbsolutePosition); 179 sp1ChildClient.SceneAgent.AbsolutePosition);
175 180
176 TestUserOutOfRange(sp1Client, "beef", ref receivedSp2ChatMessage); 181 TestUserOutOfRange(sp1Client, "beef", ref receivedSp2ChatMessage);
@@ -197,8 +202,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
197 Vector3 sp2Position = new Vector3(128, 6, 20); 202 Vector3 sp2Position = new Vector3(128, 6, 20);
198 203
199 SceneHelpers sh = new SceneHelpers(); 204 SceneHelpers sh = new SceneHelpers();
200 TestScene sceneNorth = sh.SetupScene("sceneNorth", TestHelpers.ParseTail(0x1), 1000, 1000); 205 TestScene sceneNorth = sh.SetupScene("sceneNorth", TestHelpers.ParseTail(0x1), 1000, 1000);
201 TestScene sceneSouth = sh.SetupScene("sceneSouth", TestHelpers.ParseTail(0x2), 1000, 1001); 206 TestScene sceneSouth = sh.SetupScene("sceneSouth", TestHelpers.ParseTail(0x2), 1000, 1001);
202 207
203 SetupNeighbourRegions(sceneNorth, sceneSouth); 208 SetupNeighbourRegions(sceneNorth, sceneSouth);
204 209
@@ -210,12 +215,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
210 // physics is irrelevant to this test. 215 // physics is irrelevant to this test.
211 sp1.Flying = true; 216 sp1.Flying = true;
212 217
213 // When sp1 logs in to sceneEast, it sets up a child agent in sceneNorth and informs the sp2 client to 218 // When sp1 logs in to sceneEast, it sets up a child agent in sceneNorth and informs the sp2 client to
214 // make the connection. For this test, will simplify this chain by making the connection directly. 219 // make the connection. For this test, will simplify this chain by making the connection directly.
215 ScenePresence sp1Child = SceneHelpers.AddChildScenePresence(sceneSouth, sp1Uuid); 220 ScenePresence sp1Child = SceneHelpers.AddChildScenePresence(sceneSouth, sp1Uuid);
216 TestClient sp1ChildClient = (TestClient)sp1Child.ControllingClient; 221 TestClient sp1ChildClient = (TestClient)sp1Child.ControllingClient;
217 222
218 sp1.AbsolutePosition = sp1Position; 223 sp1.AbsolutePosition = sp1Position;
219 224
220 ScenePresence sp2 = SceneHelpers.AddScenePresence(sceneSouth, sp2Uuid); 225 ScenePresence sp2 = SceneHelpers.AddScenePresence(sceneSouth, sp2Uuid);
221 TestClient sp2Client = (TestClient)sp2.ControllingClient; 226 TestClient sp2Client = (TestClient)sp2.ControllingClient;
@@ -224,7 +229,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
224 ScenePresence sp2Child = SceneHelpers.AddChildScenePresence(sceneNorth, sp2Uuid); 229 ScenePresence sp2Child = SceneHelpers.AddChildScenePresence(sceneNorth, sp2Uuid);
225 TestClient sp2ChildClient = (TestClient)sp2Child.ControllingClient; 230 TestClient sp2ChildClient = (TestClient)sp2Child.ControllingClient;
226 231
227 sp2.AbsolutePosition = sp2Position; 232 sp2.AbsolutePosition = sp2Position;
228 233
229 // We must update the scenes in order to make the root new root agents trigger position updates in their 234 // We must update the scenes in order to make the root new root agents trigger position updates in their
230 // children. 235 // children.
@@ -233,19 +238,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
233 238
234 // Check child positions are correct. 239 // Check child positions are correct.
235 Assert.AreEqual( 240 Assert.AreEqual(
236 new Vector3(sp1Position.X, sp1Position.Y - sceneNorth.RegionInfo.RegionSizeY, sp1Position.Z), 241 new Vector3(sp1Position.X, sp1Position.Y - sceneNorth.RegionInfo.RegionSizeY, sp1Position.Z),
237 sp1ChildClient.SceneAgent.AbsolutePosition); 242 sp1ChildClient.SceneAgent.AbsolutePosition);
238 243
239 Assert.AreEqual( 244 Assert.AreEqual(
240 new Vector3(sp2Position.X, sp2Position.Y + sceneSouth.RegionInfo.RegionSizeY, sp2Position.Z), 245 new Vector3(sp2Position.X, sp2Position.Y + sceneSouth.RegionInfo.RegionSizeY, sp2Position.Z),
241 sp2ChildClient.SceneAgent.AbsolutePosition); 246 sp2ChildClient.SceneAgent.AbsolutePosition);
242 247
243 string receivedSp1ChatMessage = ""; 248 string receivedSp1ChatMessage = "";
244 string receivedSp2ChatMessage = ""; 249 string receivedSp2ChatMessage = "";
245 250
246 sp1ChildClient.OnReceivedChatMessage 251 sp1ChildClient.OnReceivedChatMessage
247 += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp1ChatMessage = message; 252 += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp1ChatMessage = message;
248 sp2ChildClient.OnReceivedChatMessage 253 sp2ChildClient.OnReceivedChatMessage
249 += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp2ChatMessage = message; 254 += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp2ChatMessage = message;
250 255
251 TestUserInRange(sp1Client, "ello darling", ref receivedSp2ChatMessage); 256 TestUserInRange(sp1Client, "ello darling", ref receivedSp2ChatMessage);
@@ -254,16 +259,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
254 sp1Position = new Vector3(30, 128, 20); 259 sp1Position = new Vector3(30, 128, 20);
255 sp1.AbsolutePosition = sp1Position; 260 sp1.AbsolutePosition = sp1Position;
256 sceneNorth.Update(1); 261 sceneNorth.Update(1);
262 sceneSouth.Update(1);
263 Thread.Sleep(12000); // child updates are now time limited
264 sceneNorth.Update(5);
265 sceneSouth.Update(5);
257 266
258 // Check child position is correct. 267 // Check child position is correct.
259 Assert.AreEqual( 268 Assert.AreEqual(
260 new Vector3(sp1Position.X, sp1Position.Y - sceneNorth.RegionInfo.RegionSizeY, sp1Position.Z), 269 new Vector3(sp1Position.X, sp1Position.Y - sceneNorth.RegionInfo.RegionSizeY, sp1Position.Z),
261 sp1ChildClient.SceneAgent.AbsolutePosition); 270 sp1ChildClient.SceneAgent.AbsolutePosition);
262 271
263 TestUserOutOfRange(sp1Client, "beef", ref receivedSp2ChatMessage); 272 TestUserOutOfRange(sp1Client, "beef", ref receivedSp2ChatMessage);
264 TestUserOutOfRange(sp2Client, "lentils", ref receivedSp1ChatMessage); 273 TestUserOutOfRange(sp2Client, "lentils", ref receivedSp1ChatMessage);
265 } 274 }
266 275
267 private void TestUserInRange(TestClient speakClient, string testMessage, ref string receivedMessage) 276 private void TestUserInRange(TestClient speakClient, string testMessage, ref string receivedMessage)
268 { 277 {
269 receivedMessage = ""; 278 receivedMessage = "";
diff --git a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
index fc23b72..4e1958a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
@@ -183,10 +183,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
183 try 183 try
184 { 184 {
185 ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 185 ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
186
187 if (obj == null) 186 if (obj == null)
188 return; 187 return;
189
190 if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0 188 if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0
191 || avatar.Scene.RegionInfo.RegionSettings.AllowDamage) 189 || avatar.Scene.RegionInfo.RegionSettings.AllowDamage)
192 { 190 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs b/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
index 764adf9..cf65c47 100644
--- a/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
@@ -62,19 +62,19 @@ namespace OpenSim.Region.CoreModules.Avatars.Commands
62 private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>(); 62 private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
63 63
64 public string Name { get { return "User Commands Module"; } } 64 public string Name { get { return "User Commands Module"; } }
65 65
66 public Type ReplaceableInterface { get { return null; } } 66 public Type ReplaceableInterface { get { return null; } }
67 67
68 public void Initialise(IConfigSource source) 68 public void Initialise(IConfigSource source)
69 { 69 {
70// m_log.DebugFormat("[USER COMMANDS MODULE]: INITIALIZED MODULE"); 70// m_log.DebugFormat("[USER COMMANDS MODULE]: INITIALIZED MODULE");
71 } 71 }
72 72
73 public void PostInitialise() 73 public void PostInitialise()
74 { 74 {
75// m_log.DebugFormat("[USER COMMANDS MODULE]: POST INITIALIZED MODULE"); 75// m_log.DebugFormat("[USER COMMANDS MODULE]: POST INITIALIZED MODULE");
76 } 76 }
77 77
78 public void Close() 78 public void Close()
79 { 79 {
80// m_log.DebugFormat("[USER COMMANDS MODULE]: CLOSED MODULE"); 80// m_log.DebugFormat("[USER COMMANDS MODULE]: CLOSED MODULE");
diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
index a896897..56819fa 100644
--- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
@@ -203,8 +203,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
203 { 203 {
204 m_scene.ForEachRootClient(delegate(IClientAPI client) 204 m_scene.ForEachRootClient(delegate(IClientAPI client)
205 { 205 {
206 client.SendBlueBoxMessage(fromAvatarID, fromAvatarName, 206 client.SendAgentAlertMessage(
207 message); 207 message, false);
208 }); 208 });
209 } 209 }
210 210
@@ -260,4 +260,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
260 return result; 260 return result;
261 } 261 }
262 } 262 }
263} \ No newline at end of file 263}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
index eb23e83..4a55a7e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
@@ -118,7 +118,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
118 // If we're in god mode, we reverse the meaning. Offer 118 // If we're in god mode, we reverse the meaning. Offer
119 // calling card becomes "Take a calling card" for that 119 // calling card becomes "Take a calling card" for that
120 // person, no matter if they agree or not. 120 // person, no matter if they agree or not.
121 if (sp.GodLevel >= 200) 121 if (sp.IsViewerUIGod)
122 { 122 {
123 CreateCallingCard(client.AgentId, destID, UUID.Zero, true); 123 CreateCallingCard(client.AgentId, destID, UUID.Zero, true);
124 return; 124 return;
@@ -239,8 +239,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
239 InventoryFolderBase trashFolder = 239 InventoryFolderBase trashFolder =
240 invService.GetFolderForType(client.AgentId, FolderType.Trash); 240 invService.GetFolderForType(client.AgentId, FolderType.Trash);
241 241
242 InventoryItemBase item = new InventoryItemBase(transactionID, client.AgentId); 242 InventoryItemBase item = invService.GetItem(client.AgentId, transactionID);
243 item = invService.GetItem(item);
244 243
245 if (item != null && trashFolder != null) 244 if (item != null && trashFolder != null)
246 { 245 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 08e7dd2..772485c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -167,7 +167,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
167 m_Enabled = true; 167 m_Enabled = true;
168 m_log.DebugFormat("[FRIENDS MODULE]: {0} enabled.", Name); 168 m_log.DebugFormat("[FRIENDS MODULE]: {0} enabled.", Name);
169 } 169 }
170 } 170 }
171 } 171 }
172 172
173 protected virtual void InitModule(IConfigSource config) 173 protected virtual void InitModule(IConfigSource config)
@@ -247,14 +247,30 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
247 { 247 {
248 FriendInfo[] friends = GetFriendsFromCache(principalID); 248 FriendInfo[] friends = GetFriendsFromCache(principalID);
249 FriendInfo finfo = GetFriend(friends, friendID); 249 FriendInfo finfo = GetFriend(friends, friendID);
250 if (finfo != null) 250 if (finfo != null && finfo.TheirFlags != -1)
251 { 251 {
252 return finfo.TheirFlags; 252 return finfo.TheirFlags;
253 } 253 }
254
255 return 0; 254 return 0;
256 } 255 }
257 256
257 private void OnMakeRootAgent(ScenePresence sp)
258 {
259 if(sp.gotCrossUpdate)
260 return;
261
262 RecacheFriends(sp.ControllingClient);
263
264 lock (m_NeedsToNotifyStatus)
265 {
266 if (m_NeedsToNotifyStatus.Remove(sp.UUID))
267 {
268 // Inform the friends that this user is online. This can only be done once the client is a Root Agent.
269 StatusChange(sp.UUID, true);
270 }
271 }
272 }
273
258 private void OnNewClient(IClientAPI client) 274 private void OnNewClient(IClientAPI client)
259 { 275 {
260 client.OnInstantMessage += OnInstantMessage; 276 client.OnInstantMessage += OnInstantMessage;
@@ -262,6 +278,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
262 client.OnDenyFriendRequest += OnDenyFriendRequest; 278 client.OnDenyFriendRequest += OnDenyFriendRequest;
263 client.OnTerminateFriendship += RemoveFriendship; 279 client.OnTerminateFriendship += RemoveFriendship;
264 client.OnGrantUserRights += GrantRights; 280 client.OnGrantUserRights += GrantRights;
281 client.OnFindAgent += FindFriend;
265 282
266 // We need to cache information for child agents as well as root agents so that friend edit/move/delete 283 // We need to cache information for child agents as well as root agents so that friend edit/move/delete
267 // permissions will work across borders where both regions are on different simulators. 284 // permissions will work across borders where both regions are on different simulators.
@@ -326,20 +343,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
326 } 343 }
327 } 344 }
328 345
329 private void OnMakeRootAgent(ScenePresence sp)
330 {
331 RecacheFriends(sp.ControllingClient);
332
333 lock (m_NeedsToNotifyStatus)
334 {
335 if (m_NeedsToNotifyStatus.Remove(sp.UUID))
336 {
337 // Inform the friends that this user is online. This can only be done once the client is a Root Agent.
338 StatusChange(sp.UUID, true);
339 }
340 }
341 }
342
343 private void OnClientLogin(IClientAPI client) 346 private void OnClientLogin(IClientAPI client)
344 { 347 {
345 UUID agentID = client.AgentId; 348 UUID agentID = client.AgentId;
@@ -358,8 +361,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
358 m_NeedsListOfOnlineFriends.Add(agentID); 361 m_NeedsListOfOnlineFriends.Add(agentID);
359 } 362 }
360 363
364 public void IsNowRoot(ScenePresence sp)
365 {
366 OnMakeRootAgent(sp);
367 }
368
361 public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client) 369 public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client)
362 { 370 {
371 if (client == null)
372 return false;
373
363 UUID agentID = client.AgentId; 374 UUID agentID = client.AgentId;
364 375
365 // Check if the online friends list is needed 376 // Check if the online friends list is needed
@@ -500,18 +511,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
500 if (((fi.MyFlags & (int)FriendRights.CanSeeOnline) != 0) && (fi.TheirFlags != -1)) 511 if (((fi.MyFlags & (int)FriendRights.CanSeeOnline) != 0) && (fi.TheirFlags != -1))
501 friendList.Add(fi); 512 friendList.Add(fi);
502 } 513 }
503 514 if(friendList.Count > 0)
504 Util.FireAndForget( 515 {
505 delegate 516 Util.FireAndForget(
506 { 517 delegate
507// m_log.DebugFormat( 518 {
508// "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}", 519// m_log.DebugFormat(
509// friendList.Count, agentID, online); 520// "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}",
510 521// friendList.Count, agentID, online);
511 // Notify about this user status 522
512 StatusNotify(friendList, agentID, online); 523 // Notify about this user status
513 }, null, "FriendsModule.StatusChange" 524 StatusNotify(friendList, agentID, online);
514 ); 525 }, null, "FriendsModule.StatusChange"
526 );
527 }
515 } 528 }
516 } 529 }
517 530
@@ -540,6 +553,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
540 // We do this regrouping so that we can efficiently send a single request rather than one for each 553 // We do this regrouping so that we can efficiently send a single request rather than one for each
541 // friend in what may be a very large friends list. 554 // friend in what may be a very large friends list.
542 PresenceInfo[] friendSessions = PresenceService.GetAgents(remoteFriendStringIds.ToArray()); 555 PresenceInfo[] friendSessions = PresenceService.GetAgents(remoteFriendStringIds.ToArray());
556 if(friendSessions == null)
557 return;
543 558
544 foreach (PresenceInfo friendSession in friendSessions) 559 foreach (PresenceInfo friendSession in friendSessions)
545 { 560 {
@@ -561,7 +576,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
561 protected virtual void OnInstantMessage(IClientAPI client, GridInstantMessage im) 576 protected virtual void OnInstantMessage(IClientAPI client, GridInstantMessage im)
562 { 577 {
563 if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered) 578 if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered)
564 { 579 {
565 // we got a friendship offer 580 // we got a friendship offer
566 UUID principalID = new UUID(im.fromAgentID); 581 UUID principalID = new UUID(im.fromAgentID);
567 UUID friendID = new UUID(im.toAgentID); 582 UUID friendID = new UUID(im.toAgentID);
@@ -596,7 +611,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
596 im.imSessionID = im.fromAgentID; 611 im.imSessionID = im.fromAgentID;
597 im.fromAgentName = GetFriendshipRequesterName(agentID); 612 im.fromAgentName = GetFriendshipRequesterName(agentID);
598 613
599 // Try the local sim 614 // Try the local sim
600 if (LocalFriendshipOffered(friendID, im)) 615 if (LocalFriendshipOffered(friendID, im))
601 return true; 616 return true;
602 617
@@ -639,7 +654,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
639 ccm.CreateCallingCard(client.AgentId, friendID, UUID.Zero); 654 ccm.CreateCallingCard(client.AgentId, friendID, UUID.Zero);
640 } 655 }
641 656
642 // Update the local cache. 657 // Update the local cache.
643 RecacheFriends(client); 658 RecacheFriends(client);
644 659
645 // 660 //
@@ -695,7 +710,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
695 } 710 }
696 } 711 }
697 } 712 }
698 713
699 public void RemoveFriendship(IClientAPI client, UUID exfriendID) 714 public void RemoveFriendship(IClientAPI client, UUID exfriendID)
700 { 715 {
701 if (!DeleteFriendship(client.AgentId, exfriendID)) 716 if (!DeleteFriendship(client.AgentId, exfriendID))
@@ -723,7 +738,65 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
723 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); 738 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
724 m_FriendsSimConnector.FriendshipTerminated(region, client.AgentId, exfriendID); 739 m_FriendsSimConnector.FriendshipTerminated(region, client.AgentId, exfriendID);
725 } 740 }
726 } 741 }
742 }
743
744 public void FindFriend(IClientAPI remoteClient,UUID HunterID ,UUID PreyID)
745 {
746 UUID requester = remoteClient.AgentId;
747 if(requester != HunterID) // only allow client agent to be the hunter (?)
748 return;
749
750 FriendInfo[] friends = GetFriendsFromCache(requester);
751 if (friends.Length == 0)
752 return;
753
754 FriendInfo friend = GetFriend(friends, PreyID);
755 if (friend == null)
756 return;
757
758 if(friend.TheirFlags == -1 || (friend.TheirFlags & (int)FriendRights.CanSeeOnMap) == 0)
759 return;
760
761 Scene hunterScene = (Scene)remoteClient.Scene;
762
763 if(hunterScene == null)
764 return;
765
766 // check local
767 ScenePresence sp;
768 double px;
769 double py;
770 if(hunterScene.TryGetScenePresence(PreyID, out sp))
771 {
772 if(sp == null)
773 return;
774 px = hunterScene.RegionInfo.WorldLocX + sp.AbsolutePosition.X;
775 py = hunterScene.RegionInfo.WorldLocY + sp.AbsolutePosition.Y;
776
777 remoteClient.SendFindAgent(HunterID, PreyID, px, py);
778 return;
779 }
780
781 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { PreyID.ToString() });
782
783 if (friendSessions == null || friendSessions.Length == 0)
784 return;
785
786 PresenceInfo friendSession = friendSessions[0];
787 if (friendSession == null)
788 return;
789
790 GridRegion region = GridService.GetRegionByUUID(hunterScene.RegionInfo.ScopeID, friendSession.RegionID);
791
792 if(region == null)
793 return;
794
795 // we don't have presence location so point to a standard region center for now
796 px = region.RegionLocX + 128.0;
797 py = region.RegionLocY + 128.0;
798
799 remoteClient.SendFindAgent(HunterID, PreyID, px, py);
727 } 800 }
728 801
729 public void GrantRights(IClientAPI remoteClient, UUID friendID, int rights) 802 public void GrantRights(IClientAPI remoteClient, UUID friendID, int rights)
@@ -745,7 +818,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
745 818
746 if (friend != null) // Found it 819 if (friend != null) // Found it
747 { 820 {
748 // Store it on the DB 821 // Store it on service
749 if (!StoreRights(requester, friendID, rights)) 822 if (!StoreRights(requester, friendID, rights))
750 { 823 {
751 remoteClient.SendAlertMessage("Unable to grant rights."); 824 remoteClient.SendAlertMessage("Unable to grant rights.");
@@ -869,28 +942,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
869 return false; 942 return false;
870 } 943 }
871 944
872 public bool LocalGrantRights(UUID userID, UUID friendID, int userFlags, int rights) 945 public bool LocalGrantRights(UUID userID, UUID friendID, int oldRights, int newRights)
873 { 946 {
874 IClientAPI friendClient = LocateClientObject(friendID); 947 IClientAPI friendClient = LocateClientObject(friendID);
875 if (friendClient != null) 948 if (friendClient != null)
876 { 949 {
877 bool onlineBitChanged = ((rights ^ userFlags) & (int)FriendRights.CanSeeOnline) != 0; 950 int changedRights = newRights ^ oldRights;
951 bool onlineBitChanged = (changedRights & (int)FriendRights.CanSeeOnline) != 0;
878 if (onlineBitChanged) 952 if (onlineBitChanged)
879 { 953 {
880 if ((rights & (int)FriendRights.CanSeeOnline) == 1) 954 if ((newRights & (int)FriendRights.CanSeeOnline) == 1)
881 friendClient.SendAgentOnline(new UUID[] { userID }); 955 friendClient.SendAgentOnline(new UUID[] { userID });
882 else 956 else
883 friendClient.SendAgentOffline(new UUID[] { userID }); 957 friendClient.SendAgentOffline(new UUID[] { userID });
884 } 958 }
885 else 959
886 { 960 if(changedRights != 0)
887 bool canEditObjectsChanged = ((rights ^ userFlags) & (int)FriendRights.CanModifyObjects) != 0; 961 friendClient.SendChangeUserRights(userID, friendID, newRights);
888 if (canEditObjectsChanged)
889 friendClient.SendChangeUserRights(userID, friendID, rights);
890 }
891 962
892 // Update local cache 963 // Update local cache
893 UpdateLocalCache(userID, friendID, rights); 964 UpdateLocalCache(userID, friendID, newRights);
894 965
895 return true; 966 return true;
896 } 967 }
@@ -946,8 +1017,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
946 lock (m_Friends) 1017 lock (m_Friends)
947 { 1018 {
948 FriendInfo[] friends = GetFriendsFromCache(friendID); 1019 FriendInfo[] friends = GetFriendsFromCache(friendID);
949 FriendInfo finfo = GetFriend(friends, userID); 1020 if(friends != EMPTY_FRIENDS)
950 finfo.TheirFlags = rights; 1021 {
1022 FriendInfo finfo = GetFriend(friends, userID);
1023 if(finfo!= null)
1024 finfo.TheirFlags = rights;
1025 }
951 } 1026 }
952 } 1027 }
953 1028
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
index 13512a2..091b197 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
@@ -65,9 +65,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
65 protected override byte[] ProcessRequest( 65 protected override byte[] ProcessRequest(
66 string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 66 string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
67 { 67 {
68 StreamReader sr = new StreamReader(requestData); 68 string body;
69 string body = sr.ReadToEnd(); 69 using(StreamReader sr = new StreamReader(requestData))
70 sr.Close(); 70 body = sr.ReadToEnd();
71
71 body = body.Trim(); 72 body = body.Trim();
72 73
73 //m_log.DebugFormat("[XXX]: query String: {0}", body); 74 //m_log.DebugFormat("[XXX]: query String: {0}", body);
@@ -127,7 +128,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
127 UserAccount account = m_FriendsModule.UserAccountService.GetUserAccount(UUID.Zero, fromID); 128 UserAccount account = m_FriendsModule.UserAccountService.GetUserAccount(UUID.Zero, fromID);
128 string name = (account == null) ? "Unknown" : account.FirstName + " " + account.LastName; 129 string name = (account == null) ? "Unknown" : account.FirstName + " " + account.LastName;
129 130
130 GridInstantMessage im = new GridInstantMessage(m_FriendsModule.Scene, fromID, name, toID, 131 GridInstantMessage im = new GridInstantMessage(m_FriendsModule.Scene, fromID, name, toID,
131 (byte)InstantMessageDialog.FriendshipOffered, message, false, Vector3.Zero); 132 (byte)InstantMessageDialog.FriendshipOffered, message, false, Vector3.Zero);
132 133
133 // !! HACK 134 // !! HACK
@@ -211,7 +212,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
211 { 212 {
212 UUID fromID = UUID.Zero; 213 UUID fromID = UUID.Zero;
213 UUID toID = UUID.Zero; 214 UUID toID = UUID.Zero;
214 int rights = 0, userFlags = 0; 215 int oldRights = 0, newRights = 0;
215 216
216 if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID")) 217 if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID"))
217 return FailureResult(); 218 return FailureResult();
@@ -222,13 +223,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
222 if (!UUID.TryParse(request["ToID"].ToString(), out toID)) 223 if (!UUID.TryParse(request["ToID"].ToString(), out toID))
223 return FailureResult(); 224 return FailureResult();
224 225
225 if (!Int32.TryParse(request["UserFlags"].ToString(), out userFlags)) 226 if (!Int32.TryParse(request["UserFlags"].ToString(), out oldRights))
226 return FailureResult(); 227 return FailureResult();
227 228
228 if (!Int32.TryParse(request["Rights"].ToString(), out rights)) 229 if (!Int32.TryParse(request["Rights"].ToString(), out newRights))
229 return FailureResult(); 230 return FailureResult();
230 231
231 if (m_FriendsModule.LocalGrantRights(UUID.Zero, UUID.Zero, userFlags, rights)) 232 if (m_FriendsModule.LocalGrantRights(fromID, toID, oldRights, newRights))
232 return SuccessResult(); 233 return SuccessResult();
233 234
234 return FailureResult(); 235 return FailureResult();
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
index 27b7376..fae1e05 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -141,7 +141,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
141 if (avatar == null) 141 if (avatar == null)
142 return; 142 return;
143 143
144 if (avatar.UserLevel < m_levelHGFriends) 144 if (avatar.GodController.UserLevel < m_levelHGFriends)
145 { 145 {
146 client.SendAgentAlertMessage("Unable to send friendship invitation to foreigner. Insufficient permissions.", false); 146 client.SendAgentAlertMessage("Unable to send friendship invitation to foreigner. Insufficient permissions.", false);
147 return; 147 return;
@@ -214,7 +214,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
214 FriendInfo[] friends = GetFriendsFromCache(client.AgentId); 214 FriendInfo[] friends = GetFriendsFromCache(client.AgentId);
215 foreach (FriendInfo f in friends) 215 foreach (FriendInfo f in friends)
216 { 216 {
217 client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags); 217 int rights = f.TheirFlags;
218 if(rights != -1 )
219 client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, rights);
218 } 220 }
219 } 221 }
220 } 222 }
@@ -337,7 +339,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
337 if (UUID.TryParse(friendID, out id)) 339 if (UUID.TryParse(friendID, out id))
338 return base.FriendshipMessage(friendID); 340 return base.FriendshipMessage(friendID);
339 341
340 return "Please confirm this friendship you made while you were away."; 342 return "Please confirm this friendship you made while you where on another HG grid";
341 } 343 }
342 344
343 protected override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID) 345 protected override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
@@ -456,6 +458,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
456 { 458 {
457 // local grid users 459 // local grid users
458 m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local"); 460 m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local");
461 DeletePreviousHGRelations(agentID, friendID);
459 base.StoreFriendships(agentID, friendID); 462 base.StoreFriendships(agentID, friendID);
460 return; 463 return;
461 } 464 }
@@ -538,8 +541,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
538 // m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}", 541 // m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}",
539 // agentUUI, friendUUI, agentFriendService, friendFriendService); 542 // agentUUI, friendUUI, agentFriendService, friendFriendService);
540 543
541 } 544 }
542 545
543 // Delete any previous friendship relations 546 // Delete any previous friendship relations
544 DeletePreviousRelations(agentID, friendID); 547 DeletePreviousRelations(agentID, friendID);
545 548
@@ -624,6 +627,45 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
624 } 627 }
625 } 628 }
626 629
630 private void DeletePreviousHGRelations(UUID a1, UUID a2)
631 {
632 // Delete any previous friendship relations
633 FriendInfo[] finfos = null;
634 finfos = GetFriendsFromCache(a1);
635 if (finfos != null)
636 {
637 foreach (FriendInfo f in finfos)
638 {
639 if (f.TheirFlags == -1)
640 {
641 if (f.Friend.StartsWith(a2.ToString()))
642 {
643 FriendsService.Delete(a1, f.Friend);
644 // and also the converse
645 FriendsService.Delete(f.Friend, a1.ToString());
646 }
647 }
648 }
649 }
650
651 finfos = GetFriendsFromCache(a1);
652 if (finfos != null)
653 {
654 foreach (FriendInfo f in finfos)
655 {
656 if (f.TheirFlags == -1)
657 {
658 if (f.Friend.StartsWith(a1.ToString()))
659 {
660 FriendsService.Delete(a2, f.Friend);
661 // and also the converse
662 FriendsService.Delete(f.Friend, a2.ToString());
663 }
664 }
665 }
666 }
667 }
668
627 protected override bool DeleteFriendship(UUID agentID, UUID exfriendID) 669 protected override bool DeleteFriendship(UUID agentID, UUID exfriendID)
628 { 670 {
629 Boolean agentIsLocal = true; 671 Boolean agentIsLocal = true;
@@ -743,7 +785,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
743 m_log.DebugFormat("[HGFRIENDS MODULE]: Forwading friendship from {0} to {1} @ {2}", agentID, friendID, friendsURL); 785 m_log.DebugFormat("[HGFRIENDS MODULE]: Forwading friendship from {0} to {1} @ {2}", agentID, friendID, friendsURL);
744 GridRegion region = new GridRegion(); 786 GridRegion region = new GridRegion();
745 region.ServerURI = friendsURL; 787 region.ServerURI = friendsURL;
746 788
747 string name = im.fromAgentName; 789 string name = im.fromAgentName;
748 if (m_uMan.IsLocalGridUser(agentID)) 790 if (m_uMan.IsLocalGridUser(agentID))
749 { 791 {
@@ -775,7 +817,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
775 } 817 }
776 818
777 m_HGFriendsConnector.FriendshipOffered(region, agentID, friendID, im.message, name); 819 m_HGFriendsConnector.FriendshipOffered(region, agentID, friendID, im.message, name);
778 820
779 return true; 821 return true;
780 } 822 }
781 } 823 }
@@ -804,4 +846,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
804 return false; 846 return false;
805 } 847 }
806 } 848 }
807} \ No newline at end of file 849}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGStatusNotifier.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGStatusNotifier.cs
index 1fa4dd6..3fae271 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/HGStatusNotifier.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGStatusNotifier.cs
@@ -32,7 +32,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
32 { 32 {
33 if (kvp.Key != "local") 33 if (kvp.Key != "local")
34 { 34 {
35 // For the others, call the user agent service 35 // For the others, call the user agent service
36 List<string> ids = new List<string>(); 36 List<string> ids = new List<string>();
37 foreach (FriendInfo f in kvp.Value) 37 foreach (FriendInfo f in kvp.Value)
38 ids.Add(f.Friend); 38 ids.Add(f.Friend);
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
index e6fd54e..3d9bd35 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
@@ -67,7 +67,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests
67 // so that different services and simulator can share the data in standalone mode. This is pretty horrible 67 // so that different services and simulator can share the data in standalone mode. This is pretty horrible
68 // effectively the statics are global variables. 68 // effectively the statics are global variables.
69 NullFriendsData.Clear(); 69 NullFriendsData.Clear();
70 70
71 IConfigSource config = new IniConfigSource(); 71 IConfigSource config = new IniConfigSource();
72 config.AddConfig("Modules"); 72 config.AddConfig("Modules");
73 // Not strictly necessary since FriendsModule assumes it is the default (!) 73 // Not strictly necessary since FriendsModule assumes it is the default (!)
diff --git a/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs b/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs
index 095c57b..03e2c5a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs
@@ -42,11 +42,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Gestures
42{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GesturesModule")] 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GesturesModule")]
44 public class GesturesModule : INonSharedRegionModule 44 public class GesturesModule : INonSharedRegionModule
45 { 45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 protected Scene m_scene; 48 protected Scene m_scene;
49 49
50 public void Initialise(IConfigSource source) 50 public void Initialise(IConfigSource source)
51 { 51 {
52 } 52 }
@@ -67,7 +67,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gestures
67 m_scene.EventManager.OnNewClient -= OnNewClient; 67 m_scene.EventManager.OnNewClient -= OnNewClient;
68 m_scene = null; 68 m_scene = null;
69 } 69 }
70 70
71 public void Close() {} 71 public void Close() {}
72 public string Name { get { return "Gestures Module"; } } 72 public string Name { get { return "Gestures Module"; } }
73 73
@@ -81,19 +81,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Gestures
81 client.OnActivateGesture += ActivateGesture; 81 client.OnActivateGesture += ActivateGesture;
82 client.OnDeactivateGesture += DeactivateGesture; 82 client.OnDeactivateGesture += DeactivateGesture;
83 } 83 }
84 84
85 public virtual void ActivateGesture(IClientAPI client, UUID assetId, UUID gestureId) 85 public virtual void ActivateGesture(IClientAPI client, UUID assetId, UUID gestureId)
86 { 86 {
87 IInventoryService invService = m_scene.InventoryService; 87 IInventoryService invService = m_scene.InventoryService;
88 88
89 InventoryItemBase item = new InventoryItemBase(gestureId, client.AgentId); 89 InventoryItemBase item = invService.GetItem(client.AgentId, gestureId);
90 item = invService.GetItem(item);
91 if (item != null) 90 if (item != null)
92 { 91 {
93 item.Flags |= 1; 92 item.Flags |= 1;
94 invService.UpdateItem(item); 93 invService.UpdateItem(item);
95 } 94 }
96 else 95 else
97 m_log.WarnFormat( 96 m_log.WarnFormat(
98 "[GESTURES]: Unable to find gesture {0} to activate for {1}", gestureId, client.Name); 97 "[GESTURES]: Unable to find gesture {0} to activate for {1}", gestureId, client.Name);
99 } 98 }
@@ -102,14 +101,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Gestures
102 { 101 {
103 IInventoryService invService = m_scene.InventoryService; 102 IInventoryService invService = m_scene.InventoryService;
104 103
105 InventoryItemBase item = new InventoryItemBase(gestureId, client.AgentId); 104 InventoryItemBase item = invService.GetItem(client.AgentId, gestureId);
106 item = invService.GetItem(item);
107 if (item != null) 105 if (item != null)
108 { 106 {
109 item.Flags &= ~(uint)1; 107 item.Flags &= ~(uint)1;
110 invService.UpdateItem(item); 108 invService.UpdateItem(item);
111 } 109 }
112 else 110 else
113 m_log.ErrorFormat( 111 m_log.ErrorFormat(
114 "[GESTURES]: Unable to find gesture to deactivate {0} for {1}", gestureId, client.Name); 112 "[GESTURES]: Unable to find gesture to deactivate {0} for {1}", gestureId, client.Name);
115 } 113 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 3b6d970..6e6974a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -59,19 +59,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
59 59
60 /// <summary>Special UUID for actions that apply to all agents</summary> 60 /// <summary>Special UUID for actions that apply to all agents</summary>
61 private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb"); 61 private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb");
62 private static readonly UUID UUID_GRID_GOD = new UUID("6571e388-6218-4574-87db-f9379718315e");
62 63
63 protected Scene m_scene; 64 protected Scene m_scene;
64 protected IDialogModule m_dialogModule; 65 protected IDialogModule m_dialogModule;
65 protected IDialogModule DialogModule
66 {
67 get
68 {
69 if (m_dialogModule == null)
70 m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>();
71
72 return m_dialogModule;
73 }
74 }
75 66
76 public void Initialise(IConfigSource source) 67 public void Initialise(IConfigSource source)
77 { 68 {
@@ -96,6 +87,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
96 87
97 public void RegionLoaded(Scene scene) 88 public void RegionLoaded(Scene scene)
98 { 89 {
90 m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>();
99 } 91 }
100 92
101 public void Close() {} 93 public void Close() {}
@@ -111,19 +103,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
111 client.OnGodKickUser += KickUser; 103 client.OnGodKickUser += KickUser;
112 client.OnRequestGodlikePowers += RequestGodlikePowers; 104 client.OnRequestGodlikePowers += RequestGodlikePowers;
113 } 105 }
114 106
115 public void UnsubscribeFromClientEvents(IClientAPI client) 107 public void UnsubscribeFromClientEvents(IClientAPI client)
116 { 108 {
117 client.OnGodKickUser -= KickUser; 109 client.OnGodKickUser -= KickUser;
118 client.OnRequestGodlikePowers -= RequestGodlikePowers; 110 client.OnRequestGodlikePowers -= RequestGodlikePowers;
119 } 111 }
120 112
121 private void OnRegisterCaps(UUID agentID, Caps caps) 113 private void OnRegisterCaps(UUID agentID, Caps caps)
122 { 114 {
123 string uri = "/CAPS/" + UUID.Random(); 115 string uri = "/CAPS/" + UUID.Random();
124 116
125 caps.RegisterHandler( 117 caps.RegisterHandler(
126 "UntrustedSimulatorMessage", 118 "UntrustedSimulatorMessage",
127 new RestStreamHandler("POST", uri, HandleUntrustedSimulatorMessage, "UntrustedSimulatorMessage", null)); 119 new RestStreamHandler("POST", uri, HandleUntrustedSimulatorMessage, "UntrustedSimulatorMessage", null));
128 } 120 }
129 121
@@ -146,11 +138,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
146 UUID godSessionID = userData["GodSessionID"].AsUUID(); 138 UUID godSessionID = userData["GodSessionID"].AsUUID();
147 uint kickFlags = userData["KickFlags"].AsUInteger(); 139 uint kickFlags = userData["KickFlags"].AsUInteger();
148 string reason = userData["Reason"].AsString(); 140 string reason = userData["Reason"].AsString();
141
149 ScenePresence god = m_scene.GetScenePresence(godID); 142 ScenePresence god = m_scene.GetScenePresence(godID);
150 if (god == null || god.ControllingClient.SessionId != godSessionID) 143 if (god == null || god.ControllingClient.SessionId != godSessionID)
151 return String.Empty; 144 return String.Empty;
152 145
153 KickUser(godID, godSessionID, agentID, kickFlags, Util.StringToBytes1024(reason)); 146 KickUser(godID, agentID, kickFlags, reason);
154 } 147 }
155 else 148 else
156 { 149 {
@@ -160,59 +153,63 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
160 } 153 }
161 154
162 public void RequestGodlikePowers( 155 public void RequestGodlikePowers(
163 UUID agentID, UUID sessionID, UUID token, bool godLike, IClientAPI controllingClient) 156 UUID agentID, UUID sessionID, UUID token, bool godLike)
164 { 157 {
165 ScenePresence sp = m_scene.GetScenePresence(agentID); 158 ScenePresence sp = m_scene.GetScenePresence(agentID);
159 if(sp == null || sp.IsDeleted || sp.IsNPC)
160 return;
166 161
167 if (sp != null) 162 if (sessionID != sp.ControllingClient.SessionId)
168 { 163 return;
169 if (godLike == false)
170 {
171 sp.GrantGodlikePowers(agentID, sessionID, token, godLike);
172 return;
173 }
174 164
175 // First check that this is the sim owner 165 sp.GrantGodlikePowers(token, godLike);
176 if (m_scene.Permissions.IsGod(agentID)) 166
177 { 167 if (godLike && !sp.IsViewerUIGod && m_dialogModule != null)
178 // Next we check for spoofing..... 168 m_dialogModule.SendAlertToUser(agentID, "Request for god powers denied");
179 UUID testSessionID = sp.ControllingClient.SessionId;
180 if (sessionID == testSessionID)
181 {
182 if (sessionID == controllingClient.SessionId)
183 {
184 //m_log.Info("godlike: " + godLike.ToString());
185 sp.GrantGodlikePowers(agentID, testSessionID, token, godLike);
186 }
187 }
188 }
189 else
190 {
191 if (DialogModule != null)
192 DialogModule.SendAlertToUser(agentID, "Request for god powers denied");
193 }
194 }
195 } 169 }
196 170
171 public void KickUser(UUID godID, UUID agentID, uint kickflags, byte[] reason)
172 {
173 KickUser(godID, agentID, kickflags, Utils.BytesToString(reason));
174 }
175
197 /// <summary> 176 /// <summary>
198 /// Kicks User specified from the simulator. This logs them off of the grid 177 /// Kicks or freezes User specified from the simulator. This logs them off of the grid
199 /// If the client gets the UUID: 44e87126e7944ded05b37c42da3d5cdb it assumes
200 /// that you're kicking it even if the avatar's UUID isn't the UUID that the
201 /// agent is assigned
202 /// </summary> 178 /// </summary>
203 /// <param name="godID">The person doing the kicking</param> 179 /// <param name="godID">The person doing the kicking</param>
204 /// <param name="sessionID">The session of the person doing the kicking</param>
205 /// <param name="agentID">the person that is being kicked</param> 180 /// <param name="agentID">the person that is being kicked</param>
206 /// <param name="kickflags">Tells what to do to the user</param> 181 /// <param name="kickflags">Tells what to do to the user</param>
207 /// <param name="reason">The message to send to the user after it's been turned into a field</param> 182 /// <param name="reason">The message to send to the user after it's been turned into a field</param>
208 public void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason) 183 public void KickUser(UUID godID, UUID agentID, uint kickflags, string reason)
209 { 184 {
210 if (!m_scene.Permissions.IsGod(godID)) 185 // assuming automatic god rights on this for fast griefing reaction
186 // this is also needed for kick via message
187 if(!m_scene.Permissions.IsGod(godID))
211 return; 188 return;
212 189
213 ScenePresence sp = m_scene.GetScenePresence(agentID); 190 int godlevel = 200;
191 // update level so higher gods can kick lower ones
192 ScenePresence god = m_scene.GetScenePresence(godID);
193 if(god != null && god.GodController.GodLevel > godlevel)
194 godlevel = god.GodController.GodLevel;
195
196 if(agentID == ALL_AGENTS)
197 {
198 m_scene.ForEachRootScenePresence(delegate(ScenePresence p)
199 {
200 if (p.UUID != godID)
201 {
202 if(godlevel > p.GodController.GodLevel)
203 doKickmodes(godID, p, kickflags, reason);
204 else if(m_dialogModule != null)
205 m_dialogModule.SendAlertToUser(p.UUID, "Kick from " + godID.ToString() + " ignored, kick reason: " + reason);
206 }
207 });
208 return;
209 }
214 210
215 if (sp == null && agentID != ALL_AGENTS) 211 ScenePresence sp = m_scene.GetScenePresence(agentID);
212 if (sp == null || sp.IsChildAgent)
216 { 213 {
217 IMessageTransferModule transferModule = 214 IMessageTransferModule transferModule =
218 m_scene.RequestModuleInterface<IMessageTransferModule>(); 215 m_scene.RequestModuleInterface<IMessageTransferModule>();
@@ -221,58 +218,95 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
221 m_log.DebugFormat("[GODS]: Sending nonlocal kill for agent {0}", agentID); 218 m_log.DebugFormat("[GODS]: Sending nonlocal kill for agent {0}", agentID);
222 transferModule.SendInstantMessage(new GridInstantMessage( 219 transferModule.SendInstantMessage(new GridInstantMessage(
223 m_scene, godID, "God", agentID, (byte)250, false, 220 m_scene, godID, "God", agentID, (byte)250, false,
224 Utils.BytesToString(reason), UUID.Zero, true, 221 reason, UUID.Zero, true,
225 new Vector3(), new byte[] {(byte)kickflags}, true), 222 new Vector3(), new byte[] {(byte)kickflags}, true),
226 delegate(bool success) {} ); 223 delegate(bool success) {} );
227 } 224 }
228 return; 225 return;
229 } 226 }
230 227
228 if (godlevel <= sp.GodController.GodLevel) // no god wars
229 {
230 if(m_dialogModule != null)
231 m_dialogModule.SendAlertToUser(sp.UUID, "Kick from " + godID.ToString() + " ignored, kick reason: " + reason);
232 return;
233 }
234
235 if(sp.UUID == godID)
236 return;
237
238 doKickmodes(godID, sp, kickflags, reason);
239 }
240
241 private void doKickmodes(UUID godID, ScenePresence sp, uint kickflags, string reason)
242 {
231 switch (kickflags) 243 switch (kickflags)
232 { 244 {
233 case 0: 245 case 0:
234 if (sp != null) 246 KickPresence(sp, reason);
235 { 247 break;
236 KickPresence(sp, Utils.BytesToString(reason)); 248 case 1:
237 }
238 else if (agentID == ALL_AGENTS)
239 {
240 m_scene.ForEachRootScenePresence(
241 delegate(ScenePresence p)
242 {
243 if (p.UUID != godID && (!m_scene.Permissions.IsGod(p.UUID)))
244 KickPresence(p, Utils.BytesToString(reason));
245 }
246 );
247 }
248 break;
249 case 1:
250 if (sp != null)
251 {
252 sp.AllowMovement = false; 249 sp.AllowMovement = false;
253 m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason)); 250 if(m_dialogModule != null)
254 m_dialogModule.SendAlertToUser(godID, "User Frozen"); 251 {
255 } 252 m_dialogModule.SendAlertToUser(sp.UUID, reason);
256 break; 253 m_dialogModule.SendAlertToUser(godID, "User Frozen");
257 case 2: 254 }
258 if (sp != null) 255 break;
259 { 256 case 2:
260 sp.AllowMovement = true; 257 sp.AllowMovement = true;
261 m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason)); 258 if(m_dialogModule != null)
262 m_dialogModule.SendAlertToUser(godID, "User Unfrozen"); 259 {
263 } 260 m_dialogModule.SendAlertToUser(sp.UUID, reason);
264 break; 261 m_dialogModule.SendAlertToUser(godID, "User Unfrozen");
265 default: 262 }
266 break; 263 break;
264 default:
265 break;
267 } 266 }
268 } 267 }
269 268
270 private void KickPresence(ScenePresence sp, string reason) 269 private void KickPresence(ScenePresence sp, string reason)
271 { 270 {
272 if (sp.IsChildAgent) 271 if(sp.IsDeleted || sp.IsChildAgent)
272 return;
273 sp.ControllingClient.Kick(reason);
274 sp.Scene.CloseAgent(sp.UUID, true);
275 }
276
277 public void GridKickUser(UUID agentID, string reason)
278 {
279 int godlevel = 240; // grid god default
280
281 ScenePresence sp = m_scene.GetScenePresence(agentID);
282 if (sp == null || sp.IsChildAgent)
283 {
284 IMessageTransferModule transferModule =
285 m_scene.RequestModuleInterface<IMessageTransferModule>();
286 if (transferModule != null)
287 {
288 m_log.DebugFormat("[GODS]: Sending nonlocal kill for agent {0}", agentID);
289 transferModule.SendInstantMessage(new GridInstantMessage(
290 m_scene, UUID_GRID_GOD, "GRID", agentID, (byte)250, false,
291 reason, UUID.Zero, true,
292 new Vector3(), new byte[] {0}, true),
293 delegate(bool success) {} );
294 }
295 return;
296 }
297
298 if(sp.IsDeleted)
299 return;
300
301 if (godlevel <= sp.GodController.GodLevel) // no god wars
302 {
303 if(m_dialogModule != null)
304 m_dialogModule.SendAlertToUser(sp.UUID, "GRID kick detected and ignored, kick reason: " + reason);
273 return; 305 return;
306 }
307
274 sp.ControllingClient.Kick(reason); 308 sp.ControllingClient.Kick(reason);
275 sp.Scene.CloseAgent(sp.UUID, true); 309 sp.Scene.CloseAgent(sp.UUID, true);
276 } 310 }
277 311
278 private void OnIncomingInstantMessage(GridInstantMessage msg) 312 private void OnIncomingInstantMessage(GridInstantMessage msg)
@@ -284,7 +318,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
284 UUID godID = new UUID(msg.fromAgentID); 318 UUID godID = new UUID(msg.fromAgentID);
285 uint kickMode = (uint)msg.binaryBucket[0]; 319 uint kickMode = (uint)msg.binaryBucket[0];
286 320
287 KickUser(godID, UUID.Zero, agentID, kickMode, Util.StringToBytes1024(reason)); 321 if(godID == UUID_GRID_GOD)
322 GridKickUser(agentID, reason);
323 else
324 KickUser(godID, agentID, kickMode, reason);
288 } 325 }
289 } 326 }
290 } 327 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
index b735c61..7f91a61 100644
--- a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
@@ -145,7 +145,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
145 return; 145 return;
146 146
147// m_log.Debug("[GROUPS]: Shutting down group module."); 147// m_log.Debug("[GROUPS]: Shutting down group module.");
148 148
149 lock (m_ClientMap) 149 lock (m_ClientMap)
150 { 150 {
151 m_ClientMap.Clear(); 151 m_ClientMap.Clear();
@@ -182,11 +182,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
182 m_ClientMap.Add(client.AgentId, client); 182 m_ClientMap.Add(client.AgentId, client);
183 } 183 }
184 } 184 }
185
186 GroupMembershipData[] updateGroups = new GroupMembershipData[1];
187 updateGroups[0] = osGroup;
188
189 client.SendGroupMembership(updateGroups);
190 } 185 }
191 186
192 private void OnAgentDataUpdateRequest(IClientAPI remoteClient, 187 private void OnAgentDataUpdateRequest(IClientAPI remoteClient,
@@ -237,6 +232,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
237 remote_client.SendGroupNameReply(groupUUID, groupnamereply); 232 remote_client.SendGroupNameReply(groupUUID, groupnamereply);
238 } 233 }
239 234
235 public GroupMembershipData[] GetMembershipData(UUID agentID)
236 {
237 GroupMembershipData[] updateGroups = new GroupMembershipData[1];
238 updateGroups[0] = osGroup;
239 return updateGroups;
240 }
241
242 public GroupMembershipData GetActiveMembershipData(UUID agentID)
243 {
244 return osGroup;
245 }
246
240 private void OnClientClosed(UUID agentID, Scene scene) 247 private void OnClientClosed(UUID agentID, Scene scene)
241 { 248 {
242 lock (m_ClientMap) 249 lock (m_ClientMap)
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
index a1b918a..16e2ec3 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
@@ -144,11 +144,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
144 foreach (Scene scene in m_Scenes) 144 foreach (Scene scene in m_Scenes)
145 { 145 {
146// m_log.DebugFormat( 146// m_log.DebugFormat(
147// "[HG INSTANT MESSAGE]: Looking for root agent {0} in {1}", 147// "[HG INSTANT MESSAGE]: Looking for root agent {0} in {1}",
148// toAgentID.ToString(), scene.RegionInfo.RegionName); 148// toAgentID.ToString(), scene.RegionInfo.RegionName);
149 ScenePresence sp = scene.GetScenePresence(toAgentID); 149 ScenePresence sp = scene.GetScenePresence(toAgentID);
150 if (sp != null && !sp.IsChildAgent) 150 if (sp != null && !sp.IsChildAgent && !sp.IsDeleted)
151 { 151 {
152 // Local message 152 // Local message
153// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); 153// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID);
154 sp.ControllingClient.SendInstantMessage(im); 154 sp.ControllingClient.SendInstantMessage(im);
@@ -159,25 +159,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
159 } 159 }
160 } 160 }
161 161
162 // try child avatar second
163 foreach (Scene scene in m_Scenes)
164 {
165// m_log.DebugFormat(
166// "[HG INSTANT MESSAGE]: Looking for child of {0} in {1}",
167// toAgentID, scene.RegionInfo.RegionName);
168 ScenePresence sp = scene.GetScenePresence(toAgentID);
169 if (sp != null)
170 {
171 // Local message
172// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID);
173 sp.ControllingClient.SendInstantMessage(im);
174
175 // Message sent
176 result(true);
177 return;
178 }
179 }
180
181// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); 162// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
182 // Is the user a local user? 163 // Is the user a local user?
183 string url = string.Empty; 164 string url = string.Empty;
@@ -224,7 +205,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
224 foreach (Scene scene in m_Scenes) 205 foreach (Scene scene in m_Scenes)
225 { 206 {
226 ScenePresence sp = scene.GetScenePresence(toAgentID); 207 ScenePresence sp = scene.GetScenePresence(toAgentID);
227 if(sp != null && !sp.IsChildAgent) 208 if(sp != null && !sp.IsChildAgent && !sp.IsDeleted)
228 { 209 {
229 scene.EventManager.TriggerIncomingInstantMessage(gim); 210 scene.EventManager.TriggerIncomingInstantMessage(gim);
230 successful = true; 211 successful = true;
@@ -310,7 +291,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
310 foreach (Scene scene in m_Scenes) 291 foreach (Scene scene in m_Scenes)
311 { 292 {
312 ScenePresence presence = scene.GetScenePresence(agentID); 293 ScenePresence presence = scene.GetScenePresence(agentID);
313 if (presence != null && !presence.IsChildAgent) 294 if (presence != null && !presence.IsChildAgent && !presence.IsDeleted)
314 return presence.ControllingClient; 295 return presence.ControllingClient;
315 } 296 }
316 } 297 }
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
index c33a296..71c0a8a 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
@@ -27,6 +27,7 @@
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Reflection; 29using System.Reflection;
30using System.Timers;
30using log4net; 31using log4net;
31using Mono.Addins; 32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
@@ -47,15 +48,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
47 /// <value> 48 /// <value>
48 /// Is this module enabled? 49 /// Is this module enabled?
49 /// </value> 50 /// </value>
50 private bool m_enabled = false; 51 protected bool m_enabled = false;
51 52
52 private readonly List<Scene> m_scenes = new List<Scene>(); 53 protected readonly List<Scene> m_scenes = new List<Scene>();
53 54
54 #region Region Module interface 55 #region Region Module interface
55 56
56 private IMessageTransferModule m_TransferModule = null; 57 protected IMessageTransferModule m_TransferModule = null;
57 58
58 public void Initialise(IConfigSource config) 59 public virtual void Initialise(IConfigSource config)
59 { 60 {
60 if (config.Configs["Messaging"] != null) 61 if (config.Configs["Messaging"] != null)
61 { 62 {
@@ -64,11 +65,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
64 "InstantMessageModule") 65 "InstantMessageModule")
65 return; 66 return;
66 } 67 }
67 68
68 m_enabled = true; 69 m_enabled = true;
69 } 70 }
70 71
71 public void AddRegion(Scene scene) 72 public virtual void AddRegion(Scene scene)
72 { 73 {
73 if (!m_enabled) 74 if (!m_enabled)
74 return; 75 return;
@@ -84,7 +85,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
84 } 85 }
85 } 86 }
86 87
87 public void RegionLoaded(Scene scene) 88 public virtual void RegionLoaded(Scene scene)
88 { 89 {
89 if (!m_enabled) 90 if (!m_enabled)
90 return; 91 return;
@@ -106,7 +107,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
106 } 107 }
107 } 108 }
108 109
109 public void RemoveRegion(Scene scene) 110 public virtual void RemoveRegion(Scene scene)
110 { 111 {
111 if (!m_enabled) 112 if (!m_enabled)
112 return; 113 return;
@@ -117,7 +118,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
117 } 118 }
118 } 119 }
119 120
120 void OnClientConnect(IClientCore client) 121 protected virtual void OnClientConnect(IClientCore client)
121 { 122 {
122 IClientIM clientIM; 123 IClientIM clientIM;
123 if (client.TryGet(out clientIM)) 124 if (client.TryGet(out clientIM))
@@ -126,27 +127,33 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
126 } 127 }
127 } 128 }
128 129
129 public void PostInitialise() 130 public virtual void PostInitialise()
130 { 131 {
131 } 132 }
132 133
133 public void Close() 134 public virtual void Close()
134 { 135 {
135 } 136 }
136 137
137 public string Name 138 public virtual string Name
138 { 139 {
139 get { return "InstantMessageModule"; } 140 get { return "InstantMessageModule"; }
140 } 141 }
141 142
142 public Type ReplaceableInterface 143 public virtual Type ReplaceableInterface
143 { 144 {
144 get { return null; } 145 get { return null; }
145 } 146 }
146 147
147 #endregion 148 #endregion
148 149/*
149 public void OnInstantMessage(IClientAPI client, GridInstantMessage im) 150 public virtual void OnViewerInstantMessage(IClientAPI client, GridInstantMessage im)
151 {
152 im.fromAgentName = client.FirstName + " " + client.LastName;
153 OnInstantMessage(client, im);
154 }
155*/
156 public virtual void OnInstantMessage(IClientAPI client, GridInstantMessage im)
150 { 157 {
151 byte dialog = im.dialog; 158 byte dialog = im.dialog;
152 159
@@ -159,10 +166,34 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
159 return; 166 return;
160 } 167 }
161 168
169 //DateTime dt = DateTime.UtcNow;
170
171 // Ticks from UtcNow, but make it look like local. Evil, huh?
172 //dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
173
174 //try
175 //{
176 // // Convert that to the PST timezone
177 // TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
178 // dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
179 //}
180 //catch
181 //{
182 // //m_log.Info("[OFFLINE MESSAGING]: No PST timezone found on this machine. Saving with local timestamp.");
183 //}
184
185 //// And make it look local again to fool the unix time util
186 //dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
187
188 // If client is null, this message comes from storage and IS offline
189 if (client != null)
190 im.offline = 0;
191
192 if (im.offline == 0)
193 im.timestamp = (uint)Util.UnixTimeSinceEpoch();
194
162 if (m_TransferModule != null) 195 if (m_TransferModule != null)
163 { 196 {
164 if (client != null)
165 im.fromAgentName = client.FirstName + " " + client.LastName;
166 m_TransferModule.SendInstantMessage(im, 197 m_TransferModule.SendInstantMessage(im,
167 delegate(bool success) 198 delegate(bool success)
168 { 199 {
@@ -193,7 +224,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
193 /// 224 ///
194 /// </summary> 225 /// </summary>
195 /// <param name="msg"></param> 226 /// <param name="msg"></param>
196 private void OnGridInstantMessage(GridInstantMessage msg) 227 protected virtual void OnGridInstantMessage(GridInstantMessage msg)
197 { 228 {
198 // Just call the Text IM handler above 229 // Just call the Text IM handler above
199 // This event won't be raised unless we have that agent, 230 // This event won't be raised unless we have that agent,
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index 2462ff8..efb9421 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -50,6 +50,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 51
52 private bool m_Enabled = false; 52 private bool m_Enabled = false;
53 protected string m_MessageKey = String.Empty;
53 protected List<Scene> m_Scenes = new List<Scene>(); 54 protected List<Scene> m_Scenes = new List<Scene>();
54 protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>(); 55 protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>();
55 56
@@ -69,14 +70,17 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
69 public virtual void Initialise(IConfigSource config) 70 public virtual void Initialise(IConfigSource config)
70 { 71 {
71 IConfig cnf = config.Configs["Messaging"]; 72 IConfig cnf = config.Configs["Messaging"];
72 if (cnf != null && cnf.GetString( 73 if (cnf != null)
73 "MessageTransferModule", "MessageTransferModule") !=
74 "MessageTransferModule")
75 { 74 {
76 m_log.Debug("[MESSAGE TRANSFER]: Disabled by configuration"); 75 if (cnf.GetString("MessageTransferModule",
77 return; 76 "MessageTransferModule") != "MessageTransferModule")
78 } 77 {
78 return;
79 }
79 80
81 m_MessageKey = cnf.GetString("MessageKey", String.Empty);
82 }
83 m_log.Debug("[MESSAGE TRANSFER]: Module enabled");
80 m_Enabled = true; 84 m_Enabled = true;
81 } 85 }
82 86
@@ -135,53 +139,45 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
135 { 139 {
136 UUID toAgentID = new UUID(im.toAgentID); 140 UUID toAgentID = new UUID(im.toAgentID);
137 141
142 if (toAgentID == UUID.Zero)
143 return;
144
145 IClientAPI client = null;
146
138 // Try root avatar only first 147 // Try root avatar only first
139 foreach (Scene scene in m_Scenes) 148 foreach (Scene scene in m_Scenes)
140 { 149 {
141// m_log.DebugFormat(
142// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
143// toAgentID.ToString(), scene.RegionInfo.RegionName);
144
145 ScenePresence sp = scene.GetScenePresence(toAgentID); 150 ScenePresence sp = scene.GetScenePresence(toAgentID);
146 if (sp != null && !sp.IsChildAgent) 151 if (sp != null && !sp.IsDeleted && sp.ControllingClient.IsActive)
147 { 152 {
148 // Local message 153 // actualy don't send via child agents
149// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); 154 // ims can be complex things, and not sure viewers will not mess up
150 155 if(sp.IsChildAgent)
151 sp.ControllingClient.SendInstantMessage(im); 156 continue;
152 157
153 // Message sent 158 client = sp.ControllingClient;
154 result(true); 159 if(!sp.IsChildAgent)
155 return; 160 break;
156 } 161 }
157 } 162 }
158 163
159 // try child avatar second 164 if(client != null)
160 foreach (Scene scene in m_Scenes)
161 { 165 {
162// m_log.DebugFormat( 166 // Local message
163// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); 167// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID);
164
165 ScenePresence sp = scene.GetScenePresence(toAgentID);
166 if (sp != null)
167 {
168 // Local message
169// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID);
170 168
171 sp.ControllingClient.SendInstantMessage(im); 169 client.SendInstantMessage(im);
172 170
173 // Message sent 171 // Message sent
174 result(true); 172 result(true);
175 return; 173 return;
176 }
177 } 174 }
178
179// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); 175// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
180 176
181 SendGridInstantMessageViaXMLRPC(im, result); 177 SendGridInstantMessageViaXMLRPC(im, result);
182 } 178 }
183 179
184 public void HandleUndeliverableMessage(GridInstantMessage im, MessageResultNotification result) 180 public virtual void HandleUndeliverableMessage(GridInstantMessage im, MessageResultNotification result)
185 { 181 {
186 UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage; 182 UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage;
187 183
@@ -211,10 +207,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
211 protected virtual XmlRpcResponse processXMLRPCGridInstantMessage(XmlRpcRequest request, IPEndPoint remoteClient) 207 protected virtual XmlRpcResponse processXMLRPCGridInstantMessage(XmlRpcRequest request, IPEndPoint remoteClient)
212 { 208 {
213 bool successful = false; 209 bool successful = false;
214 210
215 // TODO: For now, as IMs seem to be a bit unreliable on OSGrid, catch all exception that 211 // TODO: For now, as IMs seem to be a bit unreliable on OSGrid, catch all exception that
216 // happen here and aren't caught and log them. 212 // happen here and aren't caught and log them.
217 try 213 try
218 { 214 {
219 // various rational defaults 215 // various rational defaults
220 UUID fromAgentID = UUID.Zero; 216 UUID fromAgentID = UUID.Zero;
@@ -236,7 +232,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
236 float pos_z = 0; 232 float pos_z = 0;
237 //m_log.Info("Processing IM"); 233 //m_log.Info("Processing IM");
238 234
239
240 Hashtable requestData = (Hashtable)request.Params[0]; 235 Hashtable requestData = (Hashtable)request.Params[0];
241 // Check if it's got all the data 236 // Check if it's got all the data
242 if (requestData.ContainsKey("from_agent_id") 237 if (requestData.ContainsKey("from_agent_id")
@@ -249,6 +244,19 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
249 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id") 244 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id")
250 && requestData.ContainsKey("binary_bucket")) 245 && requestData.ContainsKey("binary_bucket"))
251 { 246 {
247 if (m_MessageKey != String.Empty)
248 {
249 XmlRpcResponse error_resp = new XmlRpcResponse();
250 Hashtable error_respdata = new Hashtable();
251 error_respdata["success"] = "FALSE";
252 error_resp.Value = error_respdata;
253
254 if (!requestData.Contains("message_key"))
255 return error_resp;
256 if (m_MessageKey != (string)requestData["message_key"])
257 return error_resp;
258 }
259
252 // Do the easy way of validating the UUIDs 260 // Do the easy way of validating the UUIDs
253 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID); 261 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID);
254 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID); 262 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID);
@@ -382,7 +390,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
382 gim.Position = Position; 390 gim.Position = Position;
383 gim.binaryBucket = binaryBucket; 391 gim.binaryBucket = binaryBucket;
384 392
385
386 // Trigger the Instant message in the scene. 393 // Trigger the Instant message in the scene.
387 foreach (Scene scene in m_Scenes) 394 foreach (Scene scene in m_Scenes)
388 { 395 {
@@ -425,104 +432,191 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
425 return resp; 432 return resp;
426 } 433 }
427 434
435
428 /// <summary> 436 /// <summary>
429 /// delegate for sending a grid instant message asynchronously 437 /// delegate for sending a grid instant message asynchronously
430 /// </summary> 438 /// </summary>
431 public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result); 439 private delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result);
440
441 private class GIM {
442 public GridInstantMessage im;
443 public MessageResultNotification result;
444 };
432 445
433 protected virtual void GridInstantMessageCompleted(IAsyncResult iar) 446 private Queue<GIM> pendingInstantMessages = new Queue<GIM>();
447 private int numInstantMessageThreads = 0;
448
449 private void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
434 { 450 {
435 GridInstantMessageDelegate icon = 451 lock (pendingInstantMessages) {
436 (GridInstantMessageDelegate)iar.AsyncState; 452 if (numInstantMessageThreads >= 4) {
437 icon.EndInvoke(iar); 453 GIM gim = new GIM();
454 gim.im = im;
455 gim.result = result;
456 pendingInstantMessages.Enqueue(gim);
457 } else {
458 ++ numInstantMessageThreads;
459 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: ++numInstantMessageThreads={0}", numInstantMessageThreads);
460 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsyncMain;
461 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
462 }
463 }
438 } 464 }
439 465
440 466
441 protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) 467 private void GridInstantMessageCompleted(IAsyncResult iar)
442 { 468 {
443 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; 469 GridInstantMessageDelegate d = (GridInstantMessageDelegate)iar.AsyncState;
444 470 d.EndInvoke(iar);
445 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
446 } 471 }
447 472
448 /// <summary> 473 /// <summary>
449 /// Internal SendGridInstantMessage over XMLRPC method. 474 /// Internal SendGridInstantMessage over XMLRPC method.
450 /// </summary> 475 /// </summary>
451 /// <remarks> 476
452 /// This is called from within a dedicated thread. 477 /// <param name="prevRegionHandle">
453 /// </remarks> 478 /// Pass in 0 the first time this method is called. It will be called recursively with the last
454 private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result) 479 /// regionhandle tried
480 /// </param>
481 private void SendGridInstantMessageViaXMLRPCAsyncMain(GridInstantMessage im, MessageResultNotification result)
482 {
483 GIM gim;
484 do {
485 try {
486 SendGridInstantMessageViaXMLRPCAsync(im, result, UUID.Zero);
487 } catch (Exception e) {
488 m_log.Error("[SendGridInstantMessageViaXMLRPC]: exception " + e.Message);
489 }
490 lock (pendingInstantMessages) {
491 if (pendingInstantMessages.Count > 0) {
492 gim = pendingInstantMessages.Dequeue();
493 im = gim.im;
494 result = gim.result;
495 } else {
496 gim = null;
497 -- numInstantMessageThreads;
498 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: --numInstantMessageThreads={0}", numInstantMessageThreads);
499 }
500 }
501 } while (gim != null);
502 }
503
504 private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID)
455 { 505 {
506
456 UUID toAgentID = new UUID(im.toAgentID); 507 UUID toAgentID = new UUID(im.toAgentID);
457 UUID regionID; 508 PresenceInfo upd = null;
458 bool needToLookupAgent; 509 bool lookupAgent = false;
459 510
460 lock (m_UserRegionMap) 511 lock (m_UserRegionMap)
461 needToLookupAgent = !m_UserRegionMap.TryGetValue(toAgentID, out regionID);
462
463 while (true)
464 { 512 {
465 if (needToLookupAgent) 513 if (m_UserRegionMap.ContainsKey(toAgentID))
466 { 514 {
467 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); 515 upd = new PresenceInfo();
468 516 upd.RegionID = m_UserRegionMap[toAgentID];
469 UUID foundRegionID = UUID.Zero;
470 517
471 if (presences != null) 518 // We need to compare the current regionhandle with the previous region handle
519 // or the recursive loop will never end because it will never try to lookup the agent again
520 if (prevRegionID == upd.RegionID)
472 { 521 {
473 foreach (PresenceInfo p in presences) 522 lookupAgent = true;
474 {
475 if (p.RegionID != UUID.Zero)
476 {
477 foundRegionID = p.RegionID;
478 break;
479 }
480 }
481 } 523 }
482
483 // If not found or the found region is the same as the last lookup, then message is undeliverable
484 if (foundRegionID == UUID.Zero || foundRegionID == regionID)
485 break;
486 else
487 regionID = foundRegionID;
488 } 524 }
489 525 else
490 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, regionID);
491 if (reginfo == null)
492 { 526 {
493 m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", regionID); 527 lookupAgent = true;
494 break;
495 } 528 }
529 }
496 530
497 // Try to send the message to the agent via the retrieved region.
498 Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
499 msgdata["region_handle"] = 0;
500 bool imresult = doIMSending(reginfo, msgdata);
501 531
502 // If the message delivery was successful, then cache the entry. 532 // Are we needing to look-up an agent?
503 if (imresult) 533 if (lookupAgent)
534 {
535 // Non-cached user agent lookup.
536 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() });
537 if (presences != null && presences.Length > 0)
504 { 538 {
505 lock (m_UserRegionMap) 539 foreach (PresenceInfo p in presences)
506 { 540 {
507 m_UserRegionMap[toAgentID] = regionID; 541 if (p.RegionID != UUID.Zero)
542 {
543 upd = p;
544 break;
545 }
508 } 546 }
509 result(true);
510 return;
511 } 547 }
512 548
513 // If we reach this point in the first iteration of the while, then we may have unsuccessfully tried 549 if (upd != null)
514 // to use a locally cached region ID. All subsequent attempts need to lookup agent details from 550 {
515 // the presence service. 551 // check if we've tried this before..
516 needToLookupAgent = true; 552 // This is one way to end the recursive loop
553 //
554 if (upd.RegionID == prevRegionID)
555 {
556 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
557 HandleUndeliverableMessage(im, result);
558 return;
559 }
560 }
561 else
562 {
563 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
564 HandleUndeliverableMessage(im, result);
565 return;
566 }
517 } 567 }
518 568
519 // If we reached this point then the message was not deliverable. Remove the bad cache entry and 569 if (upd != null)
520 // signal the delivery failure. 570 {
521 lock (m_UserRegionMap) 571 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(UUID.Zero,
522 m_UserRegionMap.Remove(toAgentID); 572 upd.RegionID);
573 if (reginfo != null)
574 {
575 Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
576 // Not actually used anymore, left in for compatibility
577 // Remove at next interface change
578 //
579 msgdata["region_handle"] = 0;
580 bool imresult = doIMSending(reginfo, msgdata);
581 if (imresult)
582 {
583 // IM delivery successful, so store the Agent's location in our local cache.
584 lock (m_UserRegionMap)
585 {
586 if (m_UserRegionMap.ContainsKey(toAgentID))
587 {
588 m_UserRegionMap[toAgentID] = upd.RegionID;
589 }
590 else
591 {
592 m_UserRegionMap.Add(toAgentID, upd.RegionID);
593 }
594 }
595 result(true);
596 }
597 else
598 {
599 // try again, but lookup user this time.
600 // Warning, this must call the Async version
601 // of this method or we'll be making thousands of threads
602 // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync
603 // The version that spawns the thread is SendGridInstantMessageViaXMLRPC
523 604
524 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); 605 // This is recursive!!!!!
525 HandleUndeliverableMessage(im, result); 606 SendGridInstantMessageViaXMLRPCAsync(im, result,
607 upd.RegionID);
608 }
609 }
610 else
611 {
612 m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID);
613 HandleUndeliverableMessage(im, result);
614 }
615 }
616 else
617 {
618 HandleUndeliverableMessage(im, result);
619 }
526 } 620 }
527 621
528 /// <summary> 622 /// <summary>
@@ -622,8 +716,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
622 gim["position_z"] = msg.Position.Z.ToString(); 716 gim["position_z"] = msg.Position.Z.ToString();
623 gim["region_id"] = new UUID(msg.RegionID).ToString(); 717 gim["region_id"] = new UUID(msg.RegionID).ToString();
624 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None); 718 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None);
719 if (m_MessageKey != String.Empty)
720 gim["message_key"] = m_MessageKey;
625 return gim; 721 return gim;
626 } 722 }
627
628 } 723 }
629} 724}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs
index 315d372..2d57193 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs
@@ -118,11 +118,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
118 { 118 {
119 get { return null; } 119 get { return null; }
120 } 120 }
121 121
122 public void Close() 122 public void Close()
123 { 123 {
124 } 124 }
125 125
126 private void OnNewClient(IClientAPI client) 126 private void OnNewClient(IClientAPI client)
127 { 127 {
128 client.OnMuteListRequest += OnMuteListRequest; 128 client.OnMuteListRequest += OnMuteListRequest;
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModuleTst.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModuleTst.cs
new file mode 100644
index 0000000..6857f35
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModuleTst.cs
@@ -0,0 +1,229 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Reflection;
30using System.Text;
31using log4net;
32using Nini.Config;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Framework.Servers;
36using OpenSim.Framework.Client;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using Mono.Addins;
40
41using OpenSim.Server.Base;
42using OpenSim.Services.Interfaces;
43
44namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MuteListModuleTst")]
47 public class MuteListModuleTst : ISharedRegionModule
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(
50 MethodBase.GetCurrentMethod().DeclaringType);
51
52 protected bool m_Enabled = false;
53 protected List<Scene> m_SceneList = new List<Scene>();
54 protected IMuteListService m_service = null;
55
56 public void Initialise(IConfigSource config)
57 {
58 IConfig cnf = config.Configs["Messaging"];
59 if (cnf == null)
60 return;
61
62 if (cnf.GetString("MuteListModule", "None") != "MuteListModuleTst")
63 return;
64
65 m_Enabled = true;
66 }
67
68 public void AddRegion(Scene scene)
69 {
70 }
71
72 public void RegionLoaded(Scene scene)
73 {
74 if (!m_Enabled)
75 return;
76
77 IXfer xfer = scene.RequestModuleInterface<IXfer>();
78 if (xfer == null)
79 {
80 m_log.ErrorFormat("[MuteListModuleTst]: Xfer not availble in region {0}. Module Disabled", scene.Name);
81 m_Enabled = false;
82 return;
83 }
84
85 IMuteListService srv = scene.RequestModuleInterface<IMuteListService>();
86 if(srv == null)
87 {
88 m_log.ErrorFormat("[MuteListModuleTst]: MuteListService not availble in region {0}. Module Disabled", scene.Name);
89 m_Enabled = false;
90 return;
91 }
92 lock (m_SceneList)
93 {
94 if(m_service == null)
95 m_service = srv;
96 m_SceneList.Add(scene);
97 scene.EventManager.OnNewClient += OnNewClient;
98 }
99 }
100
101 public void RemoveRegion(Scene scene)
102 {
103 lock (m_SceneList)
104 {
105 if(m_SceneList.Contains(scene))
106 {
107 m_SceneList.Remove(scene);
108 scene.EventManager.OnNewClient -= OnNewClient;
109 }
110 }
111 }
112
113 public void PostInitialise()
114 {
115 if (!m_Enabled)
116 return;
117
118 m_log.Debug("[MuteListModuleTst]: enabled");
119 }
120
121 public string Name
122 {
123 get { return "MuteListModuleTst"; }
124 }
125
126 public Type ReplaceableInterface
127 {
128 get { return null; }
129 }
130
131 public void Close()
132 {
133 }
134
135 private void OnNewClient(IClientAPI client)
136 {
137 client.OnMuteListRequest += OnMuteListRequest;
138 client.OnUpdateMuteListEntry += OnUpdateMuteListEntry;
139 client.OnRemoveMuteListEntry += OnRemoveMuteListEntry;
140 }
141
142 private void OnMuteListRequest(IClientAPI client, uint crc)
143 {
144 if (!m_Enabled)
145 {
146 if(crc == 0)
147 client.SendEmpytMuteList();
148 else
149 client.SendUseCachedMuteList();
150 return;
151 }
152
153 IXfer xfer = client.Scene.RequestModuleInterface<IXfer>();
154 if (xfer == null)
155 {
156 if(crc == 0)
157 client.SendEmpytMuteList();
158 else
159 client.SendUseCachedMuteList();
160 return;
161 }
162
163 Byte[] data = m_service.MuteListRequest(client.AgentId, crc);
164 if (data == null)
165 {
166 if(crc == 0)
167 client.SendEmpytMuteList();
168 else
169 client.SendUseCachedMuteList();
170 return;
171 }
172
173 if (data.Length == 0)
174 {
175 client.SendEmpytMuteList();
176 return;
177 }
178
179 if (data.Length == 1)
180 {
181 if(crc == 0)
182 client.SendEmpytMuteList();
183 else
184 client.SendUseCachedMuteList();
185 return;
186 }
187
188 string filename = "mutes" + client.AgentId.ToString();
189 xfer.AddNewFile(filename, data);
190 client.SendMuteListUpdate(filename);
191 }
192
193 private void OnUpdateMuteListEntry(IClientAPI client, UUID muteID, string muteName, int muteType, uint muteFlags)
194 {
195 if (!m_Enabled)
196 return;
197
198 UUID agentID = client.AgentId;
199 if(muteType == 1) // agent
200 {
201 if(agentID == muteID)
202 return;
203 if(m_SceneList[0].Permissions.IsAdministrator(muteID))
204 {
205 OnMuteListRequest(client, 0);
206 return;
207 }
208 }
209
210 MuteData mute = new MuteData();
211 mute.AgentID = agentID;
212 mute.MuteID = muteID;
213 mute.MuteName = muteName;
214 mute.MuteType = muteType;
215 mute.MuteFlags = (int)muteFlags;
216 mute.Stamp = Util.UnixTimeSinceEpoch();
217
218 m_service.UpdateMute(mute);
219 }
220
221 private void OnRemoveMuteListEntry(IClientAPI client, UUID muteID, string muteName)
222 {
223 if (!m_Enabled)
224 return;
225 m_service.RemoveMute(client.AgentId, muteID, muteName);
226 }
227 }
228}
229
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index 9cdb1c2..315ce1b 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -39,16 +39,25 @@ using OpenSim.Region.Framework.Scenes;
39 39
40namespace OpenSim.Region.CoreModules.Avatar.InstantMessage 40namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
41{ 41{
42 public struct SendReply
43 {
44 public bool Success;
45 public string Message;
46 public int Disposition;
47 }
48
42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OfflineMessageModule")] 49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OfflineMessageModule")]
43 public class OfflineMessageModule : ISharedRegionModule 50 public class OfflineMessageModule : ISharedRegionModule
44 { 51 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 53
47 private bool enabled = true; 54 private bool enabled = true;
55 private bool m_UseNewAvnCode = false;
48 private List<Scene> m_SceneList = new List<Scene>(); 56 private List<Scene> m_SceneList = new List<Scene>();
49 private string m_RestURL = String.Empty; 57 private string m_RestURL = String.Empty;
50 IMessageTransferModule m_TransferModule = null; 58 IMessageTransferModule m_TransferModule = null;
51 private bool m_ForwardOfflineGroupMessages = true; 59 private bool m_ForwardOfflineGroupMessages = true;
60 private Dictionary<IClientAPI, List<UUID>> m_repliesSent= new Dictionary<IClientAPI, List<UUID>>();
52 61
53 public void Initialise(IConfigSource config) 62 public void Initialise(IConfigSource config)
54 { 63 {
@@ -74,6 +83,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
74 } 83 }
75 84
76 m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", m_ForwardOfflineGroupMessages); 85 m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", m_ForwardOfflineGroupMessages);
86 m_UseNewAvnCode = cnf.GetBoolean("UseNewAvnCode", m_UseNewAvnCode);
77 } 87 }
78 88
79 public void AddRegion(Scene scene) 89 public void AddRegion(Scene scene)
@@ -138,7 +148,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
138 { 148 {
139 get { return null; } 149 get { return null; }
140 } 150 }
141 151
142 public void Close() 152 public void Close()
143 { 153 {
144 } 154 }
@@ -168,11 +178,21 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
168 private void OnNewClient(IClientAPI client) 178 private void OnNewClient(IClientAPI client)
169 { 179 {
170 client.OnRetrieveInstantMessages += RetrieveInstantMessages; 180 client.OnRetrieveInstantMessages += RetrieveInstantMessages;
181 client.OnLogout += OnClientLoggedOut;
182 }
183
184 public void OnClientLoggedOut(IClientAPI client)
185 {
186 m_repliesSent.Remove(client);
171 } 187 }
172 188
173 private void RetrieveInstantMessages(IClientAPI client) 189 private void RetrieveInstantMessages(IClientAPI client)
174 { 190 {
175 if (m_RestURL != "") 191 if (m_RestURL == String.Empty)
192 {
193 return;
194 }
195 else
176 { 196 {
177 m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId); 197 m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId);
178 198
@@ -180,28 +200,28 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
180 = SynchronousRestObjectRequester.MakeRequest<UUID, List<GridInstantMessage>>( 200 = SynchronousRestObjectRequester.MakeRequest<UUID, List<GridInstantMessage>>(
181 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId); 201 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId);
182 202
183 if (msglist == null) 203 if (msglist != null)
184 {
185 m_log.WarnFormat("[OFFLINE MESSAGING]: WARNING null message list.");
186 return;
187 }
188
189 foreach (GridInstantMessage im in msglist)
190 { 204 {
191 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered) 205 foreach (GridInstantMessage im in msglist)
192 // send it directly or else the item will be given twice
193 client.SendInstantMessage(im);
194 else
195 { 206 {
196 // Send through scene event manager so all modules get a chance 207 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
197 // to look at this message before it gets delivered. 208 // send it directly or else the item will be given twice
198 // 209 client.SendInstantMessage(im);
199 // Needed for proper state management for stored group 210 else
200 // invitations 211 {
201 // 212 // Send through scene event manager so all modules get a chance
202 Scene s = FindScene(client.AgentId); 213 // to look at this message before it gets delivered.
203 if (s != null) 214 //
204 s.EventManager.TriggerIncomingInstantMessage(im); 215 // Needed for proper state management for stored group
216 // invitations
217 //
218
219 im.offline = 1;
220
221 Scene s = FindScene(client.AgentId);
222 if (s != null)
223 s.EventManager.TriggerIncomingInstantMessage(im);
224 }
205 } 225 }
206 } 226 }
207 } 227 }
@@ -213,7 +233,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
213 im.dialog != (byte)InstantMessageDialog.MessageFromAgent && 233 im.dialog != (byte)InstantMessageDialog.MessageFromAgent &&
214 im.dialog != (byte)InstantMessageDialog.GroupNotice && 234 im.dialog != (byte)InstantMessageDialog.GroupNotice &&
215 im.dialog != (byte)InstantMessageDialog.GroupInvitation && 235 im.dialog != (byte)InstantMessageDialog.GroupInvitation &&
216 im.dialog != (byte)InstantMessageDialog.InventoryOffered) 236 im.dialog != (byte)InstantMessageDialog.InventoryOffered &&
237 im.dialog != (byte)InstantMessageDialog.TaskInventoryOffered)
217 { 238 {
218 return; 239 return;
219 } 240 }
@@ -225,22 +246,73 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
225 return; 246 return;
226 } 247 }
227 248
228 bool success = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>( 249 if(m_UseNewAvnCode)
229 "POST", m_RestURL+"/SaveMessage/", im, 10000); 250 {
251 Scene scene = FindScene(new UUID(im.fromAgentID));
252 if (scene == null)
253 scene = m_SceneList[0];
230 254
231 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) 255 UUID scopeID = scene.RegionInfo.ScopeID;
256 SendReply reply = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, SendReply>(
257 "POST", m_RestURL+"/SaveMessage/?scope=" + scopeID.ToString(), im, 20000);
258
259 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
260 {
261 IClientAPI client = FindClient(new UUID(im.fromAgentID));
262 if (client == null)
263 return;
264
265 if (string.IsNullOrEmpty(reply.Message))
266 reply.Message = "User is not logged in. " + (reply.Success ? "Message saved." : "Message not saved");
267
268 bool sendReply = true;
269
270 switch (reply.Disposition)
271 {
272 case 0: // Normal
273 break;
274 case 1: // Only once per user
275 if (m_repliesSent.ContainsKey(client) && m_repliesSent[client].Contains(new UUID(im.toAgentID)))
276 sendReply = false;
277 else
278 {
279 if (!m_repliesSent.ContainsKey(client))
280 m_repliesSent[client] = new List<UUID>();
281 m_repliesSent[client].Add(new UUID(im.toAgentID));
282 }
283 break;
284 }
285
286 if (sendReply)
287 {
288 client.SendInstantMessage(new GridInstantMessage(
289 null, new UUID(im.toAgentID),
290 "System", new UUID(im.fromAgentID),
291 (byte)InstantMessageDialog.MessageFromAgent,
292 reply.Message,
293 false, new Vector3()));
294 }
295 }
296 }
297 else
232 { 298 {
233 IClientAPI client = FindClient(new UUID(im.fromAgentID)); 299 bool success = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>(
234 if (client == null) 300 "POST", m_RestURL+"/SaveMessage/", im, 20000);
235 return; 301
302 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
303 {
304 IClientAPI client = FindClient(new UUID(im.fromAgentID));
305 if (client == null)
306 return;
236 307
237 client.SendInstantMessage(new GridInstantMessage( 308 client.SendInstantMessage(new GridInstantMessage(
238 null, new UUID(im.toAgentID), 309 null, new UUID(im.toAgentID),
239 "System", new UUID(im.fromAgentID), 310 "System", new UUID(im.fromAgentID),
240 (byte)InstantMessageDialog.MessageFromAgent, 311 (byte)InstantMessageDialog.MessageFromAgent,
241 "User is not logged in. "+ 312 "User is not logged in. "+
242 (success ? "Message saved." : "Message not saved"), 313 (success ? "Message saved." : "Message not saved"),
243 false, new Vector3())); 314 false, new Vector3()));
315 }
244 } 316 }
245 } 317 }
246 } 318 }
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/XMuteModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/XMuteModule.cs
new file mode 100644
index 0000000..b61e848
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/XMuteModule.cs
@@ -0,0 +1,239 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Reflection;
30using System.Text;
31using log4net;
32using Nini.Config;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37using Mono.Addins;
38using OpenSim.Data.MySQL;
39using MySql.Data.MySqlClient;
40
41
42namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XMute")]
45 public class XMuteModule : ISharedRegionModule
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 protected bool m_Enabled = true;
51 protected List<Scene> m_SceneList = new List<Scene>();
52 protected MuteTableHandler m_MuteTable;
53 protected string m_DatabaseConnect;
54
55 public void Initialise(IConfigSource config)
56 {
57 IConfig cnf = config.Configs["Messaging"];
58 if (cnf == null)
59 {
60 m_Enabled = false;
61 return;
62 }
63
64 if (cnf.GetString("MuteListModule", "None") !=
65 "XMute")
66 {
67 m_Enabled = false;
68 return;
69 }
70
71 m_DatabaseConnect = cnf.GetString("MuteDatabaseConnect", String.Empty);
72 if (m_DatabaseConnect == String.Empty)
73 {
74 m_log.Debug("[XMute]: MuteDatabaseConnect missing or empty");
75 m_Enabled = false;
76 return;
77 }
78
79 m_MuteTable = new MuteTableHandler(
80 m_DatabaseConnect, "XMute", String.Empty);
81 }
82
83 public void AddRegion(Scene scene)
84 {
85 if (!m_Enabled)
86 return;
87
88 lock (m_SceneList)
89 {
90 m_SceneList.Add(scene);
91
92 scene.EventManager.OnNewClient += OnNewClient;
93 }
94 }
95
96 public void RegionLoaded(Scene scene)
97 {
98 }
99
100 public void RemoveRegion(Scene scene)
101 {
102 if (!m_Enabled)
103 return;
104
105 lock (m_SceneList)
106 {
107 m_SceneList.Remove(scene);
108 }
109 }
110
111 public void PostInitialise()
112 {
113 if (!m_Enabled)
114 return;
115
116 m_log.Debug("[XMute]: Mute list enabled");
117 }
118
119 public string Name
120 {
121 get { return "XMuteModule"; }
122 }
123
124 public Type ReplaceableInterface
125 {
126 get { return null; }
127 }
128
129 public void Close()
130 {
131 }
132
133 private void OnNewClient(IClientAPI client)
134 {
135 client.OnMuteListRequest += OnMuteListRequest;
136 client.OnUpdateMuteListEntry += OnUpdateMuteListEntry;
137 client.OnRemoveMuteListEntry += OnRemoveMuteListEntry;
138 }
139
140 private void OnMuteListRequest(IClientAPI client, uint crc)
141 {
142 string filename = "mutes"+client.AgentId.ToString();
143
144 IXfer xfer = client.Scene.RequestModuleInterface<IXfer>();
145 if (xfer != null)
146 {
147 MuteData[] data = m_MuteTable.Get("AgentID", client.AgentId.ToString());
148 if (data == null || data.Length == 0)
149 {
150 xfer.AddNewFile(filename, new Byte[0]);
151 }
152 else
153 {
154 StringBuilder sb = new StringBuilder(1024);
155
156 foreach (MuteData d in data)
157 sb.AppendFormat("{0} {1} {2}|{3}\n",
158 d.MuteType,
159 d.MuteID.ToString(),
160 d.MuteName,
161 d.MuteFlags);
162
163 Byte[] filedata = Util.UTF8.GetBytes(sb.ToString());
164
165 uint dataCrc = Crc32.Compute(filedata);
166
167 if (dataCrc == crc)
168 {
169 client.SendUseCachedMuteList();
170 return;
171 }
172
173 xfer.AddNewFile(filename, filedata);
174 }
175
176 client.SendMuteListUpdate(filename);
177 }
178 }
179
180 private void OnUpdateMuteListEntry(IClientAPI client, UUID muteID, string muteName, int muteType, uint muteFlags)
181 {
182 MuteData mute = new MuteData();
183
184 mute.AgentID = client.AgentId;
185 mute.MuteID = muteID;
186 mute.MuteName = muteName;
187 mute.MuteType = muteType;
188 mute.MuteFlags = (int)muteFlags;
189 mute.Stamp = Util.UnixTimeSinceEpoch();
190
191 m_MuteTable.Store(mute);
192 }
193
194 private void OnRemoveMuteListEntry(IClientAPI client, UUID muteID, string muteName)
195 {
196 m_MuteTable.Delete(new string[] { "AgentID",
197 "MuteID",
198 "MuteName" },
199 new string[] { client.AgentId.ToString(),
200 muteID.ToString(),
201 muteName });
202 }
203 }
204
205 public class MuteTableHandler : MySQLGenericTableHandler<MuteData>
206 {
207 public MuteTableHandler(string conn, string realm, string m) : base(conn, realm, m)
208 {
209 }
210
211 public bool Delete(string[] fields, string[] val)
212 {
213 if (fields.Length != val.Length)
214 return false;
215
216 using (MySqlCommand cmd = new MySqlCommand())
217 {
218 string text = String.Format("delete from {0} where ", m_Realm);
219
220 List<string> terms = new List<string>();
221
222 for (int i = 0 ; i < fields.Length ; i++)
223 {
224 terms.Add(String.Format("{0} = ?{0}", fields[i]));
225 cmd.Parameters.AddWithValue("?" + fields[i], val[i]);
226 }
227
228 text += string.Join(" and ", terms.ToArray());
229
230 cmd.CommandText = text;
231
232 if (ExecuteNonQuery(cmd) > 0)
233 return true;
234 return false;
235 }
236 }
237 }
238}
239
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index 4a06fd1..1e21b74 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -56,7 +56,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
56 /// bumps here should be compatible. 56 /// bumps here should be compatible.
57 /// </summary> 57 /// </summary>
58 public static int MAX_MAJOR_VERSION = 1; 58 public static int MAX_MAJOR_VERSION = 1;
59 59
60 protected TarArchiveReader archive; 60 protected TarArchiveReader archive;
61 61
62 private UserAccount m_userInfo; 62 private UserAccount m_userInfo;
@@ -66,7 +66,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
66 /// ID of this request 66 /// ID of this request
67 /// </value> 67 /// </value>
68 protected UUID m_id; 68 protected UUID m_id;
69 69
70 /// <summary> 70 /// <summary>
71 /// Do we want to merge this load with existing inventory? 71 /// Do we want to merge this load with existing inventory?
72 /// </summary> 72 /// </summary>
@@ -82,46 +82,49 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
82 /// The stream from which the inventory archive will be loaded. 82 /// The stream from which the inventory archive will be loaded.
83 /// </value> 83 /// </value>
84 private Stream m_loadStream; 84 private Stream m_loadStream;
85 85
86 /// <summary> 86 /// <summary>
87 /// Has the control file been loaded for this archive? 87 /// Has the control file been loaded for this archive?
88 /// </summary> 88 /// </summary>
89 public bool ControlFileLoaded { get; private set; } 89 public bool ControlFileLoaded { get; private set; }
90 90
91 /// <summary> 91 /// <summary>
92 /// Do we want to enforce the check. IAR versions before 0.2 and 1.1 do not guarantee this order, so we can't 92 /// Do we want to enforce the check. IAR versions before 0.2 and 1.1 do not guarantee this order, so we can't
93 /// enforce. 93 /// enforce.
94 /// </summary> 94 /// </summary>
95 public bool EnforceControlFileCheck { get; private set; } 95 public bool EnforceControlFileCheck { get; private set; }
96 96
97 protected bool m_assetsLoaded; 97 protected bool m_assetsLoaded;
98 protected bool m_inventoryNodesLoaded; 98 protected bool m_inventoryNodesLoaded;
99 99
100 protected int m_successfulAssetRestores; 100 protected int m_successfulAssetRestores;
101 protected int m_failedAssetRestores; 101 protected int m_failedAssetRestores;
102 protected int m_successfulItemRestores; 102 protected int m_successfulItemRestores;
103 103
104 /// <summary> 104 /// <summary>
105 /// Root destination folder for the IAR load. 105 /// Root destination folder for the IAR load.
106 /// </summary> 106 /// </summary>
107 protected InventoryFolderBase m_rootDestinationFolder; 107 protected InventoryFolderBase m_rootDestinationFolder;
108 108
109 /// <summary> 109 /// <summary>
110 /// Inventory nodes loaded from the iar. 110 /// Inventory nodes loaded from the iar.
111 /// </summary> 111 /// </summary>
112 protected HashSet<InventoryNodeBase> m_loadedNodes = new HashSet<InventoryNodeBase>(); 112 protected Dictionary<UUID, InventoryNodeBase> m_loadedNodes = new Dictionary<UUID, InventoryNodeBase>();
113 113
114 /// <summary> 114 /// <summary>
115 /// In order to load identically named folders, we need to keep track of the folders that we have already 115 /// In order to load identically named folders, we need to keep track of the folders that we have already
116 /// resolved. 116 /// resolved.
117 /// </summary> 117 /// </summary>
118 Dictionary <string, InventoryFolderBase> m_resolvedFolders = new Dictionary<string, InventoryFolderBase>(); 118 Dictionary <string, InventoryFolderBase> m_resolvedFolders = new Dictionary<string, InventoryFolderBase>();
119 119
120 /// <summary> 120 /// <summary>
121 /// Record the creator id that should be associated with an asset. This is used to adjust asset creator ids 121 /// Record the creator id that should be associated with an asset. This is used to adjust asset creator ids
122 /// after OSP resolution (since OSP creators are only stored in the item 122 /// after OSP resolution (since OSP creators are only stored in the item
123 /// </summary> 123 /// </summary>
124 protected Dictionary<UUID, UUID> m_creatorIdForAssetId = new Dictionary<UUID, UUID>(); 124 protected Dictionary<UUID, UUID> m_creatorIdForAssetId = new Dictionary<UUID, UUID>();
125 protected Dictionary<UUID, UUID> m_itemIDs = new Dictionary<UUID, UUID>();
126 protected List<InventoryItemBase> m_invLinks = new List<InventoryItemBase>();
127 protected Dictionary<UUID, InventoryNodeBase> m_invLinksFolders = new Dictionary<UUID, InventoryNodeBase>();
125 128
126 public InventoryArchiveReadRequest( 129 public InventoryArchiveReadRequest(
127 IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, string loadPath, bool merge) 130 IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, string loadPath, bool merge)
@@ -163,9 +166,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
163 m_invPath = invPath; 166 m_invPath = invPath;
164 m_loadStream = loadStream; 167 m_loadStream = loadStream;
165 m_module = module; 168 m_module = module;
166 169
167 // FIXME: Do not perform this check since older versions of OpenSim do save the control file after other things 170 // FIXME: Do not perform this check since older versions of OpenSim do save the control file after other things
168 // (I thought they weren't). We will need to bump the version number and perform this check on all 171 // (I thought they weren't). We will need to bump the version number and perform this check on all
169 // subsequent IAR versions only 172 // subsequent IAR versions only
170 ControlFileLoaded = true; 173 ControlFileLoaded = true;
171 } 174 }
@@ -181,26 +184,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
181 /// returned 184 /// returned
182 /// </returns> 185 /// </returns>
183 /// <exception cref="System.Exception">Thrown if load fails.</exception> 186 /// <exception cref="System.Exception">Thrown if load fails.</exception>
184 public HashSet<InventoryNodeBase> Execute() 187 public Dictionary<UUID,InventoryNodeBase> Execute()
185 { 188 {
186 try 189 try
187 { 190 {
188 Exception reportedException = null; 191 Exception reportedException = null;
189 192
190 string filePath = "ERROR"; 193 string filePath = "ERROR";
191 194
192 List<InventoryFolderBase> folderCandidates 195 List<InventoryFolderBase> folderCandidates
193 = InventoryArchiveUtils.FindFoldersByPath( 196 = InventoryArchiveUtils.FindFoldersByPath(
194 m_InventoryService, m_userInfo.PrincipalID, m_invPath); 197 m_InventoryService, m_userInfo.PrincipalID, m_invPath);
195 198
196 if (folderCandidates.Count == 0) 199 if (folderCandidates.Count == 0)
197 { 200 {
198 // Possibly provide an option later on to automatically create this folder if it does not exist 201 // Possibly provide an option later on to automatically create this folder if it does not exist
199 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath); 202 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath);
200 203
201 return m_loadedNodes; 204 return m_loadedNodes;
202 } 205 }
203 206
204 m_rootDestinationFolder = folderCandidates[0]; 207 m_rootDestinationFolder = folderCandidates[0];
205 archive = new TarArchiveReader(m_loadStream); 208 archive = new TarArchiveReader(m_loadStream);
206 byte[] data; 209 byte[] data;
@@ -211,7 +214,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
211 if (filePath == ArchiveConstants.CONTROL_FILE_PATH) 214 if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
212 { 215 {
213 LoadControlFile(filePath, data); 216 LoadControlFile(filePath, data);
214 } 217 }
215 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) 218 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
216 { 219 {
217 LoadAssetFile(filePath, data); 220 LoadAssetFile(filePath, data);
@@ -221,17 +224,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
221 LoadInventoryFile(filePath, entryType, data); 224 LoadInventoryFile(filePath, entryType, data);
222 } 225 }
223 } 226 }
224 227
225 archive.Close(); 228 archive.Close();
229 LoadInventoryLinks();
226 230
227 m_log.DebugFormat( 231 m_log.DebugFormat(
228 "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", 232 "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures",
229 m_successfulAssetRestores, m_failedAssetRestores); 233 m_successfulAssetRestores, m_failedAssetRestores);
230 234
231 //Alicia: When this is called by LibraryModule or Tests, m_module will be null as event is not required 235 //Alicia: When this is called by LibraryModule or Tests, m_module will be null as event is not required
232 if(m_module != null) 236 if(m_module != null)
233 m_module.TriggerInventoryArchiveLoaded(m_id, true, m_userInfo, m_invPath, m_loadStream, reportedException, m_successfulItemRestores); 237 m_module.TriggerInventoryArchiveLoaded(m_id, true, m_userInfo, m_invPath, m_loadStream, reportedException, m_successfulItemRestores);
234 238
235 return m_loadedNodes; 239 return m_loadedNodes;
236 } 240 }
237 catch(Exception Ex) 241 catch(Exception Ex)
@@ -268,36 +272,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
268 /// </param> 272 /// </param>
269 /// <returns>The last user inventory folder created or found for the archive path</returns> 273 /// <returns>The last user inventory folder created or found for the archive path</returns>
270 public InventoryFolderBase ReplicateArchivePathToUserInventory( 274 public InventoryFolderBase ReplicateArchivePathToUserInventory(
271 string iarPath, 275 string iarPath,
272 InventoryFolderBase rootDestFolder, 276 InventoryFolderBase rootDestFolder,
273 Dictionary <string, InventoryFolderBase> resolvedFolders, 277 Dictionary <string, InventoryFolderBase> resolvedFolders,
274 HashSet<InventoryNodeBase> loadedNodes) 278 Dictionary<UUID, InventoryNodeBase> loadedNodes)
275 { 279 {
276 string iarPathExisting = iarPath; 280 string iarPathExisting = iarPath;
277 281
278// m_log.DebugFormat( 282// m_log.DebugFormat(
279// "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID); 283// "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID);
280 284
281 InventoryFolderBase destFolder 285 InventoryFolderBase destFolder
282 = ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, resolvedFolders); 286 = ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, resolvedFolders);
283 287
284// m_log.DebugFormat( 288// m_log.DebugFormat(
285// "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]", 289// "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]",
286// iarPath, iarPathExisting); 290// iarPath, iarPathExisting);
287 291
288 string iarPathToCreate = iarPath.Substring(iarPathExisting.Length); 292 string iarPathToCreate = iarPath.Substring(iarPathExisting.Length);
289 CreateFoldersForPath(destFolder, iarPathExisting, iarPathToCreate, resolvedFolders, loadedNodes); 293 CreateFoldersForPath(destFolder, iarPathExisting, iarPathToCreate, resolvedFolders, loadedNodes);
290 294
291 return destFolder; 295 return destFolder;
292 } 296 }
293 297
294 /// <summary> 298 /// <summary>
295 /// Resolve a destination folder 299 /// Resolve a destination folder
296 /// </summary> 300 /// </summary>
297 /// 301 ///
298 /// We require here a root destination folder (usually the root of the user's inventory) and the archive 302 /// We require here a root destination folder (usually the root of the user's inventory) and the archive
299 /// path. We also pass in a list of previously resolved folders in case we've found this one previously. 303 /// path. We also pass in a list of previously resolved folders in case we've found this one previously.
300 /// 304 ///
301 /// <param name="archivePath"> 305 /// <param name="archivePath">
302 /// The item archive path to resolve. The portion of the path passed back is that 306 /// The item archive path to resolve. The portion of the path passed back is that
303 /// which corresponds to the resolved desintation folder. 307 /// which corresponds to the resolved desintation folder.
@@ -321,7 +325,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
321 while (archivePath.Length > 0) 325 while (archivePath.Length > 0)
322 { 326 {
323// m_log.DebugFormat("[INVENTORY ARCHIVER]: Trying to resolve destination folder {0}", archivePath); 327// m_log.DebugFormat("[INVENTORY ARCHIVER]: Trying to resolve destination folder {0}", archivePath);
324 328
325 if (resolvedFolders.ContainsKey(archivePath)) 329 if (resolvedFolders.ContainsKey(archivePath))
326 { 330 {
327// m_log.DebugFormat( 331// m_log.DebugFormat(
@@ -332,13 +336,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
332 { 336 {
333 if (m_merge) 337 if (m_merge)
334 { 338 {
335 // TODO: Using m_invPath is totally wrong - what we need to do is strip the uuid from the 339 // TODO: Using m_invPath is totally wrong - what we need to do is strip the uuid from the
336 // iar name and try to find that instead. 340 // iar name and try to find that instead.
337 string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath); 341 string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath);
338 List<InventoryFolderBase> folderCandidates 342 List<InventoryFolderBase> folderCandidates
339 = InventoryArchiveUtils.FindFoldersByPath( 343 = InventoryArchiveUtils.FindFoldersByPath(
340 m_InventoryService, m_userInfo.PrincipalID, plainPath); 344 m_InventoryService, m_userInfo.PrincipalID, plainPath);
341 345
342 if (folderCandidates.Count != 0) 346 if (folderCandidates.Count != 0)
343 { 347 {
344 InventoryFolderBase destFolder = folderCandidates[0]; 348 InventoryFolderBase destFolder = folderCandidates[0];
@@ -346,7 +350,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
346 return destFolder; 350 return destFolder;
347 } 351 }
348 } 352 }
349 353
350 // Don't include the last slash so find the penultimate one 354 // Don't include the last slash so find the penultimate one
351 int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2); 355 int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2);
352 356
@@ -365,10 +369,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
365 } 369 }
366 } 370 }
367 } 371 }
368 372
369 return rootDestFolder; 373 return rootDestFolder;
370 } 374 }
371 375
372 /// <summary> 376 /// <summary>
373 /// Create a set of folders for the given path. 377 /// Create a set of folders for the given path.
374 /// </summary> 378 /// </summary>
@@ -388,11 +392,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
388 /// Track the inventory nodes created. 392 /// Track the inventory nodes created.
389 /// </param> 393 /// </param>
390 protected void CreateFoldersForPath( 394 protected void CreateFoldersForPath(
391 InventoryFolderBase destFolder, 395 InventoryFolderBase destFolder,
392 string iarPathExisting, 396 string iarPathExisting,
393 string iarPathToReplicate, 397 string iarPathToReplicate,
394 Dictionary <string, InventoryFolderBase> resolvedFolders, 398 Dictionary <string, InventoryFolderBase> resolvedFolders,
395 HashSet<InventoryNodeBase> loadedNodes) 399 Dictionary<UUID, InventoryNodeBase> loadedNodes)
396 { 400 {
397 string[] rawDirsToCreate = iarPathToReplicate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); 401 string[] rawDirsToCreate = iarPathToReplicate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
398 402
@@ -402,7 +406,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
402 406
403 if (!rawDirsToCreate[i].Contains(ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR)) 407 if (!rawDirsToCreate[i].Contains(ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR))
404 continue; 408 continue;
405 409
406 int identicalNameIdentifierIndex 410 int identicalNameIdentifierIndex
407 = rawDirsToCreate[i].LastIndexOf( 411 = rawDirsToCreate[i].LastIndexOf(
408 ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR); 412 ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR);
@@ -412,7 +416,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
412 newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName); 416 newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName);
413 UUID newFolderId = UUID.Random(); 417 UUID newFolderId = UUID.Random();
414 418
415 destFolder 419 destFolder
416 = new InventoryFolderBase( 420 = new InventoryFolderBase(
417 newFolderId, newFolderName, m_userInfo.PrincipalID, 421 newFolderId, newFolderName, m_userInfo.PrincipalID,
418 (short)FolderType.None, destFolder.ID, 1); 422 (short)FolderType.None, destFolder.ID, 1);
@@ -424,10 +428,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
424 resolvedFolders[iarPathExisting] = destFolder; 428 resolvedFolders[iarPathExisting] = destFolder;
425 429
426 if (0 == i) 430 if (0 == i)
427 loadedNodes.Add(destFolder); 431 loadedNodes[destFolder.ID] = destFolder;
428 } 432 }
429 } 433 }
430 434
431 /// <summary> 435 /// <summary>
432 /// Load an item from the archive 436 /// Load an item from the archive
433 /// </summary> 437 /// </summary>
@@ -438,15 +442,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
438 protected InventoryItemBase LoadItem(byte[] data, InventoryFolderBase loadFolder) 442 protected InventoryItemBase LoadItem(byte[] data, InventoryFolderBase loadFolder)
439 { 443 {
440 InventoryItemBase item = UserInventoryItemSerializer.Deserialize(data); 444 InventoryItemBase item = UserInventoryItemSerializer.Deserialize(data);
441 445
446 UUID oldID = item.ID;
442 // Don't use the item ID that's in the file 447 // Don't use the item ID that's in the file
443 item.ID = UUID.Random(); 448 item.ID = UUID.Random();
449 m_itemIDs[oldID] = item.ID;
444 450
445 UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_UserAccountService); 451 UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_UserAccountService);
446 if (UUID.Zero != ospResolvedId) // The user exists in this grid 452 if (UUID.Zero != ospResolvedId) // The user exists in this grid
447 { 453 {
448// m_log.DebugFormat("[INVENTORY ARCHIVER]: Found creator {0} via OSPA resolution", ospResolvedId); 454// m_log.DebugFormat("[INVENTORY ARCHIVER]: Found creator {0} via OSPA resolution", ospResolvedId);
449 455
450// item.CreatorIdAsUuid = ospResolvedId; 456// item.CreatorIdAsUuid = ospResolvedId;
451 457
452 // Don't preserve the OSPA in the creator id (which actually gets persisted to the 458 // Don't preserve the OSPA in the creator id (which actually gets persisted to the
@@ -457,7 +463,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
457 else if (string.IsNullOrEmpty(item.CreatorData)) 463 else if (string.IsNullOrEmpty(item.CreatorData))
458 { 464 {
459 item.CreatorId = m_userInfo.PrincipalID.ToString(); 465 item.CreatorId = m_userInfo.PrincipalID.ToString();
460// item.CreatorIdAsUuid = new UUID(item.CreatorId);
461 } 466 }
462 467
463 item.Owner = m_userInfo.PrincipalID; 468 item.Owner = m_userInfo.PrincipalID;
@@ -470,11 +475,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
470 // FIXME: This relies on the items coming before the assets in the TAR file. Need to create stronger 475 // FIXME: This relies on the items coming before the assets in the TAR file. Need to create stronger
471 // checks for this, and maybe even an external tool for creating OARs which enforces this, rather than 476 // checks for this, and maybe even an external tool for creating OARs which enforces this, rather than
472 // relying on native tar tools. 477 // relying on native tar tools.
473 m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid; 478 if(item.AssetType == (int)AssetType.Link)
479 {
480 m_invLinks.Add(item);
481 if(!m_loadedNodes.ContainsKey(item.Folder) && !m_invLinksFolders.ContainsKey(item.Folder))
482 m_invLinksFolders[item.Folder] = loadFolder;
483 return null;
484 }
485 else
486 {
487 m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid;
488 if (!m_InventoryService.AddItem(item))
489 m_log.WarnFormat("[INVENTORY ARCHIVER]: Unable to save item {0} in folder {1}", item.Name, item.Folder);
490 }
474 491
475 if (!m_InventoryService.AddItem(item))
476 m_log.WarnFormat("[INVENTORY ARCHIVER]: Unable to save item {0} in folder {1}", item.Name, item.Folder);
477
478 return item; 492 return item;
479 } 493 }
480 494
@@ -504,56 +518,57 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
504 string rawUuid = filename.Remove(filename.Length - extension.Length); 518 string rawUuid = filename.Remove(filename.Length - extension.Length);
505 UUID assetId = new UUID(rawUuid); 519 UUID assetId = new UUID(rawUuid);
506 520
507 if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension)) 521 if (!ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension))
508 { 522 {
509 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension]; 523 m_log.ErrorFormat(
524 "[INVENTORY ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}",
525 assetPath, extension);
526 return false;
527 }
510 528
511 if (assetType == (sbyte)AssetType.Unknown) 529 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
512 { 530 if (assetType == (sbyte)AssetType.Unknown)
513 m_log.WarnFormat("[INVENTORY ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, assetId); 531 {
514 } 532 m_log.WarnFormat("[INVENTORY ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, assetId);
515 else if (assetType == (sbyte)AssetType.Object) 533 return false;
516 { 534 }
517 if (m_creatorIdForAssetId.ContainsKey(assetId)) 535
536 if(assetType == (sbyte)AssetType.Object)
537 {
538 UUID owner = m_userInfo.PrincipalID;
539 bool doCreatorID = m_creatorIdForAssetId.ContainsKey(assetId);
540
541 data = SceneObjectSerializer.ModifySerializedObject(assetId, data,
542 sog =>
518 { 543 {
519 data = SceneObjectSerializer.ModifySerializedObject(assetId, data, 544 foreach(SceneObjectPart sop in sog.Parts)
520 sog => { 545 {
521 bool modified = false; 546 sop.OwnerID = owner;
522 547 if(doCreatorID && string.IsNullOrEmpty(sop.CreatorData))
523 foreach (SceneObjectPart sop in sog.Parts) 548 sop.CreatorID = m_creatorIdForAssetId[assetId];
524 { 549
525 if (string.IsNullOrEmpty(sop.CreatorData)) 550 foreach(TaskInventoryItem it in sop.Inventory.GetInventoryItems())
526 { 551 {
527 sop.CreatorID = m_creatorIdForAssetId[assetId]; 552 it.OwnerID = owner;
528 modified = true; 553 if(string.IsNullOrEmpty(it.CreatorData) && m_creatorIdForAssetId.ContainsKey(it.AssetID))
529 } 554 it.CreatorID = m_creatorIdForAssetId[it.AssetID];
530 } 555 }
531 556 }
532 return modified; 557 return true;
533 }); 558 });
534
535 if (data == null)
536 return false;
537 }
538 }
539 559
540 //m_log.DebugFormat("[INVENTORY ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType); 560 if(data == null)
561 return false;
562 }
541 563
542 AssetBase asset = new AssetBase(assetId, "From IAR", assetType, UUID.Zero.ToString()); 564 //m_log.DebugFormat("[INVENTORY ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType);
543 asset.Data = data;
544 565
545 m_AssetService.Store(asset); 566 AssetBase asset = new AssetBase(assetId, "From IAR", assetType, UUID.Zero.ToString());
567 asset.Data = data;
546 568
547 return true; 569 m_AssetService.Store(asset);
548 }
549 else
550 {
551 m_log.ErrorFormat(
552 "[INVENTORY ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}",
553 assetPath, extension);
554 570
555 return false; 571 return true;
556 }
557 } 572 }
558 573
559 /// <summary> 574 /// <summary>
@@ -568,7 +583,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
568 int majorVersion = int.Parse(archiveElement.Attribute("major_version").Value); 583 int majorVersion = int.Parse(archiveElement.Attribute("major_version").Value);
569 int minorVersion = int.Parse(archiveElement.Attribute("minor_version").Value); 584 int minorVersion = int.Parse(archiveElement.Attribute("minor_version").Value);
570 string version = string.Format("{0}.{1}", majorVersion, minorVersion); 585 string version = string.Format("{0}.{1}", majorVersion, minorVersion);
571 586
572 if (majorVersion > MAX_MAJOR_VERSION) 587 if (majorVersion > MAX_MAJOR_VERSION)
573 { 588 {
574 throw new Exception( 589 throw new Exception(
@@ -576,38 +591,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
576 "The IAR you are trying to load has major version number of {0} but this version of OpenSim can only load IARs with major version number {1} and below", 591 "The IAR you are trying to load has major version number of {0} but this version of OpenSim can only load IARs with major version number {1} and below",
577 majorVersion, MAX_MAJOR_VERSION)); 592 majorVersion, MAX_MAJOR_VERSION));
578 } 593 }
579 594
580 ControlFileLoaded = true; 595 ControlFileLoaded = true;
581 m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version); 596 m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version);
582 } 597 }
583 598
584 /// <summary> 599 /// <summary>
585 /// Load inventory file 600 /// Load inventory file
586 /// </summary> 601 /// </summary>
587 /// <param name="path"></param> 602 /// <param name="path"></param>
588 /// <param name="entryType"></param> 603 /// <param name="entryType"></param>
589 /// <param name="data"></param> 604 /// <param name="data"></param>
590 protected void LoadInventoryFile(string path, TarArchiveReader.TarEntryType entryType, byte[] data) 605 protected void LoadInventoryFile(string path, TarArchiveReader.TarEntryType entryType, byte[] data)
591 { 606 {
592 if (!ControlFileLoaded) 607 if (!ControlFileLoaded)
593 throw new Exception( 608 throw new Exception(
594 string.Format( 609 string.Format(
595 "The IAR you are trying to load does not list {0} before {1}. Aborting load", 610 "The IAR you are trying to load does not list {0} before {1}. Aborting load",
596 ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.INVENTORY_PATH)); 611 ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.INVENTORY_PATH));
597 612
598 if (m_assetsLoaded) 613 if (m_assetsLoaded)
599 throw new Exception( 614 throw new Exception(
600 string.Format( 615 string.Format(
601 "The IAR you are trying to load does not list all {0} before {1}. Aborting load", 616 "The IAR you are trying to load does not list all {0} before {1}. Aborting load",
602 ArchiveConstants.INVENTORY_PATH, ArchiveConstants.ASSETS_PATH)); 617 ArchiveConstants.INVENTORY_PATH, ArchiveConstants.ASSETS_PATH));
603 618
604 path = path.Substring(ArchiveConstants.INVENTORY_PATH.Length); 619 path = path.Substring(ArchiveConstants.INVENTORY_PATH.Length);
605 620
606 // Trim off the file portion if we aren't already dealing with a directory path 621 // Trim off the file portion if we aren't already dealing with a directory path
607 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) 622 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
608 path = path.Remove(path.LastIndexOf("/") + 1); 623 path = path.Remove(path.LastIndexOf("/") + 1);
609 624
610 InventoryFolderBase foundFolder 625 InventoryFolderBase foundFolder
611 = ReplicateArchivePathToUserInventory( 626 = ReplicateArchivePathToUserInventory(
612 path, m_rootDestinationFolder, m_resolvedFolders, m_loadedNodes); 627 path, m_rootDestinationFolder, m_resolvedFolders, m_loadedNodes);
613 628
@@ -618,17 +633,41 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
618 if (item != null) 633 if (item != null)
619 { 634 {
620 m_successfulItemRestores++; 635 m_successfulItemRestores++;
621 636
622 // If we aren't loading the folder containing the item then well need to update the 637 // If we aren't loading the folder containing the item then well need to update the
623 // viewer separately for that item. 638 // viewer separately for that item.
624 if (!m_loadedNodes.Contains(foundFolder)) 639 if (!m_loadedNodes.ContainsKey(foundFolder.ID))
625 m_loadedNodes.Add(item); 640 m_loadedNodes[foundFolder.ID] = item;
641 }
642 }
643
644 m_inventoryNodesLoaded = true;
645 }
646
647 private void LoadInventoryLinks()
648 {
649 foreach(InventoryItemBase it in m_invLinks)
650 {
651 UUID target = it.AssetID;
652 if(m_itemIDs.ContainsKey(target))
653 {
654 it.AssetID = m_itemIDs[target];
655 if(!m_InventoryService.AddItem(it))
656 m_log.WarnFormat("[INVENTORY ARCHIVER]: Unable to save item {0} in folder {1}",it.Name,it.Folder);
657 else
658 {
659 m_successfulItemRestores++;
660 UUID fid = it.Folder;
661 if (!m_loadedNodes.ContainsKey(fid) && m_invLinksFolders.ContainsKey(fid))
662 m_loadedNodes[fid] = m_invLinksFolders[fid];
663 }
626 } 664 }
627 } 665 }
628 666
629 m_inventoryNodesLoaded = true; 667 m_itemIDs.Clear();
668 m_invLinks.Clear();
669 m_invLinksFolders.Clear();
630 } 670 }
631
632 /// <summary> 671 /// <summary>
633 /// Load asset file 672 /// Load asset file
634 /// </summary> 673 /// </summary>
@@ -639,15 +678,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
639 if (!ControlFileLoaded) 678 if (!ControlFileLoaded)
640 throw new Exception( 679 throw new Exception(
641 string.Format( 680 string.Format(
642 "The IAR you are trying to load does not list {0} before {1}. Aborting load", 681 "The IAR you are trying to load does not list {0} before {1}. Aborting load",
643 ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.ASSETS_PATH)); 682 ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.ASSETS_PATH));
644 683
645 if (!m_inventoryNodesLoaded) 684 if (!m_inventoryNodesLoaded)
646 throw new Exception( 685 throw new Exception(
647 string.Format( 686 string.Format(
648 "The IAR you are trying to load does not list all {0} before {1}. Aborting load", 687 "The IAR you are trying to load does not list all {0} before {1}. Aborting load",
649 ArchiveConstants.INVENTORY_PATH, ArchiveConstants.ASSETS_PATH)); 688 ArchiveConstants.INVENTORY_PATH, ArchiveConstants.ASSETS_PATH));
650 689
651 if (LoadAsset(path, data)) 690 if (LoadAsset(path, data))
652 m_successfulAssetRestores++; 691 m_successfulAssetRestores++;
653 else 692 else
@@ -655,10 +694,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
655 694
656 if ((m_successfulAssetRestores) % 50 == 0) 695 if ((m_successfulAssetRestores) % 50 == 0)
657 m_log.DebugFormat( 696 m_log.DebugFormat(
658 "[INVENTORY ARCHIVER]: Loaded {0} assets...", 697 "[INVENTORY ARCHIVER]: Loaded {0} assets...",
659 m_successfulAssetRestores); 698 m_successfulAssetRestores);
660 699
661 m_assetsLoaded = true; 700 m_assetsLoaded = true;
662 } 701 }
663 } 702 }
664} 703}
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
index dbaf2aa..b66aad5 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
@@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
69 /// The path to the required folder. 69 /// The path to the required folder.
70 /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. 70 /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned.
71 /// </param> 71 /// </param>
72 /// <returns>The folder found. Please note that if there are multiple folders with the same name then an 72 /// <returns>The folder found. Please note that if there are multiple folders with the same name then an
73 /// unspecified one will be returned. If no such folder eixsts then null is returned</returns> 73 /// unspecified one will be returned. If no such folder eixsts then null is returned</returns>
74 public static InventoryFolderBase FindFolderByPath( 74 public static InventoryFolderBase FindFolderByPath(
75 IInventoryService inventoryService, UUID userId, string path) 75 IInventoryService inventoryService, UUID userId, string path)
@@ -102,7 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
102 /// The path to the required folder. 102 /// The path to the required folder.
103 /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. 103 /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned.
104 /// </param> 104 /// </param>
105 /// <returns>The folder found. Please note that if there are multiple folders with the same name then an 105 /// <returns>The folder found. Please note that if there are multiple folders with the same name then an
106 /// unspecified one will be returned. If no such folder eixsts then null is returned</returns> 106 /// unspecified one will be returned. If no such folder eixsts then null is returned</returns>
107 public static InventoryFolderBase FindFolderByPath( 107 public static InventoryFolderBase FindFolderByPath(
108 IInventoryService inventoryService, InventoryFolderBase startFolder, string path) 108 IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
@@ -149,7 +149,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
149 149
150 return FindFoldersByPath(inventoryService, rootFolder, path); 150 return FindFoldersByPath(inventoryService, rootFolder, path);
151 } 151 }
152 152
153 /// <summary> 153 /// <summary>
154 /// Find a set of folders given a PATH_DELIMITER delimited path starting from this folder 154 /// Find a set of folders given a PATH_DELIMITER delimited path starting from this folder
155 /// </summary> 155 /// </summary>
@@ -175,7 +175,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
175 IInventoryService inventoryService, InventoryFolderBase startFolder, string path) 175 IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
176 { 176 {
177 List<InventoryFolderBase> foundFolders = new List<InventoryFolderBase>(); 177 List<InventoryFolderBase> foundFolders = new List<InventoryFolderBase>();
178 178
179 if (path == string.Empty) 179 if (path == string.Empty)
180 { 180 {
181 foundFolders.Add(startFolder); 181 foundFolders.Add(startFolder);
@@ -189,17 +189,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
189 foundFolders.Add(startFolder); 189 foundFolders.Add(startFolder);
190 return foundFolders; 190 return foundFolders;
191 } 191 }
192 192
193 // If the path isn't just / then trim any starting extraneous slashes 193 // If the path isn't just / then trim any starting extraneous slashes
194 path = path.TrimStart(new char[] { PATH_DELIMITER }); 194 path = path.TrimStart(new char[] { PATH_DELIMITER });
195 195
196// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Adjusted path in FindFolderByPath() is [{0}]", path); 196// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Adjusted path in FindFolderByPath() is [{0}]", path);
197 197
198 string[] components = SplitEscapedPath(path); 198 string[] components = SplitEscapedPath(path);
199 components[0] = UnescapePath(components[0]); 199 components[0] = UnescapePath(components[0]);
200 200
201 //string[] components = path.Split(new string[] { PATH_DELIMITER.ToString() }, 2, StringSplitOptions.None); 201 //string[] components = path.Split(new string[] { PATH_DELIMITER.ToString() }, 2, StringSplitOptions.None);
202 202
203 InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); 203 InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID);
204 204
205// m_log.DebugFormat( 205// m_log.DebugFormat(
@@ -230,7 +230,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
230 /// 230 ///
231 /// FIXME: Delimitors which occur in names themselves are not currently escapable. 231 /// FIXME: Delimitors which occur in names themselves are not currently escapable.
232 /// </remarks> 232 /// </remarks>
233 /// 233 ///
234 /// <param name="inventoryService"> 234 /// <param name="inventoryService">
235 /// Inventory service to query 235 /// Inventory service to query
236 /// </param> 236 /// </param>
@@ -301,7 +301,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
301 /// 301 ///
302 /// FIXME: Delimitors which occur in names themselves are not currently escapable. 302 /// FIXME: Delimitors which occur in names themselves are not currently escapable.
303 /// </remarks> 303 /// </remarks>
304 /// 304 ///
305 /// <param name="inventoryService">Inventory service to query</param> 305 /// <param name="inventoryService">Inventory service to query</param>
306 /// <param name="startFolder">The folder from which the path starts</param> 306 /// <param name="startFolder">The folder from which the path starts</param>
307 /// <param name="path">The path to the required item.</param> 307 /// <param name="path">The path to the required item.</param>
@@ -313,10 +313,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
313 313
314 // If the path isn't just / then trim any starting extraneous slashes 314 // If the path isn't just / then trim any starting extraneous slashes
315 path = path.TrimStart(new char[] { PATH_DELIMITER }); 315 path = path.TrimStart(new char[] { PATH_DELIMITER });
316 316
317 string[] components = SplitEscapedPath(path); 317 string[] components = SplitEscapedPath(path);
318 components[0] = UnescapePath(components[0]); 318 components[0] = UnescapePath(components[0]);
319 319
320 //string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); 320 //string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None);
321 321
322 if (components.Length == 1) 322 if (components.Length == 1)
@@ -324,15 +324,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
324// m_log.DebugFormat( 324// m_log.DebugFormat(
325// "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}", 325// "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}",
326// components[0], startFolder.Name, startFolder.ID); 326// components[0], startFolder.Name, startFolder.ID);
327 327
328 List<InventoryItemBase> items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID); 328 List<InventoryItemBase> items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID);
329 329
330// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Found {0} items in FindItemByPath()", items.Count); 330// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Found {0} items in FindItemByPath()", items.Count);
331 331
332 foreach (InventoryItemBase item in items) 332 foreach (InventoryItemBase item in items)
333 { 333 {
334// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Inspecting item {0} {1}", item.Name, item.ID); 334// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Inspecting item {0} {1}", item.Name, item.ID);
335 335
336 if (item.Name == components[0]) 336 if (item.Name == components[0])
337 foundItems.Add(item); 337 foundItems.Add(item);
338 } 338 }
@@ -342,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
342// m_log.DebugFormat("FOUND COMPONENTS [{0}] and [{1}]", components[0], components[1]); 342// m_log.DebugFormat("FOUND COMPONENTS [{0}] and [{1}]", components[0], components[1]);
343 343
344 InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); 344 InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID);
345 345
346 foreach (InventoryFolderBase folder in contents.Folders) 346 foreach (InventoryFolderBase folder in contents.Folders)
347 { 347 {
348 if (folder.Name == components[0]) 348 if (folder.Name == components[0])
@@ -365,9 +365,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
365 public static string[] SplitEscapedPath(string path) 365 public static string[] SplitEscapedPath(string path)
366 { 366 {
367// m_log.DebugFormat("SPLITTING PATH {0}", path); 367// m_log.DebugFormat("SPLITTING PATH {0}", path);
368 368
369 bool singleEscapeChar = false; 369 bool singleEscapeChar = false;
370 370
371 for (int i = 0; i < path.Length; i++) 371 for (int i = 0; i < path.Length; i++)
372 { 372 {
373 if (path[i] == ESCAPE_CHARACTER && !singleEscapeChar) 373 if (path[i] == ESCAPE_CHARACTER && !singleEscapeChar)
@@ -395,7 +395,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
395 public static string UnescapePath(string path) 395 public static string UnescapePath(string path)
396 { 396 {
397// m_log.DebugFormat("ESCAPING PATH {0}", path); 397// m_log.DebugFormat("ESCAPING PATH {0}", path);
398 398
399 StringBuilder sb = new StringBuilder(); 399 StringBuilder sb = new StringBuilder();
400 400
401 bool singleEscapeChar = false; 401 bool singleEscapeChar = false;
@@ -418,7 +418,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
418 } 418 }
419 419
420// m_log.DebugFormat("ESCAPED PATH TO {0}", sb); 420// m_log.DebugFormat("ESCAPED PATH TO {0}", sb);
421 421
422 return sb.ToString(); 422 return sb.ToString();
423 } 423 }
424 424
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index f002ad7..ad46107 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -218,10 +218,39 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
218 218
219 // Count inventory items (different to asset count) 219 // Count inventory items (different to asset count)
220 CountItems++; 220 CountItems++;
221 221
222 // Don't chase down link asset items as they actually point to their target item IDs rather than an asset 222 // Don't chase down link asset items as they actually point to their target item IDs rather than an asset
223 if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) 223 if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder)
224 {
225 int curErrorCntr = m_assetGatherer.ErrorCount;
226 int possible = m_assetGatherer.possibleNotAssetCount;
224 m_assetGatherer.AddForInspection(inventoryItem.AssetID); 227 m_assetGatherer.AddForInspection(inventoryItem.AssetID);
228 m_assetGatherer.GatherAll();
229 curErrorCntr = m_assetGatherer.ErrorCount - curErrorCntr;
230 possible = m_assetGatherer.possibleNotAssetCount - possible;
231
232 if(curErrorCntr > 0 || possible > 0)
233 {
234 string spath;
235 int indx = path.IndexOf("__");
236 if(indx > 0)
237 spath = path.Substring(0,indx);
238 else
239 spath = path;
240
241 if(curErrorCntr > 0)
242 {
243 m_log.ErrorFormat("[INVENTORY ARCHIVER Warning]: item {0} '{1}', type {2}, in '{3}', contains {4} references to missing or damaged assets",
244 inventoryItem.ID, inventoryItem.Name, itemAssetType.ToString(), spath, curErrorCntr);
245 if(possible > 0)
246 m_log.WarnFormat("[INVENTORY ARCHIVER Warning]: item also contains {0} references that may be to missing or damaged assets or not a problem", possible);
247 }
248 else if(possible > 0)
249 {
250 m_log.WarnFormat("[INVENTORY ARCHIVER Warning]: item {0} '{1}', type {2}, in '{3}', contains {4} references that may be to missing or damaged assets or not a problem", inventoryItem.ID, inventoryItem.Name, itemAssetType.ToString(), spath, possible);
251 }
252 }
253 }
225 } 254 }
226 255
227 /// <summary> 256 /// <summary>
@@ -381,6 +410,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
381 string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); 410 string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath);
382 Exception e = new InventoryArchiverException(errorMessage); 411 Exception e = new InventoryArchiverException(errorMessage);
383 m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e, 0, 0); 412 m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e, 0, 0);
413 if(m_saveStream != null && m_saveStream.CanWrite)
414 m_saveStream.Close();
384 throw e; 415 throw e;
385 } 416 }
386 417
@@ -420,17 +451,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
420 { 451 {
421 m_assetGatherer.GatherAll(); 452 m_assetGatherer.GatherAll();
422 453
454 int errors = m_assetGatherer.FailedUUIDs.Count;
455
423 m_log.DebugFormat( 456 m_log.DebugFormat(
424 "[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetGatherer.GatheredUuids.Count); 457 "[INVENTORY ARCHIVER]: The items to save reference {0} possible assets", m_assetGatherer.GatheredUuids.Count + errors);
458 if(errors > 0)
459 m_log.DebugFormat("[INVENTORY ARCHIVER]: {0} of these have problems or are not assets and will be ignored", errors);
425 460
426 AssetsRequest ar 461 AssetsRequest ar = new AssetsRequest(
427 = new AssetsRequest(
428 new AssetsArchiver(m_archiveWriter), 462 new AssetsArchiver(m_archiveWriter),
429 m_assetGatherer.GatheredUuids, m_scene.AssetService, 463 m_assetGatherer.GatheredUuids, m_assetGatherer.FailedUUIDs.Count,
464 m_scene.AssetService,
430 m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, 465 m_scene.UserAccountService, m_scene.RegionInfo.ScopeID,
431 options, ReceivedAllAssets); 466 options, ReceivedAllAssets);
432 467 ar.Execute();
433 WorkManager.RunInThread(o => ar.Execute(), null, string.Format("AssetsRequest ({0})", m_scene.Name));
434 } 468 }
435 else 469 else
436 { 470 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index 9c005e4..d50ebf5 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -50,6 +50,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
50 { 50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 52
53 /// <value>
54 /// Enable or disable checking whether the iar user is actually logged in
55 /// </value>
56// public bool DisablePresenceChecks { get; set; }
57
53 public event InventoryArchiveSaved OnInventoryArchiveSaved; 58 public event InventoryArchiveSaved OnInventoryArchiveSaved;
54 public event InventoryArchiveLoaded OnInventoryArchiveLoaded; 59 public event InventoryArchiveLoaded OnInventoryArchiveLoaded;
55 60
@@ -89,6 +94,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
89 94
90 public InventoryArchiverModule() {} 95 public InventoryArchiverModule() {}
91 96
97// public InventoryArchiverModule(bool disablePresenceChecks)
98// {
99// DisablePresenceChecks = disablePresenceChecks;
100 // }
101
92 #region ISharedRegionModule 102 #region ISharedRegionModule
93 103
94 public void Initialise(IConfigSource source) 104 public void Initialise(IConfigSource source)
@@ -162,7 +172,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
162 172
163 public string Name { get { return "Inventory Archiver Module"; } } 173 public string Name { get { return "Inventory Archiver Module"; } }
164 174
165 #endregion 175 #endregion
166 176
167 /// <summary> 177 /// <summary>
168 /// Trigger the inventory archive saved event. 178 /// Trigger the inventory archive saved event.
@@ -204,21 +214,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
204 214
205 if (userInfo != null) 215 if (userInfo != null)
206 { 216 {
207 try 217// if (CheckPresence(userInfo.PrincipalID))
208 { 218// {
209 new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, saveStream).Execute(options, UserAccountService); 219 try
210 } 220 {
211 catch (EntryPointNotFoundException e) 221 InventoryArchiveWriteRequest iarReq = new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, saveStream);
212 { 222 iarReq.Execute(options, UserAccountService);
213 m_log.ErrorFormat( 223 }
214 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." 224 catch (EntryPointNotFoundException e)
215 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); 225 {
216 m_log.Error(e); 226 m_log.ErrorFormat(
217 227 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
218 return false; 228 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
219 } 229 m_log.Error(e);
220 230
221 return true; 231 return false;
232 }
233
234 return true;
235// }
236// else
237// {
238// m_log.ErrorFormat(
239// "[INVENTORY ARCHIVER]: User {0} {1} {2} not logged in to this region simulator",
240// userInfo.FirstName, userInfo.LastName, userInfo.PrincipalID);
241// }
222 } 242 }
223 } 243 }
224 244
@@ -238,21 +258,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
238 258
239 if (userInfo != null) 259 if (userInfo != null)
240 { 260 {
241 try 261// if (CheckPresence(userInfo.PrincipalID))
242 { 262// {
243 new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, savePath).Execute(options, UserAccountService); 263 try
244 } 264 {
245 catch (EntryPointNotFoundException e) 265 InventoryArchiveWriteRequest iarReq = new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, savePath);
246 { 266 iarReq.Execute(options, UserAccountService);
247 m_log.ErrorFormat( 267 }
248 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." 268 catch (EntryPointNotFoundException e)
249 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); 269 {
250 m_log.Error(e); 270 m_log.ErrorFormat(
251 271 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
252 return false; 272 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
253 } 273 m_log.Error(e);
254 274
255 return true; 275 return false;
276 }
277
278 return true;
279// }
280// else
281// {
282// m_log.ErrorFormat(
283// "[INVENTORY ARCHIVER]: User {0} {1} {2} not logged in to this region simulator",
284// userInfo.FirstName, userInfo.LastName, userInfo.PrincipalID);
285// }
256 } 286 }
257 } 287 }
258 288
@@ -274,26 +304,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
274 304
275 if (userInfo != null) 305 if (userInfo != null)
276 { 306 {
277 InventoryArchiveReadRequest request; 307// if (CheckPresence(userInfo.PrincipalID))
278 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false); 308// {
279 309 InventoryArchiveReadRequest request;
280 try 310 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false);
281 { 311
282 request = new InventoryArchiveReadRequest(id, this, m_aScene.InventoryService, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadStream, merge); 312 try
283 } 313 {
284 catch (EntryPointNotFoundException e) 314 request = new InventoryArchiveReadRequest(id, this, m_aScene.InventoryService, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadStream, merge);
285 { 315 }
286 m_log.ErrorFormat( 316 catch (EntryPointNotFoundException e)
287 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." 317 {
288 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); 318 m_log.ErrorFormat(
289 m_log.Error(e); 319 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
290 320 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
291 return false; 321 m_log.Error(e);
292 } 322
293 323 return false;
294 UpdateClientWithLoadedNodes(userInfo, request.Execute()); 324 }
295 325
296 return true; 326 UpdateClientWithLoadedNodes(userInfo, request.Execute());
327
328 return true;
329// }
330// else
331// {
332// m_log.ErrorFormat(
333// "[INVENTORY ARCHIVER]: User {0} {1} {2} not logged in to this region simulator",
334// userInfo.FirstName, userInfo.LastName, userInfo.PrincipalID);
335// }
297 } 336 }
298 else 337 else
299 m_log.ErrorFormat("[INVENTORY ARCHIVER]: User {0} {1} not found", 338 m_log.ErrorFormat("[INVENTORY ARCHIVER]: User {0} {1} not found",
@@ -313,26 +352,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
313 352
314 if (userInfo != null) 353 if (userInfo != null)
315 { 354 {
316 InventoryArchiveReadRequest request; 355// if (CheckPresence(userInfo.PrincipalID))
317 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false); 356// {
318 357 InventoryArchiveReadRequest request;
319 try 358 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false);
320 { 359
321 request = new InventoryArchiveReadRequest(id, this, m_aScene.InventoryService, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadPath, merge); 360 try
322 } 361 {
323 catch (EntryPointNotFoundException e) 362 request = new InventoryArchiveReadRequest(id, this, m_aScene.InventoryService, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadPath, merge);
324 { 363 }
325 m_log.ErrorFormat( 364 catch (EntryPointNotFoundException e)
326 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." 365 {
327 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); 366 m_log.ErrorFormat(
328 m_log.Error(e); 367 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
329 368 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
330 return false; 369 m_log.Error(e);
331 } 370
332 371 return false;
333 UpdateClientWithLoadedNodes(userInfo, request.Execute()); 372 }
334 373
335 return true; 374 UpdateClientWithLoadedNodes(userInfo, request.Execute());
375
376 return true;
377// }
378// else
379// {
380// m_log.ErrorFormat(
381// "[INVENTORY ARCHIVER]: User {0} {1} {2} not logged in to this region simulator",
382// userInfo.FirstName, userInfo.LastName, userInfo.PrincipalID);
383// }
336 } 384 }
337 } 385 }
338 386
@@ -545,7 +593,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
545 /// Notify the client of loaded nodes if they are logged in 593 /// Notify the client of loaded nodes if they are logged in
546 /// </summary> 594 /// </summary>
547 /// <param name="loadedNodes">Can be empty. In which case, nothing happens</param> 595 /// <param name="loadedNodes">Can be empty. In which case, nothing happens</param>
548 private void UpdateClientWithLoadedNodes(UserAccount userInfo, HashSet<InventoryNodeBase> loadedNodes) 596 private void UpdateClientWithLoadedNodes(UserAccount userInfo, Dictionary<UUID, InventoryNodeBase> loadedNodes)
549 { 597 {
550 if (loadedNodes.Count == 0) 598 if (loadedNodes.Count == 0)
551 return; 599 return;
@@ -556,7 +604,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
556 604
557 if (user != null && !user.IsChildAgent) 605 if (user != null && !user.IsChildAgent)
558 { 606 {
559 foreach (InventoryNodeBase node in loadedNodes) 607 foreach (InventoryNodeBase node in loadedNodes.Values)
560 { 608 {
561// m_log.DebugFormat( 609// m_log.DebugFormat(
562// "[INVENTORY ARCHIVER]: Notifying {0} of loaded inventory node {1}", 610// "[INVENTORY ARCHIVER]: Notifying {0} of loaded inventory node {1}",
@@ -569,5 +617,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
569 } 617 }
570 } 618 }
571 } 619 }
620
621// /// <summary>
622// /// Check if the given user is present in any of the scenes.
623// /// </summary>
624// /// <param name="userId">The user to check</param>
625// /// <returns>true if the user is in any of the scenes, false otherwise</returns>
626// protected bool CheckPresence(UUID userId)
627// {
628// if (DisablePresenceChecks)
629// return true;
630//
631// foreach (Scene scene in m_scenes.Values)
632// {
633// ScenePresence p;
634// if ((p = scene.GetScenePresence(userId)) != null)
635// {
636// p.ControllingClient.SendAgentAlertMessage("Inventory operation has been started", false);
637// return true;
638// }
639// }
640//
641// return false;
642// }
572 } 643 }
573} 644}
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
index c2e645f..86eca17 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
@@ -56,23 +56,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
56 { 56 {
57 TestHelpers.InMethod(); 57 TestHelpers.InMethod();
58// log4net.Config.XmlConfigurator.Configure(); 58// log4net.Config.XmlConfigurator.Configure();
59 59
60 SerialiserModule serialiserModule = new SerialiserModule(); 60 SerialiserModule serialiserModule = new SerialiserModule();
61 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 61 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
62 62
63 // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene 63 // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene
64 Scene scene = new SceneHelpers().SetupScene(); 64 Scene scene = new SceneHelpers().SetupScene();
65 65
66 SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); 66 SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule);
67 67
68 UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "meowfood"); 68 UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "meowfood");
69 UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); 69 UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire");
70 70
71 archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); 71 archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream);
72 InventoryItemBase foundItem1 72 InventoryItemBase foundItem1
73 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); 73 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
74 74
75 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); 75 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1");
76 76
77 // Now try loading to a root child folder 77 // Now try loading to a root child folder
78 UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xA", false); 78 UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xA", false);
@@ -90,9 +90,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
90 90
91 InventoryItemBase foundItem3 91 InventoryItemBase foundItem3
92 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC/" + m_item1Name); 92 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC/" + m_item1Name);
93 Assert.That(foundItem3, Is.Not.Null, "Didn't find loaded item 3"); 93 Assert.That(foundItem3, Is.Not.Null, "Didn't find loaded item 3");
94 } 94 }
95 95
96 /// <summary> 96 /// <summary>
97 /// Test that things work when the load path specified starts with a slash 97 /// Test that things work when the load path specified starts with a slash
98 /// </summary> 98 /// </summary>
@@ -101,22 +101,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
101 { 101 {
102 TestHelpers.InMethod(); 102 TestHelpers.InMethod();
103// log4net.Config.XmlConfigurator.Configure(); 103// log4net.Config.XmlConfigurator.Configure();
104 104
105 SerialiserModule serialiserModule = new SerialiserModule(); 105 SerialiserModule serialiserModule = new SerialiserModule();
106 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 106 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
107 Scene scene = new SceneHelpers().SetupScene(); 107 Scene scene = new SceneHelpers().SetupScene();
108 SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); 108 SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule);
109 109
110 UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "password"); 110 UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "password");
111 archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/Objects", "password", m_iarStream); 111 archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/Objects", "password", m_iarStream);
112 112
113 InventoryItemBase foundItem1 113 InventoryItemBase foundItem1
114 = InventoryArchiveUtils.FindItemByPath( 114 = InventoryArchiveUtils.FindItemByPath(
115 scene.InventoryService, m_uaMT.PrincipalID, "/Objects/" + m_item1Name); 115 scene.InventoryService, m_uaMT.PrincipalID, "/Objects/" + m_item1Name);
116 116
117 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1 in TestLoadIarFolderStartsWithSlash()"); 117 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1 in TestLoadIarFolderStartsWithSlash()");
118 } 118 }
119 119
120 [Test] 120 [Test]
121 public void TestLoadIarPathWithEscapedChars() 121 public void TestLoadIarPathWithEscapedChars()
122 { 122 {
@@ -137,7 +137,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
137 string userLastName = "Stirrup"; 137 string userLastName = "Stirrup";
138 UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); 138 UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020");
139 UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, "meowfood"); 139 UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, "meowfood");
140 140
141 // Create asset 141 // Create asset
142 SceneObjectGroup object1; 142 SceneObjectGroup object1;
143 SceneObjectPart part1; 143 SceneObjectPart part1;
@@ -168,7 +168,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
168 item1.Name = itemName; 168 item1.Name = itemName;
169 item1.AssetID = asset1.FullID; 169 item1.AssetID = asset1.FullID;
170 item1.ID = item1Id; 170 item1.ID = item1Id;
171 InventoryFolderBase objsFolder 171 InventoryFolderBase objsFolder
172 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, userId, "Objects")[0]; 172 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, userId, "Objects")[0];
173 item1.Folder = objsFolder.ID; 173 item1.Folder = objsFolder.ID;
174 scene.AddInventoryItem(item1); 174 scene.AddInventoryItem(item1);
@@ -189,16 +189,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
189 InventoryItemBase foundItem1 189 InventoryItemBase foundItem1
190 = InventoryArchiveUtils.FindItemByPath( 190 = InventoryArchiveUtils.FindItemByPath(
191 scene.InventoryService, userId, "Scripts/Objects/" + humanEscapedItemName); 191 scene.InventoryService, userId, "Scripts/Objects/" + humanEscapedItemName);
192 192
193 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); 193 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1");
194// Assert.That( 194// Assert.That(
195// foundItem1.CreatorId, Is.EqualTo(userUuid), 195// foundItem1.CreatorId, Is.EqualTo(userUuid),
196// "Loaded item non-uuid creator doesn't match that of the loading user"); 196// "Loaded item non-uuid creator doesn't match that of the loading user");
197 Assert.That( 197 Assert.That(
198 foundItem1.Name, Is.EqualTo(itemName), 198 foundItem1.Name, Is.EqualTo(itemName),
199 "Loaded item name doesn't match saved name"); 199 "Loaded item name doesn't match saved name");
200 } 200 }
201 201
202 /// <summary> 202 /// <summary>
203 /// Test replication of an archive path to the user's inventory. 203 /// Test replication of an archive path to the user's inventory.
204 /// </summary> 204 /// </summary>
@@ -207,21 +207,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
207 { 207 {
208 TestHelpers.InMethod(); 208 TestHelpers.InMethod();
209// log4net.Config.XmlConfigurator.Configure(); 209// log4net.Config.XmlConfigurator.Configure();
210 210
211 Scene scene = new SceneHelpers().SetupScene(); 211 Scene scene = new SceneHelpers().SetupScene();
212 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); 212 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene);
213 213
214 Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>(); 214 Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>();
215 HashSet<InventoryNodeBase> nodesLoaded = new HashSet<InventoryNodeBase>(); 215 Dictionary<UUID, InventoryNodeBase> nodesLoaded = new Dictionary<UUID, InventoryNodeBase>();
216 216
217 string folder1Name = "1"; 217 string folder1Name = "1";
218 string folder2aName = "2a"; 218 string folder2aName = "2a";
219 string folder2bName = "2b"; 219 string folder2bName = "2b";
220 220
221 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1Name, UUID.Random()); 221 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1Name, UUID.Random());
222 string folder2aArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2aName, UUID.Random()); 222 string folder2aArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2aName, UUID.Random());
223 string folder2bArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2bName, UUID.Random()); 223 string folder2bArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2bName, UUID.Random());
224 224
225 string iarPath1 = string.Join("", new string[] { folder1ArchiveName, folder2aArchiveName }); 225 string iarPath1 = string.Join("", new string[] { folder1ArchiveName, folder2aArchiveName });
226 string iarPath2 = string.Join("", new string[] { folder1ArchiveName, folder2bArchiveName }); 226 string iarPath2 = string.Join("", new string[] { folder1ArchiveName, folder2bArchiveName });
227 227
@@ -229,42 +229,42 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
229 // Test replication of path1 229 // Test replication of path1
230 new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false) 230 new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false)
231 .ReplicateArchivePathToUserInventory( 231 .ReplicateArchivePathToUserInventory(
232 iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 232 iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
233 foldersCreated, nodesLoaded); 233 foldersCreated, nodesLoaded);
234 234
235 List<InventoryFolderBase> folder1Candidates 235 List<InventoryFolderBase> folder1Candidates
236 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); 236 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1Name);
237 Assert.That(folder1Candidates.Count, Is.EqualTo(1)); 237 Assert.That(folder1Candidates.Count, Is.EqualTo(1));
238 238
239 InventoryFolderBase folder1 = folder1Candidates[0]; 239 InventoryFolderBase folder1 = folder1Candidates[0];
240 List<InventoryFolderBase> folder2aCandidates 240 List<InventoryFolderBase> folder2aCandidates
241 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2aName); 241 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2aName);
242 Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); 242 Assert.That(folder2aCandidates.Count, Is.EqualTo(1));
243 } 243 }
244 244
245 { 245 {
246 // Test replication of path2 246 // Test replication of path2
247 new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false) 247 new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false)
248 .ReplicateArchivePathToUserInventory( 248 .ReplicateArchivePathToUserInventory(
249 iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 249 iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
250 foldersCreated, nodesLoaded); 250 foldersCreated, nodesLoaded);
251 251
252 List<InventoryFolderBase> folder1Candidates 252 List<InventoryFolderBase> folder1Candidates
253 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); 253 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1Name);
254 Assert.That(folder1Candidates.Count, Is.EqualTo(1)); 254 Assert.That(folder1Candidates.Count, Is.EqualTo(1));
255 255
256 InventoryFolderBase folder1 = folder1Candidates[0]; 256 InventoryFolderBase folder1 = folder1Candidates[0];
257 257
258 List<InventoryFolderBase> folder2aCandidates 258 List<InventoryFolderBase> folder2aCandidates
259 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2aName); 259 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2aName);
260 Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); 260 Assert.That(folder2aCandidates.Count, Is.EqualTo(1));
261 261
262 List<InventoryFolderBase> folder2bCandidates 262 List<InventoryFolderBase> folder2bCandidates
263 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2bName); 263 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2bName);
264 Assert.That(folder2bCandidates.Count, Is.EqualTo(1)); 264 Assert.That(folder2bCandidates.Count, Is.EqualTo(1));
265 } 265 }
266 } 266 }
267 267
268 /// <summary> 268 /// <summary>
269 /// Test replication of a partly existing archive path to the user's inventory. This should create 269 /// Test replication of a partly existing archive path to the user's inventory. This should create
270 /// a duplicate path without the merge option. 270 /// a duplicate path without the merge option.
@@ -274,31 +274,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
274 { 274 {
275 TestHelpers.InMethod(); 275 TestHelpers.InMethod();
276 //log4net.Config.XmlConfigurator.Configure(); 276 //log4net.Config.XmlConfigurator.Configure();
277 277
278 Scene scene = new SceneHelpers().SetupScene(); 278 Scene scene = new SceneHelpers().SetupScene();
279 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); 279 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene);
280 280
281 string folder1ExistingName = "a"; 281 string folder1ExistingName = "a";
282 string folder2Name = "b"; 282 string folder2Name = "b";
283 283
284 InventoryFolderBase folder1 284 InventoryFolderBase folder1
285 = UserInventoryHelpers.CreateInventoryFolder( 285 = UserInventoryHelpers.CreateInventoryFolder(
286 scene.InventoryService, ua1.PrincipalID, folder1ExistingName, false); 286 scene.InventoryService, ua1.PrincipalID, folder1ExistingName, false);
287 287
288 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); 288 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random());
289 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); 289 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random());
290 290
291 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); 291 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName });
292 292
293 new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false) 293 new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false)
294 .ReplicateArchivePathToUserInventory( 294 .ReplicateArchivePathToUserInventory(
295 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 295 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
296 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>()); 296 new Dictionary<string, InventoryFolderBase>(), new Dictionary<UUID, InventoryNodeBase>());
297 297
298 List<InventoryFolderBase> folder1PostCandidates 298 List<InventoryFolderBase> folder1PostCandidates
299 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); 299 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName);
300 Assert.That(folder1PostCandidates.Count, Is.EqualTo(2)); 300 Assert.That(folder1PostCandidates.Count, Is.EqualTo(2));
301 301
302 // FIXME: Temporarily, we're going to do something messy to make sure we pick up the created folder. 302 // FIXME: Temporarily, we're going to do something messy to make sure we pick up the created folder.
303 InventoryFolderBase folder1Post = null; 303 InventoryFolderBase folder1Post = null;
304 foreach (InventoryFolderBase folder in folder1PostCandidates) 304 foreach (InventoryFolderBase folder in folder1PostCandidates)
@@ -311,11 +311,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
311 } 311 }
312// Assert.That(folder1Post.ID, Is.EqualTo(folder1.ID)); 312// Assert.That(folder1Post.ID, Is.EqualTo(folder1.ID));
313 313
314 List<InventoryFolderBase> folder2PostCandidates 314 List<InventoryFolderBase> folder2PostCandidates
315 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1Post, "b"); 315 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1Post, "b");
316 Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); 316 Assert.That(folder2PostCandidates.Count, Is.EqualTo(1));
317 } 317 }
318 318
319 /// <summary> 319 /// <summary>
320 /// Test replication of a partly existing archive path to the user's inventory. This should create 320 /// Test replication of a partly existing archive path to the user's inventory. This should create
321 /// a merged path. 321 /// a merged path.
@@ -325,33 +325,33 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
325 { 325 {
326 TestHelpers.InMethod(); 326 TestHelpers.InMethod();
327// log4net.Config.XmlConfigurator.Configure(); 327// log4net.Config.XmlConfigurator.Configure();
328 328
329 Scene scene = new SceneHelpers().SetupScene(); 329 Scene scene = new SceneHelpers().SetupScene();
330 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); 330 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene);
331 331
332 string folder1ExistingName = "a"; 332 string folder1ExistingName = "a";
333 string folder2Name = "b"; 333 string folder2Name = "b";
334 334
335 InventoryFolderBase folder1 335 InventoryFolderBase folder1
336 = UserInventoryHelpers.CreateInventoryFolder( 336 = UserInventoryHelpers.CreateInventoryFolder(
337 scene.InventoryService, ua1.PrincipalID, folder1ExistingName, false); 337 scene.InventoryService, ua1.PrincipalID, folder1ExistingName, false);
338 338
339 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); 339 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random());
340 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); 340 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random());
341 341
342 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); 342 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName });
343 343
344 new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, folder1ExistingName, (Stream)null, true) 344 new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, folder1ExistingName, (Stream)null, true)
345 .ReplicateArchivePathToUserInventory( 345 .ReplicateArchivePathToUserInventory(
346 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 346 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
347 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>()); 347 new Dictionary<string, InventoryFolderBase>(), new Dictionary<UUID, InventoryNodeBase>());
348 348
349 List<InventoryFolderBase> folder1PostCandidates 349 List<InventoryFolderBase> folder1PostCandidates
350 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); 350 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName);
351 Assert.That(folder1PostCandidates.Count, Is.EqualTo(1)); 351 Assert.That(folder1PostCandidates.Count, Is.EqualTo(1));
352 Assert.That(folder1PostCandidates[0].ID, Is.EqualTo(folder1.ID)); 352 Assert.That(folder1PostCandidates[0].ID, Is.EqualTo(folder1.ID));
353 353
354 List<InventoryFolderBase> folder2PostCandidates 354 List<InventoryFolderBase> folder2PostCandidates
355 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1PostCandidates[0], "b"); 355 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1PostCandidates[0], "b");
356 Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); 356 Assert.That(folder2PostCandidates.Count, Is.EqualTo(1));
357 } 357 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs
index 57b4f80..d0bdc91 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
47{ 47{
48 [TestFixture] 48 [TestFixture]
49 public class InventoryArchiveLoadTests : InventoryArchiveTestCase 49 public class InventoryArchiveLoadTests : InventoryArchiveTestCase
50 { 50 {
51 protected TestScene m_scene; 51 protected TestScene m_scene;
52 protected InventoryArchiverModule m_archiverModule; 52 protected InventoryArchiverModule m_archiverModule;
53 53
@@ -55,12 +55,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
55 public override void SetUp() 55 public override void SetUp()
56 { 56 {
57 base.SetUp(); 57 base.SetUp();
58 58
59 SerialiserModule serialiserModule = new SerialiserModule(); 59 SerialiserModule serialiserModule = new SerialiserModule();
60 m_archiverModule = new InventoryArchiverModule(); 60 m_archiverModule = new InventoryArchiverModule();
61 61
62 m_scene = new SceneHelpers().SetupScene(); 62 m_scene = new SceneHelpers().SetupScene();
63 SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); 63 SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule);
64 } 64 }
65 65
66 [Test] 66 [Test]
@@ -68,35 +68,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
68 { 68 {
69 TestHelpers.InMethod(); 69 TestHelpers.InMethod();
70// TestHelpers.EnableLogging(); 70// TestHelpers.EnableLogging();
71 71
72 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); 72 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password");
73 m_archiverModule.DearchiveInventory(UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); 73 m_archiverModule.DearchiveInventory(UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream);
74 74
75 InventoryItemBase coaItem 75 InventoryItemBase coaItem
76 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName); 76 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName);
77 77
78 Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1"); 78 Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1");
79 79
80 string assetXml = AssetHelpers.ReadAssetAsString(m_scene.AssetService, coaItem.AssetID); 80 string assetXml = AssetHelpers.ReadAssetAsString(m_scene.AssetService, coaItem.AssetID);
81 81
82 CoalescedSceneObjects coa; 82 CoalescedSceneObjects coa;
83 bool readResult = CoalescedSceneObjectsSerializer.TryFromXml(assetXml, out coa); 83 bool readResult = CoalescedSceneObjectsSerializer.TryFromXml(assetXml, out coa);
84 84
85 Assert.That(readResult, Is.True); 85 Assert.That(readResult, Is.True);
86 Assert.That(coa.Count, Is.EqualTo(2)); 86 Assert.That(coa.Count, Is.EqualTo(2));
87 87
88 List<SceneObjectGroup> coaObjects = coa.Objects; 88 List<SceneObjectGroup> coaObjects = coa.Objects;
89 Assert.That(coaObjects[0].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000120"))); 89 Assert.That(coaObjects[0].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000120")));
90 Assert.That(coaObjects[0].AbsolutePosition, Is.EqualTo(new Vector3(15, 30, 45))); 90 Assert.That(coaObjects[0].AbsolutePosition, Is.EqualTo(new Vector3(15, 30, 45)));
91 91
92 Assert.That(coaObjects[1].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000140"))); 92 Assert.That(coaObjects[1].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000140")));
93 Assert.That(coaObjects[1].AbsolutePosition, Is.EqualTo(new Vector3(25, 50, 75))); 93 Assert.That(coaObjects[1].AbsolutePosition, Is.EqualTo(new Vector3(25, 50, 75)));
94 } 94 }
95 95
96 /// <summary> 96 /// <summary>
97 /// Test case where a creator account exists for the creator UUID embedded in item metadata and serialized 97 /// Test case where a creator account exists for the creator UUID embedded in item metadata and serialized
98 /// objects. 98 /// objects.
99 /// </summary> 99 /// </summary>
100 [Test] 100 [Test]
101 public void TestLoadIarCreatorAccountPresent() 101 public void TestLoadIarCreatorAccountPresent()
102 { 102 {
@@ -105,26 +105,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
105 105
106 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "meowfood"); 106 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "meowfood");
107 107
108 m_archiverModule.DearchiveInventory(UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/", "meowfood", m_iarStream); 108 m_archiverModule.DearchiveInventory(UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/", "meowfood", m_iarStream);
109 InventoryItemBase foundItem1 109 InventoryItemBase foundItem1
110 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_item1Name); 110 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_item1Name);
111 111
112 Assert.That( 112 Assert.That(
113 foundItem1.CreatorId, Is.EqualTo(m_uaLL1.PrincipalID.ToString()), 113 foundItem1.CreatorId, Is.EqualTo(m_uaLL1.PrincipalID.ToString()),
114 "Loaded item non-uuid creator doesn't match original"); 114 "Loaded item non-uuid creator doesn't match original");
115 Assert.That( 115 Assert.That(
116 foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL1.PrincipalID), 116 foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL1.PrincipalID),
117 "Loaded item uuid creator doesn't match original"); 117 "Loaded item uuid creator doesn't match original");
118 Assert.That(foundItem1.Owner, Is.EqualTo(m_uaLL1.PrincipalID), 118 Assert.That(foundItem1.Owner, Is.EqualTo(m_uaLL1.PrincipalID),
119 "Loaded item owner doesn't match inventory reciever"); 119 "Loaded item owner doesn't match inventory reciever");
120 120
121 AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); 121 AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
122 string xmlData = Utils.BytesToString(asset1.Data); 122 string xmlData = Utils.BytesToString(asset1.Data);
123 SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 123 SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
124 124
125 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); 125 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID));
126 } 126 }
127 127
128// /// <summary> 128// /// <summary>
129// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where 129// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
130// /// an account exists with the same name as the creator, though not the same id. 130// /// an account exists with the same name as the creator, though not the same id.
@@ -137,24 +137,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
137// 137//
138// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); 138// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood");
139// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); 139// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire");
140// 140//
141// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); 141// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream);
142// InventoryItemBase foundItem1 142// InventoryItemBase foundItem1
143// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); 143// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
144// 144//
145// Assert.That( 145// Assert.That(
146// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), 146// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()),
147// "Loaded item non-uuid creator doesn't match original"); 147// "Loaded item non-uuid creator doesn't match original");
148// Assert.That( 148// Assert.That(
149// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), 149// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID),
150// "Loaded item uuid creator doesn't match original"); 150// "Loaded item uuid creator doesn't match original");
151// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), 151// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID),
152// "Loaded item owner doesn't match inventory reciever"); 152// "Loaded item owner doesn't match inventory reciever");
153// 153//
154// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); 154// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
155// string xmlData = Utils.BytesToString(asset1.Data); 155// string xmlData = Utils.BytesToString(asset1.Data);
156// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 156// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
157// 157//
158// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); 158// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID));
159// } 159// }
160 160
@@ -167,26 +167,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
167 { 167 {
168 TestHelpers.InMethod(); 168 TestHelpers.InMethod();
169// log4net.Config.XmlConfigurator.Configure(); 169// log4net.Config.XmlConfigurator.Configure();
170 170
171 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "password"); 171 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "password");
172 m_archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/", "password", m_iarStream); 172 m_archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/", "password", m_iarStream);
173 173
174 InventoryItemBase foundItem1 174 InventoryItemBase foundItem1
175 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); 175 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
176 176
177 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); 177 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1");
178 Assert.That( 178 Assert.That(
179 foundItem1.CreatorId, Is.EqualTo(m_uaMT.PrincipalID.ToString()), 179 foundItem1.CreatorId, Is.EqualTo(m_uaMT.PrincipalID.ToString()),
180 "Loaded item non-uuid creator doesn't match that of the loading user"); 180 "Loaded item non-uuid creator doesn't match that of the loading user");
181 Assert.That( 181 Assert.That(
182 foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaMT.PrincipalID), 182 foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaMT.PrincipalID),
183 "Loaded item uuid creator doesn't match that of the loading user"); 183 "Loaded item uuid creator doesn't match that of the loading user");
184 184
185 AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); 185 AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
186 string xmlData = Utils.BytesToString(asset1.Data); 186 string xmlData = Utils.BytesToString(asset1.Data);
187 SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 187 SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
188 188
189 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaMT.PrincipalID)); 189 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaMT.PrincipalID));
190 } 190 }
191 } 191 }
192} \ No newline at end of file 192} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
index 7265405..bd112b4 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
@@ -50,19 +50,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
50 { 50 {
51 protected TestScene m_scene; 51 protected TestScene m_scene;
52 protected InventoryArchiverModule m_archiverModule; 52 protected InventoryArchiverModule m_archiverModule;
53 53
54 [SetUp] 54 [SetUp]
55 public override void SetUp() 55 public override void SetUp()
56 { 56 {
57 base.SetUp(); 57 base.SetUp();
58 58
59 SerialiserModule serialiserModule = new SerialiserModule(); 59 SerialiserModule serialiserModule = new SerialiserModule();
60 m_archiverModule = new InventoryArchiverModule(); 60 m_archiverModule = new InventoryArchiverModule();
61 61
62 m_scene = new SceneHelpers().SetupScene(); 62 m_scene = new SceneHelpers().SetupScene();
63 SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); 63 SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule);
64 } 64 }
65 65
66 /// <summary> 66 /// <summary>
67 /// Test that the IAR has the required files in the right order. 67 /// Test that the IAR has the required files in the right order.
68 /// </summary> 68 /// </summary>
@@ -73,20 +73,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
73 public void TestOrder() 73 public void TestOrder()
74 { 74 {
75 TestHelpers.InMethod(); 75 TestHelpers.InMethod();
76// log4net.Config.XmlConfigurator.Configure(); 76// log4net.Config.XmlConfigurator.Configure();
77 77
78 MemoryStream archiveReadStream = new MemoryStream(m_iarStreamBytes); 78 MemoryStream archiveReadStream = new MemoryStream(m_iarStreamBytes);
79 TarArchiveReader tar = new TarArchiveReader(archiveReadStream); 79 TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
80 string filePath; 80 string filePath;
81 TarArchiveReader.TarEntryType tarEntryType; 81 TarArchiveReader.TarEntryType tarEntryType;
82 82
83 byte[] data = tar.ReadEntry(out filePath, out tarEntryType); 83 byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
84 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 84 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
85 85
86 InventoryArchiveReadRequest iarr 86 InventoryArchiveReadRequest iarr
87 = new InventoryArchiveReadRequest(UUID.Random(), null, null, null, null, null, null, (Stream)null, false); 87 = new InventoryArchiveReadRequest(UUID.Random(), null, null, null, null, null, null, (Stream)null, false);
88 iarr.LoadControlFile(filePath, data); 88 iarr.LoadControlFile(filePath, data);
89 89
90 Assert.That(iarr.ControlFileLoaded, Is.True); 90 Assert.That(iarr.ControlFileLoaded, Is.True);
91 } 91 }
92 92
@@ -119,22 +119,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
119// InventoryArchiveUtils. 119// InventoryArchiveUtils.
120 bool gotObjectsFolder = false; 120 bool gotObjectsFolder = false;
121 121
122 string objectsFolderName 122 string objectsFolderName
123 = string.Format( 123 = string.Format(
124 "{0}{1}", 124 "{0}{1}",
125 ArchiveConstants.INVENTORY_PATH, 125 ArchiveConstants.INVENTORY_PATH,
126 InventoryArchiveWriteRequest.CreateArchiveFolderName( 126 InventoryArchiveWriteRequest.CreateArchiveFolderName(
127 UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, userId, "Objects"))); 127 UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, userId, "Objects")));
128 128
129 string filePath; 129 string filePath;
130 TarArchiveReader.TarEntryType tarEntryType; 130 TarArchiveReader.TarEntryType tarEntryType;
131 131
132 while (tar.ReadEntry(out filePath, out tarEntryType) != null) 132 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
133 { 133 {
134// Console.WriteLine("Got {0}", filePath); 134// Console.WriteLine("Got {0}", filePath);
135 135
136 // Lazily, we only bother to look for the system objects folder created when we call CreateUserWithInventory() 136 // Lazily, we only bother to look for the system objects folder created when we call CreateUserWithInventory()
137 // XXX: But really we need to stop all that stuff being created in tests or check for such folders 137 // XXX: But really we need to stop all that stuff being created in tests or check for such folders
138 // more thoroughly 138 // more thoroughly
139 if (filePath == objectsFolderName) 139 if (filePath == objectsFolderName)
140 gotObjectsFolder = true; 140 gotObjectsFolder = true;
@@ -157,19 +157,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
157 UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); 157 UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword);
158 158
159 // Create base folder 159 // Create base folder
160 InventoryFolderBase f1 160 InventoryFolderBase f1
161 = UserInventoryHelpers.CreateInventoryFolder(m_scene.InventoryService, userId, "f1", true); 161 = UserInventoryHelpers.CreateInventoryFolder(m_scene.InventoryService, userId, "f1", true);
162 162
163 // Create item1 163 // Create item1
164 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, userId, "My Little Dog Object", 0x5); 164 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, userId, "My Little Dog Object", 0x5);
165 InventoryItemBase i1 = UserInventoryHelpers.AddInventoryItem(m_scene, so1, 0x50, 0x60, "f1"); 165 InventoryItemBase i1 = UserInventoryHelpers.AddInventoryItem(m_scene, so1, 0x50, 0x60, "f1");
166 166
167 // Create embedded folder 167 // Create embedded folder
168 InventoryFolderBase f1_1 168 InventoryFolderBase f1_1
169 = UserInventoryHelpers.CreateInventoryFolder(m_scene.InventoryService, userId, "f1/f1.1", true); 169 = UserInventoryHelpers.CreateInventoryFolder(m_scene.InventoryService, userId, "f1/f1.1", true);
170 170
171 // Create embedded item 171 // Create embedded item
172 SceneObjectGroup so1_1 = SceneHelpers.CreateSceneObject(1, userId, "My Little Cat Object", 0x6); 172 SceneObjectGroup so1_1 = SceneHelpers.CreateSceneObject(1, userId, "My Little Cat Object", 0x6);
173 InventoryItemBase i2 = UserInventoryHelpers.AddInventoryItem(m_scene, so1_1, 0x500, 0x600, "f1/f1.1"); 173 InventoryItemBase i2 = UserInventoryHelpers.AddInventoryItem(m_scene, so1_1, 0x500, 0x600, "f1/f1.1");
174 174
175 MemoryStream archiveWriteStream = new MemoryStream(); 175 MemoryStream archiveWriteStream = new MemoryStream();
@@ -188,18 +188,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
188// InventoryArchiveUtils. 188// InventoryArchiveUtils.
189 bool gotf1 = false, gotf1_1 = false, gotso1 = false, gotso2 = false; 189 bool gotf1 = false, gotf1_1 = false, gotso1 = false, gotso2 = false;
190 190
191 string f1FileName 191 string f1FileName
192 = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, InventoryArchiveWriteRequest.CreateArchiveFolderName(f1)); 192 = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, InventoryArchiveWriteRequest.CreateArchiveFolderName(f1));
193 string f1_1FileName 193 string f1_1FileName
194 = string.Format("{0}{1}", f1FileName, InventoryArchiveWriteRequest.CreateArchiveFolderName(f1_1)); 194 = string.Format("{0}{1}", f1FileName, InventoryArchiveWriteRequest.CreateArchiveFolderName(f1_1));
195 string so1FileName 195 string so1FileName
196 = string.Format("{0}{1}", f1FileName, InventoryArchiveWriteRequest.CreateArchiveItemName(i1)); 196 = string.Format("{0}{1}", f1FileName, InventoryArchiveWriteRequest.CreateArchiveItemName(i1));
197 string so2FileName 197 string so2FileName
198 = string.Format("{0}{1}", f1_1FileName, InventoryArchiveWriteRequest.CreateArchiveItemName(i2)); 198 = string.Format("{0}{1}", f1_1FileName, InventoryArchiveWriteRequest.CreateArchiveItemName(i2));
199 199
200 string filePath; 200 string filePath;
201 TarArchiveReader.TarEntryType tarEntryType; 201 TarArchiveReader.TarEntryType tarEntryType;
202 202
203 while (tar.ReadEntry(out filePath, out tarEntryType) != null) 203 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
204 { 204 {
205// Console.WriteLine("Got {0}", filePath); 205// Console.WriteLine("Got {0}", filePath);
@@ -222,7 +222,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
222 222
223 // TODO: Test presence of more files and contents of files. 223 // TODO: Test presence of more files and contents of files.
224 } 224 }
225 225
226 /// <summary> 226 /// <summary>
227 /// Test saving a single inventory item to an IAR 227 /// Test saving a single inventory item to an IAR
228 /// (subject to change since there is no fixed format yet). 228 /// (subject to change since there is no fixed format yet).
@@ -239,10 +239,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
239 string userPassword = "troll"; 239 string userPassword = "troll";
240 UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); 240 UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020");
241 UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); 241 UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword);
242 242
243 // Create asset 243 // Create asset
244 UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); 244 UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040");
245 SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, ownerId, "My Little Dog Object", 0x50); 245 SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, ownerId, "My Little Dog Object", 0x50);
246 246
247 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); 247 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060");
248 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); 248 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1);
@@ -255,7 +255,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
255 item1.Name = item1Name; 255 item1.Name = item1Name;
256 item1.AssetID = asset1.FullID; 256 item1.AssetID = asset1.FullID;
257 item1.ID = item1Id; 257 item1.ID = item1Id;
258 InventoryFolderBase objsFolder 258 InventoryFolderBase objsFolder
259 = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, userId, "Objects")[0]; 259 = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, userId, "Objects")[0];
260 item1.Folder = objsFolder.ID; 260 item1.Folder = objsFolder.ID;
261 m_scene.AddInventoryItem(item1); 261 m_scene.AddInventoryItem(item1);
@@ -285,7 +285,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
285 TarArchiveReader.TarEntryType tarEntryType; 285 TarArchiveReader.TarEntryType tarEntryType;
286 286
287// Console.WriteLine("Reading archive"); 287// Console.WriteLine("Reading archive");
288 288
289 while (tar.ReadEntry(out filePath, out tarEntryType) != null) 289 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
290 { 290 {
291 Console.WriteLine("Got {0}", filePath); 291 Console.WriteLine("Got {0}", filePath);
@@ -294,7 +294,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
294// { 294// {
295// gotControlFile = true; 295// gotControlFile = true;
296// } 296// }
297 297
298 if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml")) 298 if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml"))
299 { 299 {
300// string fileName = filePath.Remove(0, "Objects/".Length); 300// string fileName = filePath.Remove(0, "Objects/".Length);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
index 519c697..0b65829 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
@@ -49,35 +49,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
49 public class InventoryArchiveTestCase : OpenSimTestCase 49 public class InventoryArchiveTestCase : OpenSimTestCase
50 { 50 {
51 protected ManualResetEvent mre = new ManualResetEvent(false); 51 protected ManualResetEvent mre = new ManualResetEvent(false);
52 52
53 /// <summary> 53 /// <summary>
54 /// A raw array of bytes that we'll use to create an IAR memory stream suitable for isolated use in each test. 54 /// A raw array of bytes that we'll use to create an IAR memory stream suitable for isolated use in each test.
55 /// </summary> 55 /// </summary>
56 protected byte[] m_iarStreamBytes; 56 protected byte[] m_iarStreamBytes;
57 57
58 /// <summary> 58 /// <summary>
59 /// Stream of data representing a common IAR for load tests. 59 /// Stream of data representing a common IAR for load tests.
60 /// </summary> 60 /// </summary>
61 protected MemoryStream m_iarStream; 61 protected MemoryStream m_iarStream;
62 62
63 protected UserAccount m_uaMT 63 protected UserAccount m_uaMT
64 = new UserAccount { 64 = new UserAccount {
65 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000555"), 65 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000555"),
66 FirstName = "Mr", 66 FirstName = "Mr",
67 LastName = "Tiddles" }; 67 LastName = "Tiddles" };
68 68
69 protected UserAccount m_uaLL1 69 protected UserAccount m_uaLL1
70 = new UserAccount { 70 = new UserAccount {
71 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000666"), 71 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000666"),
72 FirstName = "Lord", 72 FirstName = "Lord",
73 LastName = "Lucan" }; 73 LastName = "Lucan" };
74 74
75 protected UserAccount m_uaLL2 75 protected UserAccount m_uaLL2
76 = new UserAccount { 76 = new UserAccount {
77 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000777"), 77 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000777"),
78 FirstName = "Lord", 78 FirstName = "Lord",
79 LastName = "Lucan" }; 79 LastName = "Lucan" };
80 80
81 protected string m_item1Name = "Ray Gun Item"; 81 protected string m_item1Name = "Ray Gun Item";
82 protected string m_coaItemName = "Coalesced Item"; 82 protected string m_coaItemName = "Coalesced Item";
83 83
@@ -105,72 +105,72 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
105 base.SetUp(); 105 base.SetUp();
106 m_iarStream = new MemoryStream(m_iarStreamBytes); 106 m_iarStream = new MemoryStream(m_iarStreamBytes);
107 } 107 }
108 108
109 protected void ConstructDefaultIarBytesForTestLoad() 109 protected void ConstructDefaultIarBytesForTestLoad()
110 { 110 {
111// log4net.Config.XmlConfigurator.Configure(); 111// log4net.Config.XmlConfigurator.Configure();
112 112
113 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 113 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
114 Scene scene = new SceneHelpers().SetupScene(); 114 Scene scene = new SceneHelpers().SetupScene();
115 SceneHelpers.SetupSceneModules(scene, archiverModule); 115 SceneHelpers.SetupSceneModules(scene, archiverModule);
116 116
117 UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); 117 UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire");
118 118
119 MemoryStream archiveWriteStream = new MemoryStream(); 119 MemoryStream archiveWriteStream = new MemoryStream();
120 120
121 // Create scene object asset 121 // Create scene object asset
122 UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); 122 UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040");
123 SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, ownerId, "Ray Gun Object", 0x50); 123 SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, ownerId, "Ray Gun Object", 0x50);
124 124
125 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); 125 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060");
126 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); 126 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1);
127 scene.AssetService.Store(asset1); 127 scene.AssetService.Store(asset1);
128 128
129 // Create scene object item 129 // Create scene object item
130 InventoryItemBase item1 = new InventoryItemBase(); 130 InventoryItemBase item1 = new InventoryItemBase();
131 item1.Name = m_item1Name; 131 item1.Name = m_item1Name;
132 item1.ID = UUID.Parse("00000000-0000-0000-0000-000000000020"); 132 item1.ID = UUID.Parse("00000000-0000-0000-0000-000000000020");
133 item1.AssetID = asset1.FullID; 133 item1.AssetID = asset1.FullID;
134 item1.GroupID = UUID.Random(); 134 item1.GroupID = UUID.Random();
135 item1.CreatorId = m_uaLL1.PrincipalID.ToString(); 135 item1.CreatorId = m_uaLL1.PrincipalID.ToString();
136 item1.Owner = m_uaLL1.PrincipalID; 136 item1.Owner = m_uaLL1.PrincipalID;
137 item1.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID; 137 item1.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID;
138 scene.AddInventoryItem(item1); 138 scene.AddInventoryItem(item1);
139 139
140 // Create coalesced objects asset 140 // Create coalesced objects asset
141 SceneObjectGroup cobj1 = SceneHelpers.CreateSceneObject(1, m_uaLL1.PrincipalID, "Object1", 0x120); 141 SceneObjectGroup cobj1 = SceneHelpers.CreateSceneObject(1, m_uaLL1.PrincipalID, "Object1", 0x120);
142 cobj1.AbsolutePosition = new Vector3(15, 30, 45); 142 cobj1.AbsolutePosition = new Vector3(15, 30, 45);
143 143
144 SceneObjectGroup cobj2 = SceneHelpers.CreateSceneObject(1, m_uaLL1.PrincipalID, "Object2", 0x140); 144 SceneObjectGroup cobj2 = SceneHelpers.CreateSceneObject(1, m_uaLL1.PrincipalID, "Object2", 0x140);
145 cobj2.AbsolutePosition = new Vector3(25, 50, 75); 145 cobj2.AbsolutePosition = new Vector3(25, 50, 75);
146 146
147 CoalescedSceneObjects coa = new CoalescedSceneObjects(m_uaLL1.PrincipalID, cobj1, cobj2); 147 CoalescedSceneObjects coa = new CoalescedSceneObjects(m_uaLL1.PrincipalID, cobj1, cobj2);
148 148
149 AssetBase coaAsset = AssetHelpers.CreateAsset(0x160, coa); 149 AssetBase coaAsset = AssetHelpers.CreateAsset(0x160, coa);
150 scene.AssetService.Store(coaAsset); 150 scene.AssetService.Store(coaAsset);
151 151
152 // Create coalesced objects inventory item 152 // Create coalesced objects inventory item
153 InventoryItemBase coaItem = new InventoryItemBase(); 153 InventoryItemBase coaItem = new InventoryItemBase();
154 coaItem.Name = m_coaItemName; 154 coaItem.Name = m_coaItemName;
155 coaItem.ID = UUID.Parse("00000000-0000-0000-0000-000000000180"); 155 coaItem.ID = UUID.Parse("00000000-0000-0000-0000-000000000180");
156 coaItem.AssetID = coaAsset.FullID; 156 coaItem.AssetID = coaAsset.FullID;
157 coaItem.GroupID = UUID.Random(); 157 coaItem.GroupID = UUID.Random();
158 coaItem.CreatorId = m_uaLL1.PrincipalID.ToString(); 158 coaItem.CreatorId = m_uaLL1.PrincipalID.ToString();
159 coaItem.Owner = m_uaLL1.PrincipalID; 159 coaItem.Owner = m_uaLL1.PrincipalID;
160 coaItem.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID; 160 coaItem.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID;
161 scene.AddInventoryItem(coaItem); 161 scene.AddInventoryItem(coaItem);
162 162
163 archiverModule.ArchiveInventory( 163 archiverModule.ArchiveInventory(
164 UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/*", "hampshire", archiveWriteStream); 164 UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/*", "hampshire", archiveWriteStream);
165 165
166 m_iarStreamBytes = archiveWriteStream.ToArray(); 166 m_iarStreamBytes = archiveWriteStream.ToArray();
167 } 167 }
168 168
169 protected void SaveCompleted( 169 protected void SaveCompleted(
170 UUID id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, 170 UUID id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream,
171 Exception reportedException, int SaveCount, int FilterCount) 171 Exception reportedException, int SaveCount, int FilterCount)
172 { 172 {
173 mre.Set(); 173 mre.Set();
174 } 174 }
175 } 175 }
176} \ No newline at end of file 176} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index bba48cc..5d7f25c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -149,10 +149,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
149 private void OnInstantMessage(IClientAPI client, GridInstantMessage im) 149 private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
150 { 150 {
151// m_log.DebugFormat( 151// m_log.DebugFormat(
152// "[INVENTORY TRANSFER]: {0} IM type received from client {1}. From={2} ({3}), To={4}", 152// "[INVENTORY TRANSFER]: {0} IM type received from client {1}. From={2} ({3}), To={4}",
153// (InstantMessageDialog)im.dialog, client.Name, 153// (InstantMessageDialog)im.dialog, client.Name,
154// im.fromAgentID, im.fromAgentName, im.toAgentID); 154// im.fromAgentID, im.fromAgentName, im.toAgentID);
155 155
156 Scene scene = FindClientScene(client.AgentId); 156 Scene scene = FindClientScene(client.AgentId);
157 157
158 if (scene == null) // Something seriously wrong here. 158 if (scene == null) // Something seriously wrong here.
@@ -164,31 +164,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
164 164
165 if (im.binaryBucket.Length < 17) // Invalid 165 if (im.binaryBucket.Length < 17) // Invalid
166 return; 166 return;
167 167
168 UUID receipientID = new UUID(im.toAgentID); 168 UUID recipientID = new UUID(im.toAgentID);
169 ScenePresence user = scene.GetScenePresence(receipientID); 169 ScenePresence user = scene.GetScenePresence(recipientID);
170 UUID copyID; 170 UUID copyID;
171 171
172 // First byte is the asset type 172 // First byte is the asset type
173 AssetType assetType = (AssetType)im.binaryBucket[0]; 173 AssetType assetType = (AssetType)im.binaryBucket[0];
174 174
175 if (AssetType.Folder == assetType) 175 if (AssetType.Folder == assetType)
176 { 176 {
177 UUID folderID = new UUID(im.binaryBucket, 1); 177 UUID folderID = new UUID(im.binaryBucket, 1);
178 178
179 m_log.DebugFormat( 179 m_log.DebugFormat(
180 "[INVENTORY TRANSFER]: Inserting original folder {0} into agent {1}'s inventory", 180 "[INVENTORY TRANSFER]: Inserting original folder {0} into agent {1}'s inventory",
181 folderID, new UUID(im.toAgentID)); 181 folderID, new UUID(im.toAgentID));
182 182
183 InventoryFolderBase folderCopy 183 InventoryFolderBase folderCopy
184 = scene.GiveInventoryFolder(client, receipientID, client.AgentId, folderID, UUID.Zero); 184 = scene.GiveInventoryFolder(client, recipientID, client.AgentId, folderID, UUID.Zero);
185 185
186 if (folderCopy == null) 186 if (folderCopy == null)
187 { 187 {
188 client.SendAgentAlertMessage("Can't find folder to give. Nothing given.", false); 188 client.SendAgentAlertMessage("Can't find folder to give. Nothing given.", false);
189 return; 189 return;
190 } 190 }
191 191
192 // The outgoing binary bucket should contain only the byte which signals an asset folder is 192 // The outgoing binary bucket should contain only the byte which signals an asset folder is
193 // being copied and the following bytes for the copied folder's UUID 193 // being copied and the following bytes for the copied folder's UUID
194 copyID = folderCopy.ID; 194 copyID = folderCopy.ID;
@@ -196,7 +196,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
196 im.binaryBucket = new byte[1 + copyIDBytes.Length]; 196 im.binaryBucket = new byte[1 + copyIDBytes.Length];
197 im.binaryBucket[0] = (byte)AssetType.Folder; 197 im.binaryBucket[0] = (byte)AssetType.Folder;
198 Array.Copy(copyIDBytes, 0, im.binaryBucket, 1, copyIDBytes.Length); 198 Array.Copy(copyIDBytes, 0, im.binaryBucket, 1, copyIDBytes.Length);
199 199
200 if (user != null) 200 if (user != null)
201 user.ControllingClient.SendBulkUpdateInventory(folderCopy); 201 user.ControllingClient.SendBulkUpdateInventory(folderCopy);
202 202
@@ -225,10 +225,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
225 client.SendAgentAlertMessage(message, false); 225 client.SendAgentAlertMessage(message, false);
226 return; 226 return;
227 } 227 }
228 228
229 copyID = itemCopy.ID; 229 copyID = itemCopy.ID;
230 Array.Copy(copyID.GetBytes(), 0, im.binaryBucket, 1, 16); 230 Array.Copy(copyID.GetBytes(), 0, im.binaryBucket, 1, 16);
231 231
232 if (user != null) 232 if (user != null)
233 user.ControllingClient.SendBulkUpdateInventory(itemCopy); 233 user.ControllingClient.SendBulkUpdateInventory(itemCopy);
234 234
@@ -239,6 +239,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
239 im.imSessionID = copyID.Guid; 239 im.imSessionID = copyID.Guid;
240 } 240 }
241 241
242 im.offline = 0;
243
242 // Send the IM to the recipient. The item is already 244 // Send the IM to the recipient. The item is already
243 // in their inventory, so it will not be lost if 245 // in their inventory, so it will not be lost if
244 // they are offline. 246 // they are offline.
@@ -251,15 +253,47 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
251 else 253 else
252 { 254 {
253 if (m_TransferModule != null) 255 if (m_TransferModule != null)
254 m_TransferModule.SendInstantMessage(im, delegate(bool success) 256 m_TransferModule.SendInstantMessage(im, delegate(bool success)
255 { 257 {
256 if (!success) 258 if (!success)
257 client.SendAlertMessage("User not online. Inventory has been saved"); 259 client.SendAlertMessage("User not online. Inventory has been saved");
258 }); 260 });
259 } 261 }
260 } 262 }
261 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted) 263 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted ||
264 im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
262 { 265 {
266 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
267 IInventoryService invService = scene.InventoryService;
268
269 // Special case: folder redirect.
270 // RLV uses this
271 if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
272 {
273 InventoryFolderBase folder = invService.GetFolder(client.AgentId, inventoryID);
274
275 if (folder != null)
276 {
277 if (im.binaryBucket.Length >= 16)
278 {
279 UUID destFolderID = new UUID(im.binaryBucket, 0);
280 if (destFolderID != UUID.Zero)
281 {
282 InventoryFolderBase destFolder = invService.GetFolder(client.AgentId, destFolderID);
283 if (destFolder != null)
284 {
285 if (folder.ParentID != destFolder.ID)
286 {
287 folder.ParentID = destFolder.ID;
288 invService.MoveFolder(folder);
289 client.SendBulkUpdateInventory(folder);
290 }
291 }
292 }
293 }
294 }
295 }
296
263 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); 297 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
264 298
265 if (user != null) // Local 299 if (user != null) // Local
@@ -269,33 +303,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
269 else 303 else
270 { 304 {
271 if (m_TransferModule != null) 305 if (m_TransferModule != null)
272 m_TransferModule.SendInstantMessage(im, delegate(bool success) { 306 m_TransferModule.SendInstantMessage(im, delegate(bool success) {});
273
274 // justincc - FIXME: Comment out for now. This code was added in commit db91044 Mon Aug 22 2011
275 // and is apparently supposed to fix bulk inventory updates after accepting items. But
276 // instead it appears to cause two copies of an accepted folder for the receiving user in
277 // at least some cases. Folder/item update is already done when the offer is made (see code above)
278
279// // Send BulkUpdateInventory
280// IInventoryService invService = scene.InventoryService;
281// UUID inventoryEntityID = new UUID(im.imSessionID); // The inventory item /folder, back from it's trip
282//
283// InventoryFolderBase folder = new InventoryFolderBase(inventoryEntityID, client.AgentId);
284// folder = invService.GetFolder(folder);
285//
286// ScenePresence fromUser = scene.GetScenePresence(new UUID(im.fromAgentID));
287//
288// // If the user has left the scene by the time the message comes back then we can't send
289// // them the update.
290// if (fromUser != null)
291// fromUser.ControllingClient.SendBulkUpdateInventory(folder);
292 });
293 } 307 }
294 } 308 }
295 309
296 // XXX: This code was placed here to try and accomodate RLV which moves given folders named #RLV/~<name> 310 // XXX: This code was placed here to try and accomodate RLV which moves given folders named #RLV/~<name>
297 // to the requested folder, which in this case is #RLV. However, it is the viewer that appears to be 311 // to the requested folder, which in this case is #RLV. However, it is the viewer that appears to be
298 // response from renaming the #RLV/~example folder to ~example. For some reason this is not yet 312 // response from renaming the #RLV/~example folder to ~example. For some reason this is not yet
299 // happening, possibly because we are not sending the correct inventory update messages with the correct 313 // happening, possibly because we are not sending the correct inventory update messages with the correct
300 // transaction IDs 314 // transaction IDs
301 else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) 315 else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
@@ -310,21 +324,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
310 if (destinationFolderID != UUID.Zero) 324 if (destinationFolderID != UUID.Zero)
311 { 325 {
312 InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId); 326 InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId);
313 if (destinationFolder == null)
314 {
315 m_log.WarnFormat(
316 "[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist",
317 client.Name, scene.Name, destinationFolderID);
318
319 return;
320 }
321
322 IInventoryService invService = scene.InventoryService; 327 IInventoryService invService = scene.InventoryService;
323 328
324 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip 329 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
325 330
326 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); 331 InventoryItemBase item = invService.GetItem(client.AgentId, inventoryID);
327 item = invService.GetItem(item);
328 InventoryFolderBase folder = null; 332 InventoryFolderBase folder = null;
329 UUID? previousParentFolderID = null; 333 UUID? previousParentFolderID = null;
330 334
@@ -338,8 +342,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
338 } 342 }
339 else 343 else
340 { 344 {
341 folder = new InventoryFolderBase(inventoryID, client.AgentId); 345 folder = invService.GetFolder(client.AgentId, inventoryID);
342 folder = invService.GetFolder(folder);
343 346
344 if (folder != null) // It's a folder 347 if (folder != null) // It's a folder
345 { 348 {
@@ -352,9 +355,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
352 // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). 355 // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code).
353 if (previousParentFolderID != null) 356 if (previousParentFolderID != null)
354 { 357 {
355 InventoryFolderBase previousParentFolder 358 InventoryFolderBase previousParentFolder = invService.GetFolder(client.AgentId, (UUID)previousParentFolderID);
356 = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId);
357 previousParentFolder = invService.GetFolder(previousParentFolder);
358 scene.SendInventoryUpdate(client, previousParentFolder, true, true); 359 scene.SendInventoryUpdate(client, previousParentFolder, true, true);
359 360
360 scene.SendInventoryUpdate(client, destinationFolder, true, true); 361 scene.SendInventoryUpdate(client, destinationFolder, true, true);
@@ -376,11 +377,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
376 377
377 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip 378 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
378 379
379 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); 380 InventoryItemBase item = invService.GetItem(client.AgentId, inventoryID);
380 item = invService.GetItem(item);
381 InventoryFolderBase folder = null; 381 InventoryFolderBase folder = null;
382 UUID? previousParentFolderID = null; 382 UUID? previousParentFolderID = null;
383 383
384 if (item != null && trashFolder != null) 384 if (item != null && trashFolder != null)
385 { 385 {
386 previousParentFolderID = item.Folder; 386 previousParentFolderID = item.Folder;
@@ -394,37 +394,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
394 } 394 }
395 else 395 else
396 { 396 {
397 folder = new InventoryFolderBase(inventoryID, client.AgentId); 397 folder = invService.GetFolder(client.AgentId, inventoryID);
398 folder = invService.GetFolder(folder);
399 398
400 if (folder != null & trashFolder != null) 399 if (folder != null & trashFolder != null)
401 { 400 {
402 previousParentFolderID = folder.ParentID; 401 previousParentFolderID = folder.ParentID;
403 folder.ParentID = trashFolder.ID; 402 folder.ParentID = trashFolder.ID;
404 invService.MoveFolder(folder); 403 invService.MoveFolder(folder);
404 client.SendBulkUpdateInventory(folder);
405 } 405 }
406 } 406 }
407 407
408 if ((null == item && null == folder) | null == trashFolder) 408 if ((null == item && null == folder) | null == trashFolder)
409 { 409 {
410 string reason = String.Empty; 410 string reason = String.Empty;
411 411
412 if (trashFolder == null) 412 if (trashFolder == null)
413 reason += " Trash folder not found."; 413 reason += " Trash folder not found.";
414 if (item == null) 414 if (item == null)
415 reason += " Item not found."; 415 reason += " Item not found.";
416 if (folder == null) 416 if (folder == null)
417 reason += " Folder not found."; 417 reason += " Folder not found.";
418 418
419 client.SendAgentAlertMessage("Unable to delete "+ 419 client.SendAgentAlertMessage("Unable to delete "+
420 "received inventory" + reason, false); 420 "received inventory" + reason, false);
421 } 421 }
422 // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). 422 // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code).
423 else if (previousParentFolderID != null) 423 else if (previousParentFolderID != null)
424 { 424 {
425 InventoryFolderBase previousParentFolder 425 InventoryFolderBase previousParentFolder = invService.GetFolder(client.AgentId, (UUID)previousParentFolderID);
426 = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId);
427 previousParentFolder = invService.GetFolder(previousParentFolder);
428 scene.SendInventoryUpdate(client, previousParentFolder, true, true); 426 scene.SendInventoryUpdate(client, previousParentFolder, true, true);
429 427
430 scene.SendInventoryUpdate(client, trashFolder, true, true); 428 scene.SendInventoryUpdate(client, trashFolder, true, true);
@@ -453,18 +451,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
453 /// <param name="im"></param> 451 /// <param name="im"></param>
454 private void OnGridInstantMessage(GridInstantMessage im) 452 private void OnGridInstantMessage(GridInstantMessage im)
455 { 453 {
456 // Check if it's a type of message that we should handle
457 if (!((im.dialog == (byte) InstantMessageDialog.InventoryOffered)
458 || (im.dialog == (byte) InstantMessageDialog.TaskInventoryOffered)
459 || (im.dialog == (byte) InstantMessageDialog.InventoryAccepted)
460 || (im.dialog == (byte) InstantMessageDialog.InventoryDeclined)
461 || (im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined)))
462 return;
463
464 m_log.DebugFormat(
465 "[INVENTORY TRANSFER]: {0} IM type received from grid. From={1} ({2}), To={3}",
466 (InstantMessageDialog)im.dialog, im.fromAgentID, im.fromAgentName, im.toAgentID);
467
468 // Check if this is ours to handle 454 // Check if this is ours to handle
469 // 455 //
470 Scene scene = FindClientScene(new UUID(im.toAgentID)); 456 Scene scene = FindClientScene(new UUID(im.toAgentID));
@@ -475,32 +461,92 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
475 // Find agent to deliver to 461 // Find agent to deliver to
476 // 462 //
477 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); 463 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
464 if (user == null)
465 return;
478 466
479 if (user != null) 467 // This requires a little bit of processing because we have to make the
468 // new item visible in the recipient's inventory here
469 //
470 if (im.dialog == (byte) InstantMessageDialog.InventoryOffered)
480 { 471 {
481 user.ControllingClient.SendInstantMessage(im); 472 if (im.binaryBucket.Length < 17) // Invalid
473 return;
482 474
483 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered) 475 UUID recipientID = new UUID(im.toAgentID);
476
477 // First byte is the asset type
478 AssetType assetType = (AssetType)im.binaryBucket[0];
479
480 if (AssetType.Folder == assetType)
484 { 481 {
485 AssetType assetType = (AssetType)im.binaryBucket[0]; 482 UUID folderID = new UUID(im.binaryBucket, 1);
486 UUID inventoryID = new UUID(im.binaryBucket, 1); 483
487 484 InventoryFolderBase folder =
488 IInventoryService invService = scene.InventoryService; 485 scene.InventoryService.GetFolder(recipientID, folderID);
489 InventoryNodeBase node = null; 486
490 if (AssetType.Folder == assetType) 487 if (folder != null)
488 user.ControllingClient.SendBulkUpdateInventory(folder);
489 }
490 else
491 {
492 UUID itemID = new UUID(im.binaryBucket, 1);
493
494 InventoryItemBase item =
495 scene.InventoryService.GetItem(recipientID, itemID);
496
497 if (item != null)
491 { 498 {
492 InventoryFolderBase folder = new InventoryFolderBase(inventoryID, new UUID(im.toAgentID)); 499 user.ControllingClient.SendBulkUpdateInventory(item);
493 node = invService.GetFolder(folder);
494 } 500 }
495 else 501 }
502 user.ControllingClient.SendInstantMessage(im);
503 }
504 if (im.dialog == (byte) InstantMessageDialog.TaskInventoryOffered)
505 {
506 if (im.binaryBucket.Length < 1) // Invalid
507 return;
508
509 UUID recipientID = new UUID(im.toAgentID);
510
511 // Bucket is the asset type
512 AssetType assetType = (AssetType)im.binaryBucket[0];
513
514 if (AssetType.Folder == assetType)
515 {
516 UUID folderID = new UUID(im.imSessionID);
517
518 InventoryFolderBase folder =
519 scene.InventoryService.GetFolder(recipientID, folderID);
520
521 if (folder != null)
522 user.ControllingClient.SendBulkUpdateInventory(folder);
523 }
524 else
525 {
526 UUID itemID = new UUID(im.imSessionID);
527
528 InventoryItemBase item =
529 scene.InventoryService.GetItem(recipientID, itemID);
530
531 if (item != null)
496 { 532 {
497 InventoryItemBase item = new InventoryItemBase(inventoryID, new UUID(im.toAgentID)); 533 user.ControllingClient.SendBulkUpdateInventory(item);
498 node = invService.GetItem(item);
499 } 534 }
500
501 if (node != null)
502 user.ControllingClient.SendBulkUpdateInventory(node);
503 } 535 }
536
537 // Fix up binary bucket since this may be 17 chars long here
538 Byte[] bucket = new Byte[1];
539 bucket[0] = im.binaryBucket[0];
540 im.binaryBucket = bucket;
541
542 user.ControllingClient.SendInstantMessage(im);
543 }
544 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted ||
545 im.dialog == (byte) InstantMessageDialog.InventoryDeclined ||
546 im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined ||
547 im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
548 {
549 user.ControllingClient.SendInstantMessage(im);
504 } 550 }
505 } 551 }
506 } 552 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs
index 7ddc396..82ed091 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs
@@ -44,9 +44,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
44{ 44{
45 [TestFixture] 45 [TestFixture]
46 public class InventoryTransferModuleTests : OpenSimTestCase 46 public class InventoryTransferModuleTests : OpenSimTestCase
47 { 47 {
48 protected TestScene m_scene; 48 protected TestScene m_scene;
49 49
50 [SetUp] 50 [SetUp]
51 public override void SetUp() 51 public override void SetUp()
52 { 52 {
@@ -56,9 +56,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
56 config.AddConfig("Messaging"); 56 config.AddConfig("Messaging");
57 config.Configs["Messaging"].Set("InventoryTransferModule", "InventoryTransferModule"); 57 config.Configs["Messaging"].Set("InventoryTransferModule", "InventoryTransferModule");
58 58
59 m_scene = new SceneHelpers().SetupScene(); 59 m_scene = new SceneHelpers().SetupScene();
60 SceneHelpers.SetupSceneModules(m_scene, config, new InventoryTransferModule()); 60 SceneHelpers.SetupSceneModules(m_scene, config, new InventoryTransferModule());
61 } 61 }
62 62
63 [Test] 63 [Test]
64 public void TestAcceptGivenItem() 64 public void TestAcceptGivenItem()
@@ -69,9 +69,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
69 UUID itemId = TestHelpers.ParseTail(0x100); 69 UUID itemId = TestHelpers.ParseTail(0x100);
70 UUID assetId = TestHelpers.ParseTail(0x200); 70 UUID assetId = TestHelpers.ParseTail(0x200);
71 71
72 UserAccount ua1 72 UserAccount ua1
73 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw"); 73 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
74 UserAccount ua2 74 UserAccount ua2
75 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw"); 75 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
76 76
77 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1); 77 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
@@ -81,7 +81,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
81 TestClient receiverClient = (TestClient)receiverSp.ControllingClient; 81 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
82 82
83 // Create the object to test give 83 // Create the object to test give
84 InventoryItemBase originalItem 84 InventoryItemBase originalItem
85 = UserInventoryHelpers.CreateInventoryItem( 85 = UserInventoryHelpers.CreateInventoryItem(
86 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object); 86 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object);
87 87
@@ -89,35 +89,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
89 byte[] itemIdBytes = itemId.GetBytes(); 89 byte[] itemIdBytes = itemId.GetBytes();
90 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); 90 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
91 91
92 GridInstantMessage giveIm 92 GridInstantMessage giveIm
93 = new GridInstantMessage( 93 = new GridInstantMessage(
94 m_scene, 94 m_scene,
95 giverSp.UUID, 95 giverSp.UUID,
96 giverSp.Name, 96 giverSp.Name,
97 receiverSp.UUID, 97 receiverSp.UUID,
98 (byte)InstantMessageDialog.InventoryOffered, 98 (byte)InstantMessageDialog.InventoryOffered,
99 false, 99 false,
100 "inventory offered msg", 100 "inventory offered msg",
101 initialSessionId, 101 initialSessionId,
102 false, 102 false,
103 Vector3.Zero, 103 Vector3.Zero,
104 giveImBinaryBucket, 104 giveImBinaryBucket,
105 true); 105 true);
106 106
107 giverClient.HandleImprovedInstantMessage(giveIm); 107 giverClient.HandleImprovedInstantMessage(giveIm);
108 108
109 // These details might not all be correct. 109 // These details might not all be correct.
110 GridInstantMessage acceptIm 110 GridInstantMessage acceptIm
111 = new GridInstantMessage( 111 = new GridInstantMessage(
112 m_scene, 112 m_scene,
113 receiverSp.UUID, 113 receiverSp.UUID,
114 receiverSp.Name, 114 receiverSp.Name,
115 giverSp.UUID, 115 giverSp.UUID,
116 (byte)InstantMessageDialog.InventoryAccepted, 116 (byte)InstantMessageDialog.InventoryAccepted,
117 false, 117 false,
118 "inventory accepted msg", 118 "inventory accepted msg",
119 initialSessionId, 119 initialSessionId,
120 false, 120 false,
121 Vector3.Zero, 121 Vector3.Zero,
122 null, 122 null,
123 true); 123 true);
@@ -133,7 +133,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
133 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID)); 133 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID));
134 134
135 // Test for item successfully making it into the receiver's inventory 135 // Test for item successfully making it into the receiver's inventory
136 InventoryItemBase receivedItem 136 InventoryItemBase receivedItem
137 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Objects/givenObj"); 137 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Objects/givenObj");
138 138
139 Assert.That(receivedItem, Is.Not.Null); 139 Assert.That(receivedItem, Is.Not.Null);
@@ -148,7 +148,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
148 Assert.That(originalItemAfterDelete, Is.Not.Null); 148 Assert.That(originalItemAfterDelete, Is.Not.Null);
149 149
150 // TODO: Test scenario where giver deletes their item first. 150 // TODO: Test scenario where giver deletes their item first.
151 } 151 }
152 152
153 /// <summary> 153 /// <summary>
154 /// Test user rejection of a given item. 154 /// Test user rejection of a given item.
@@ -165,9 +165,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
165 UUID itemId = TestHelpers.ParseTail(0x100); 165 UUID itemId = TestHelpers.ParseTail(0x100);
166 UUID assetId = TestHelpers.ParseTail(0x200); 166 UUID assetId = TestHelpers.ParseTail(0x200);
167 167
168 UserAccount ua1 168 UserAccount ua1
169 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw"); 169 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
170 UserAccount ua2 170 UserAccount ua2
171 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw"); 171 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
172 172
173 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1); 173 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
@@ -177,7 +177,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
177 TestClient receiverClient = (TestClient)receiverSp.ControllingClient; 177 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
178 178
179 // Create the object to test give 179 // Create the object to test give
180 InventoryItemBase originalItem 180 InventoryItemBase originalItem
181 = UserInventoryHelpers.CreateInventoryItem( 181 = UserInventoryHelpers.CreateInventoryItem(
182 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object); 182 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object);
183 183
@@ -188,36 +188,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
188 byte[] itemIdBytes = itemId.GetBytes(); 188 byte[] itemIdBytes = itemId.GetBytes();
189 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); 189 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
190 190
191 GridInstantMessage giveIm 191 GridInstantMessage giveIm
192 = new GridInstantMessage( 192 = new GridInstantMessage(
193 m_scene, 193 m_scene,
194 giverSp.UUID, 194 giverSp.UUID,
195 giverSp.Name, 195 giverSp.Name,
196 receiverSp.UUID, 196 receiverSp.UUID,
197 (byte)InstantMessageDialog.InventoryOffered, 197 (byte)InstantMessageDialog.InventoryOffered,
198 false, 198 false,
199 "inventory offered msg", 199 "inventory offered msg",
200 initialSessionId, 200 initialSessionId,
201 false, 201 false,
202 Vector3.Zero, 202 Vector3.Zero,
203 giveImBinaryBucket, 203 giveImBinaryBucket,
204 true); 204 true);
205 205
206 giverClient.HandleImprovedInstantMessage(giveIm); 206 giverClient.HandleImprovedInstantMessage(giveIm);
207 207
208 // These details might not all be correct. 208 // These details might not all be correct.
209 // Session ID is now the created item ID (!) 209 // Session ID is now the created item ID (!)
210 GridInstantMessage rejectIm 210 GridInstantMessage rejectIm
211 = new GridInstantMessage( 211 = new GridInstantMessage(
212 m_scene, 212 m_scene,
213 receiverSp.UUID, 213 receiverSp.UUID,
214 receiverSp.Name, 214 receiverSp.Name,
215 giverSp.UUID, 215 giverSp.UUID,
216 (byte)InstantMessageDialog.InventoryDeclined, 216 (byte)InstantMessageDialog.InventoryDeclined,
217 false, 217 false,
218 "inventory declined msg", 218 "inventory declined msg",
219 new UUID(receivedIm.imSessionID), 219 new UUID(receivedIm.imSessionID),
220 false, 220 false,
221 Vector3.Zero, 221 Vector3.Zero,
222 null, 222 null,
223 true); 223 true);
@@ -233,7 +233,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
233 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID)); 233 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID));
234 234
235 // Test for item successfully making it into the receiver's inventory 235 // Test for item successfully making it into the receiver's inventory
236 InventoryItemBase receivedItem 236 InventoryItemBase receivedItem
237 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Trash/givenObj"); 237 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Trash/givenObj");
238 238
239 InventoryFolderBase trashFolder 239 InventoryFolderBase trashFolder
@@ -250,7 +250,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
250 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj"); 250 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
251 251
252 Assert.That(originalItemAfterDelete, Is.Not.Null); 252 Assert.That(originalItemAfterDelete, Is.Not.Null);
253 } 253 }
254 254
255 [Test] 255 [Test]
256 public void TestAcceptGivenFolder() 256 public void TestAcceptGivenFolder()
@@ -261,9 +261,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
261 UUID initialSessionId = TestHelpers.ParseTail(0x10); 261 UUID initialSessionId = TestHelpers.ParseTail(0x10);
262 UUID folderId = TestHelpers.ParseTail(0x100); 262 UUID folderId = TestHelpers.ParseTail(0x100);
263 263
264 UserAccount ua1 264 UserAccount ua1
265 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw"); 265 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
266 UserAccount ua2 266 UserAccount ua2
267 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw"); 267 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
268 268
269 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1); 269 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
@@ -272,7 +272,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
272 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2); 272 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
273 TestClient receiverClient = (TestClient)receiverSp.ControllingClient; 273 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
274 274
275 InventoryFolderBase originalFolder 275 InventoryFolderBase originalFolder
276 = UserInventoryHelpers.CreateInventoryFolder( 276 = UserInventoryHelpers.CreateInventoryFolder(
277 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true); 277 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true);
278 278
@@ -281,35 +281,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
281 byte[] itemIdBytes = folderId.GetBytes(); 281 byte[] itemIdBytes = folderId.GetBytes();
282 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); 282 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
283 283
284 GridInstantMessage giveIm 284 GridInstantMessage giveIm
285 = new GridInstantMessage( 285 = new GridInstantMessage(
286 m_scene, 286 m_scene,
287 giverSp.UUID, 287 giverSp.UUID,
288 giverSp.Name, 288 giverSp.Name,
289 receiverSp.UUID, 289 receiverSp.UUID,
290 (byte)InstantMessageDialog.InventoryOffered, 290 (byte)InstantMessageDialog.InventoryOffered,
291 false, 291 false,
292 "inventory offered msg", 292 "inventory offered msg",
293 initialSessionId, 293 initialSessionId,
294 false, 294 false,
295 Vector3.Zero, 295 Vector3.Zero,
296 giveImBinaryBucket, 296 giveImBinaryBucket,
297 true); 297 true);
298 298
299 giverClient.HandleImprovedInstantMessage(giveIm); 299 giverClient.HandleImprovedInstantMessage(giveIm);
300 300
301 // These details might not all be correct. 301 // These details might not all be correct.
302 GridInstantMessage acceptIm 302 GridInstantMessage acceptIm
303 = new GridInstantMessage( 303 = new GridInstantMessage(
304 m_scene, 304 m_scene,
305 receiverSp.UUID, 305 receiverSp.UUID,
306 receiverSp.Name, 306 receiverSp.Name,
307 giverSp.UUID, 307 giverSp.UUID,
308 (byte)InstantMessageDialog.InventoryAccepted, 308 (byte)InstantMessageDialog.InventoryAccepted,
309 false, 309 false,
310 "inventory accepted msg", 310 "inventory accepted msg",
311 initialSessionId, 311 initialSessionId,
312 false, 312 false,
313 Vector3.Zero, 313 Vector3.Zero,
314 null, 314 null,
315 true); 315 true);
@@ -325,7 +325,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
325 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID)); 325 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID));
326 326
327 // Test for item successfully making it into the receiver's inventory 327 // Test for item successfully making it into the receiver's inventory
328 InventoryFolderBase receivedFolder 328 InventoryFolderBase receivedFolder
329 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "f1"); 329 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "f1");
330 330
331 Assert.That(receivedFolder, Is.Not.Null); 331 Assert.That(receivedFolder, Is.Not.Null);
@@ -340,7 +340,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
340 Assert.That(originalFolderAfterDelete, Is.Not.Null); 340 Assert.That(originalFolderAfterDelete, Is.Not.Null);
341 341
342 // TODO: Test scenario where giver deletes their item first. 342 // TODO: Test scenario where giver deletes their item first.
343 } 343 }
344 344
345 /// <summary> 345 /// <summary>
346 /// Test user rejection of a given item. 346 /// Test user rejection of a given item.
@@ -357,9 +357,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
357 UUID initialSessionId = TestHelpers.ParseTail(0x10); 357 UUID initialSessionId = TestHelpers.ParseTail(0x10);
358 UUID folderId = TestHelpers.ParseTail(0x100); 358 UUID folderId = TestHelpers.ParseTail(0x100);
359 359
360 UserAccount ua1 360 UserAccount ua1
361 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw"); 361 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
362 UserAccount ua2 362 UserAccount ua2
363 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw"); 363 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
364 364
365 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1); 365 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
@@ -369,7 +369,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
369 TestClient receiverClient = (TestClient)receiverSp.ControllingClient; 369 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
370 370
371 // Create the folder to test give 371 // Create the folder to test give
372 InventoryFolderBase originalFolder 372 InventoryFolderBase originalFolder
373 = UserInventoryHelpers.CreateInventoryFolder( 373 = UserInventoryHelpers.CreateInventoryFolder(
374 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true); 374 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true);
375 375
@@ -381,36 +381,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
381 byte[] itemIdBytes = folderId.GetBytes(); 381 byte[] itemIdBytes = folderId.GetBytes();
382 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); 382 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
383 383
384 GridInstantMessage giveIm 384 GridInstantMessage giveIm
385 = new GridInstantMessage( 385 = new GridInstantMessage(
386 m_scene, 386 m_scene,
387 giverSp.UUID, 387 giverSp.UUID,
388 giverSp.Name, 388 giverSp.Name,
389 receiverSp.UUID, 389 receiverSp.UUID,
390 (byte)InstantMessageDialog.InventoryOffered, 390 (byte)InstantMessageDialog.InventoryOffered,
391 false, 391 false,
392 "inventory offered msg", 392 "inventory offered msg",
393 initialSessionId, 393 initialSessionId,
394 false, 394 false,
395 Vector3.Zero, 395 Vector3.Zero,
396 giveImBinaryBucket, 396 giveImBinaryBucket,
397 true); 397 true);
398 398
399 giverClient.HandleImprovedInstantMessage(giveIm); 399 giverClient.HandleImprovedInstantMessage(giveIm);
400 400
401 // These details might not all be correct. 401 // These details might not all be correct.
402 // Session ID is now the created item ID (!) 402 // Session ID is now the created item ID (!)
403 GridInstantMessage rejectIm 403 GridInstantMessage rejectIm
404 = new GridInstantMessage( 404 = new GridInstantMessage(
405 m_scene, 405 m_scene,
406 receiverSp.UUID, 406 receiverSp.UUID,
407 receiverSp.Name, 407 receiverSp.Name,
408 giverSp.UUID, 408 giverSp.UUID,
409 (byte)InstantMessageDialog.InventoryDeclined, 409 (byte)InstantMessageDialog.InventoryDeclined,
410 false, 410 false,
411 "inventory declined msg", 411 "inventory declined msg",
412 new UUID(receivedIm.imSessionID), 412 new UUID(receivedIm.imSessionID),
413 false, 413 false,
414 Vector3.Zero, 414 Vector3.Zero,
415 null, 415 null,
416 true); 416 true);
@@ -426,7 +426,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
426 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID)); 426 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID));
427 427
428 // Test for folder successfully making it into the receiver's inventory 428 // Test for folder successfully making it into the receiver's inventory
429 InventoryFolderBase receivedFolder 429 InventoryFolderBase receivedFolder
430 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "Trash/f1"); 430 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "Trash/f1");
431 431
432 InventoryFolderBase trashFolder 432 InventoryFolderBase trashFolder
@@ -443,6 +443,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
443 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1"); 443 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
444 444
445 Assert.That(originalFolderAfterDelete, Is.Not.Null); 445 Assert.That(originalFolderAfterDelete, Is.Not.Null);
446 } 446 }
447 } 447 }
448} \ No newline at end of file 448} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
index 24286a4..10781e9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
@@ -65,7 +65,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
65 { 65 {
66 m_Enabled = true; 66 m_Enabled = true;
67 67
68 m_ThisGridURL = Util.GetConfigVarFromSections<string>(config, "GatekeeperURI", 68 m_ThisGridURL = Util.GetConfigVarFromSections<string>(config, "GatekeeperURI",
69 new string[] { "Startup", "Hypergrid", "Messaging" }, String.Empty); 69 new string[] { "Startup", "Hypergrid", "Messaging" }, String.Empty);
70 // Legacy. Remove soon! 70 // Legacy. Remove soon!
71 m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", m_ThisGridURL); 71 m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", m_ThisGridURL);
@@ -154,7 +154,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
154 154
155 void OnIncomingInstantMessage(GridInstantMessage im) 155 void OnIncomingInstantMessage(GridInstantMessage im)
156 { 156 {
157 if (im.dialog == (byte)InstantMessageDialog.RequestTeleport 157 if (im.dialog == (byte)InstantMessageDialog.RequestTeleport
158 || im.dialog == (byte)InstantMessageDialog.GodLikeRequestTeleport) 158 || im.dialog == (byte)InstantMessageDialog.GodLikeRequestTeleport)
159 { 159 {
160 UUID sessionID = new UUID(im.imSessionID); 160 UUID sessionID = new UUID(im.imSessionID);
@@ -195,7 +195,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
195 195
196 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message); 196 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message);
197 m_PendingLures.Add(sessionID, m, 7200); // 2 hours 197 m_PendingLures.Add(sessionID, m, 7200); // 2 hours
198 198
199 if (m_TransferModule != null) 199 if (m_TransferModule != null)
200 { 200 {
201 m_TransferModule.SendInstantMessage(m, 201 m_TransferModule.SendInstantMessage(m,
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index 465ffbc..6f79676 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -163,16 +163,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
163 scene.RegionInfo.RegionHandle, 163 scene.RegionInfo.RegionHandle,
164 (uint)presence.AbsolutePosition.X, 164 (uint)presence.AbsolutePosition.X,
165 (uint)presence.AbsolutePosition.Y, 165 (uint)presence.AbsolutePosition.Y,
166 (uint)Math.Ceiling(presence.AbsolutePosition.Z)); 166 (uint)presence.AbsolutePosition.Z + 2);
167 167
168 m_log.DebugFormat("[LURE MODULE]: TP invite with message {0}, type {1}", message, lureType); 168 m_log.DebugFormat("[LURE MODULE]: TP invite with message {0}, type {1}", message, lureType);
169 169
170 GridInstantMessage m = new GridInstantMessage(scene, client.AgentId, 170 GridInstantMessage m;
171 client.FirstName+" "+client.LastName, targetid, 171
172 (byte)InstantMessageDialog.RequestTeleport, false, 172 if (scene.Permissions.IsAdministrator(client.AgentId) && presence.IsViewerUIGod && (!scene.Permissions.IsAdministrator(targetid)))
173 message, dest, false, presence.AbsolutePosition, 173 {
174 new Byte[0], true); 174 m = new GridInstantMessage(scene, client.AgentId,
175 175 client.FirstName+" "+client.LastName, targetid,
176 (byte)InstantMessageDialog.GodLikeRequestTeleport, false,
177 message, dest, false, presence.AbsolutePosition,
178 new Byte[0], true);
179 }
180 else
181 {
182 m = new GridInstantMessage(scene, client.AgentId,
183 client.FirstName+" "+client.LastName, targetid,
184 (byte)InstantMessageDialog.RequestTeleport, false,
185 message, dest, false, presence.AbsolutePosition,
186 new Byte[0], true);
187 }
188
176 if (m_TransferModule != null) 189 if (m_TransferModule != null)
177 { 190 {
178 m_TransferModule.SendInstantMessage(m, 191 m_TransferModule.SendInstantMessage(m,
@@ -207,7 +220,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
207 { 220 {
208 // Forward remote teleport requests 221 // Forward remote teleport requests
209 // 222 //
210 if (msg.dialog != 22) 223 if (msg.dialog != (byte)InstantMessageDialog.RequestTeleport &&
224 msg.dialog != (byte)InstantMessageDialog.GodLikeRequestTeleport)
211 return; 225 return;
212 226
213 if (m_TransferModule != null) 227 if (m_TransferModule != null)
diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
index 2bb24ae..1e1caca 100644
--- a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
@@ -68,7 +68,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile
68 { 68 {
69 if (!m_Enabled) 69 if (!m_Enabled)
70 return; 70 return;
71 71
72 lock (m_Scenes) 72 lock (m_Scenes)
73 { 73 {
74 if (!m_Scenes.Contains(scene)) 74 if (!m_Scenes.Contains(scene))
@@ -154,7 +154,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile
154 name = account.FirstName + " " + account.LastName; 154 name = account.FirstName + " " + account.LastName;
155 created = account.Created; 155 created = account.Created;
156 } 156 }
157 Byte[] charterMember = Utils.StringToBytes(name); 157 Byte[] membershipType = Utils.StringToBytes(name);
158 158
159 profileUrl = "No profile data"; 159 profileUrl = "No profile data";
160 aboutText = string.Empty; 160 aboutText = string.Empty;
@@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile
166 remoteClient.SendAvatarProperties(avatarID, aboutText, 166 remoteClient.SendAvatarProperties(avatarID, aboutText,
167 Util.ToDateTime(created).ToString( 167 Util.ToDateTime(created).ToString(
168 "M/d/yyyy", CultureInfo.InvariantCulture), 168 "M/d/yyyy", CultureInfo.InvariantCulture),
169 charterMember, firstLifeAboutText, 169 membershipType, firstLifeAboutText,
170 (uint)(0 & 0xff), 170 (uint)(0 & 0xff),
171 firstLifeImage, image, profileUrl, partner); 171 firstLifeImage, image, profileUrl, partner);
172 172
diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
index c20369c..e02ca49 100644
--- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -31,6 +31,7 @@ using System.Text;
31using System.Collections; 31using System.Collections;
32using System.Collections.Generic; 32using System.Collections.Generic;
33using System.Globalization; 33using System.Globalization;
34using System.Linq;
34using System.Net; 35using System.Net;
35using System.Net.Sockets; 36using System.Net.Sockets;
36using System.Reflection; 37using System.Reflection;
@@ -56,6 +57,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
56 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserProfilesModule")] 57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserProfilesModule")]
57 public class UserProfileModule : IProfileModule, INonSharedRegionModule 58 public class UserProfileModule : IProfileModule, INonSharedRegionModule
58 { 59 {
60 const double PROFILECACHEEXPIRE = 300;
59 /// <summary> 61 /// <summary>
60 /// Logging 62 /// Logging
61 /// </summary> 63 /// </summary>
@@ -66,8 +68,11 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
66 // count. The entries are removed when the interest count reaches 0. 68 // count. The entries are removed when the interest count reaches 0.
67 Dictionary<UUID, UUID> m_classifiedCache = new Dictionary<UUID, UUID>(); 69 Dictionary<UUID, UUID> m_classifiedCache = new Dictionary<UUID, UUID>();
68 Dictionary<UUID, int> m_classifiedInterest = new Dictionary<UUID, int>(); 70 Dictionary<UUID, int> m_classifiedInterest = new Dictionary<UUID, int>();
71 ExpiringCache<UUID, UserProfileCacheEntry> m_profilesCache = new ExpiringCache<UUID, UserProfileCacheEntry>();
72 IAssetCache m_assetCache;
69 73
70 private JsonRpcRequestManager rpc = new JsonRpcRequestManager(); 74 private JsonRpcRequestManager rpc = new JsonRpcRequestManager();
75 private bool m_allowUserProfileWebURLs = true;
71 76
72 public Scene Scene 77 public Scene Scene
73 { 78 {
@@ -80,7 +85,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
80 /// <value> 85 /// <value>
81 /// The configuration 86 /// The configuration
82 /// </value> 87 /// </value>
83 public IConfigSource Config 88 public IConfigSource Config
84 { 89 {
85 get; 90 get;
86 set; 91 set;
@@ -92,7 +97,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
92 /// <value> 97 /// <value>
93 /// The profile server URI. 98 /// The profile server URI.
94 /// </value> 99 /// </value>
95 public string ProfileServerUri 100 public string ProfileServerUri
96 { 101 {
97 get; 102 get;
98 set; 103 set;
@@ -115,23 +120,22 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
115 /// <value> 120 /// <value>
116 /// <c>true</c> if enabled; otherwise, <c>false</c>. 121 /// <c>true</c> if enabled; otherwise, <c>false</c>.
117 /// </value> 122 /// </value>
118 public bool Enabled 123 public bool Enabled
119 { 124 {
120 get; 125 get;
121 set; 126 set;
122 } 127 }
123 128
124 public string MyGatekeeper 129 public string MyGatekeeper
125 { 130 {
126 get; private set; 131 get; private set;
127 } 132 }
128 133
129
130 #region IRegionModuleBase implementation 134 #region IRegionModuleBase implementation
131 /// <summary> 135 /// <summary>
132 /// This is called to initialize the region module. For shared modules, this is called exactly once, after 136 /// This is called to initialize the region module. For shared modules, this is called exactly once, after
133 /// creating the single (shared) instance. For non-shared modules, this is called once on each instance, after 137 /// creating the single (shared) instance. For non-shared modules, this is called once on each instance, after
134 /// the instace for the region has been created. 138 /// the instace for the region has been created.
135 /// </summary> 139 /// </summary>
136 /// <param name='source'> 140 /// <param name='source'>
137 /// Source. 141 /// Source.
@@ -145,7 +149,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
145 149
146 if (profileConfig == null) 150 if (profileConfig == null)
147 { 151 {
148 m_log.Debug("[PROFILES]: UserProfiles disabled, no configuration"); 152 //m_log.Debug("[PROFILES]: UserProfiles disabled, no configuration");
149 Enabled = false; 153 Enabled = false;
150 return; 154 return;
151 } 155 }
@@ -158,7 +162,9 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
158 Enabled = false; 162 Enabled = false;
159 return; 163 return;
160 } 164 }
161 165
166 m_allowUserProfileWebURLs = profileConfig.GetBoolean("AllowUserProfileWebURLs", m_allowUserProfileWebURLs);
167
162 m_log.Debug("[PROFILES]: Full Profiles Enabled"); 168 m_log.Debug("[PROFILES]: Full Profiles Enabled");
163 ReplaceableInterface = null; 169 ReplaceableInterface = null;
164 Enabled = true; 170 Enabled = true;
@@ -181,22 +187,11 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
181 Scene = scene; 187 Scene = scene;
182 Scene.RegisterModuleInterface<IProfileModule>(this); 188 Scene.RegisterModuleInterface<IProfileModule>(this);
183 Scene.EventManager.OnNewClient += OnNewClient; 189 Scene.EventManager.OnNewClient += OnNewClient;
184 Scene.EventManager.OnMakeRootAgent += HandleOnMakeRootAgent; 190 Scene.EventManager.OnClientClosed += OnClientClosed;
185 191
186 UserManagementModule = Scene.RequestModuleInterface<IUserManagement>(); 192 UserManagementModule = Scene.RequestModuleInterface<IUserManagement>();
187 } 193 }
188 194
189 void HandleOnMakeRootAgent (ScenePresence obj)
190 {
191 if(obj.PresenceType == PresenceType.Npc)
192 return;
193
194 Util.FireAndForget(delegate
195 {
196 GetImageAssets(((IScenePresence)obj).UUID);
197 }, null, "UserProfileModule.GetImageAssets");
198 }
199
200 /// <summary> 195 /// <summary>
201 /// Removes the region. 196 /// Removes the region.
202 /// </summary> 197 /// </summary>
@@ -207,13 +202,17 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
207 { 202 {
208 if(!Enabled) 203 if(!Enabled)
209 return; 204 return;
205
206 m_profilesCache.Clear();
207 m_classifiedCache.Clear();
208 m_classifiedInterest.Clear();
210 } 209 }
211 210
212 /// <summary> 211 /// <summary>
213 /// This will be called once for every scene loaded. In a shared module this will be multiple times in one 212 /// This will be called once for every scene loaded. In a shared module this will be multiple times in one
214 /// instance, while a nonshared module instance will only be called once. This method is called after AddRegion 213 /// instance, while a nonshared module instance will only be called once. This method is called after AddRegion
215 /// has been called in all modules for that scene, providing an opportunity to request another module's 214 /// has been called in all modules for that scene, providing an opportunity to request another module's
216 /// interface, or hook an event from another module. 215 /// interface, or hook an event from another module.
217 /// </summary> 216 /// </summary>
218 /// <param name='scene'> 217 /// <param name='scene'>
219 /// Scene. 218 /// Scene.
@@ -222,6 +221,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
222 { 221 {
223 if(!Enabled) 222 if(!Enabled)
224 return; 223 return;
224 m_assetCache = Scene.RequestModuleInterface<IAssetCache>();
225 } 225 }
226 226
227 /// <summary> 227 /// <summary>
@@ -230,7 +230,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
230 /// module has registered the interface by then, this module will be activated, else it will remain inactive, 230 /// module has registered the interface by then, this module will be activated, else it will remain inactive,
231 /// letting the other module take over. This should return non-null ONLY in modules that are intended to be 231 /// letting the other module take over. This should return non-null ONLY in modules that are intended to be
232 /// easily replaceable, e.g. stub implementations that the developer expects to be replaced by third party 232 /// easily replaceable, e.g. stub implementations that the developer expects to be replaced by third party
233 /// provided modules. 233 /// provided modules.
234 /// </summary> 234 /// </summary>
235 /// <value> 235 /// <value>
236 /// The replaceable interface. 236 /// The replaceable interface.
@@ -248,7 +248,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
248 } 248 }
249 249
250 /// <value> 250 /// <value>
251 /// The name of the module 251 /// The name of the module
252 /// </value> 252 /// </value>
253 /// <summary> 253 /// <summary>
254 /// Gets the module name. 254 /// Gets the module name.
@@ -293,6 +293,40 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
293 client.OnUserInfoRequest += UserPreferencesRequest; 293 client.OnUserInfoRequest += UserPreferencesRequest;
294 client.OnUpdateUserInfo += UpdateUserPreferences; 294 client.OnUpdateUserInfo += UpdateUserPreferences;
295 } 295 }
296
297 void OnClientClosed(UUID AgentId, Scene scene)
298 {
299 ScenePresence sp = scene.GetScenePresence(AgentId);
300 IClientAPI client = sp.ControllingClient;
301 if (client == null)
302 return;
303
304 //Profile
305 client.OnRequestAvatarProperties -= RequestAvatarProperties;
306 client.OnUpdateAvatarProperties -= AvatarPropertiesUpdate;
307 client.OnAvatarInterestUpdate -= AvatarInterestsUpdate;
308
309 // Classifieds
310// client.r GenericPacketHandler("avatarclassifiedsrequest", ClassifiedsRequest);
311 client.OnClassifiedInfoUpdate -= ClassifiedInfoUpdate;
312 client.OnClassifiedInfoRequest -= ClassifiedInfoRequest;
313 client.OnClassifiedDelete -= ClassifiedDelete;
314
315 // Picks
316// client.AddGenericPacketHandler("avatarpicksrequest", PicksRequest);
317// client.AddGenericPacketHandler("pickinforequest", PickInfoRequest);
318 client.OnPickInfoUpdate -= PickInfoUpdate;
319 client.OnPickDelete -= PickDelete;
320
321 // Notes
322// client.AddGenericPacketHandler("avatarnotesrequest", NotesRequest);
323 client.OnAvatarNotesUpdate -= NotesUpdate;
324
325 // Preferences
326 client.OnUserInfoRequest -= UserPreferencesRequest;
327 client.OnUpdateUserInfo -= UpdateUserPreferences;
328 }
329
296 #endregion Region Event Handlers 330 #endregion Region Event Handlers
297 331
298 #region Classified 332 #region Classified
@@ -315,38 +349,74 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
315 return; 349 return;
316 350
317 IClientAPI remoteClient = (IClientAPI)sender; 351 IClientAPI remoteClient = (IClientAPI)sender;
352 Dictionary<UUID, string> classifieds = new Dictionary<UUID, string>();
318 353
319 UUID targetID; 354 UUID targetID;
320 UUID.TryParse(args[0], out targetID); 355 if(!UUID.TryParse(args[0], out targetID) || targetID == UUID.Zero)
356 return;
321 357
322 // Can't handle NPC yet...
323 ScenePresence p = FindPresence(targetID); 358 ScenePresence p = FindPresence(targetID);
359 if (p != null && p.IsNPC)
360 {
361 remoteClient.SendAvatarClassifiedReply(targetID, classifieds);
362 return;
363 }
324 364
325 if (null != p) 365 UserProfileCacheEntry uce = null;
366 lock(m_profilesCache)
326 { 367 {
327 if (p.PresenceType == PresenceType.Npc) 368 if(m_profilesCache.TryGetValue(targetID, out uce) && uce != null)
328 return; 369 {
370 if(uce.classifiedsLists != null)
371 {
372 foreach(KeyValuePair<UUID,string> kvp in uce.classifiedsLists)
373 {
374 UUID kvpkey = kvp.Key;
375 classifieds[kvpkey] = kvp.Value;
376 lock (m_classifiedCache)
377 {
378 if (!m_classifiedCache.ContainsKey(kvpkey))
379 {
380 m_classifiedCache.Add(kvpkey,targetID);
381 m_classifiedInterest.Add(kvpkey, 0);
382 }
383
384 m_classifiedInterest[kvpkey]++;
385 }
386 }
387 remoteClient.SendAvatarClassifiedReply(targetID, uce.classifiedsLists);
388 return;
389 }
390 }
329 } 391 }
330 392
331 string serverURI = string.Empty; 393 string serverURI = string.Empty;
332 GetUserProfileServerURI(targetID, out serverURI); 394 GetUserProfileServerURI(targetID, out serverURI);
333 UUID creatorId = UUID.Zero; 395 if(string.IsNullOrWhiteSpace(serverURI))
334 Dictionary<UUID, string> classifieds = new Dictionary<UUID, string>(); 396 {
397 remoteClient.SendAvatarClassifiedReply(targetID, classifieds);
398 return;
399 }
335 400
336 OSDMap parameters= new OSDMap(); 401 OSDMap parameters= new OSDMap();
337 UUID.TryParse(args[0], out creatorId); 402
338 parameters.Add("creatorId", OSD.FromUUID(creatorId)); 403 parameters.Add("creatorId", OSD.FromUUID(targetID));
339 OSD Params = (OSD)parameters; 404 OSD Params = (OSD)parameters;
340 if(!rpc.JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString())) 405 if(!rpc.JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString()))
341 { 406 {
342 remoteClient.SendAvatarClassifiedReply(new UUID(args[0]), classifieds); 407 remoteClient.SendAvatarClassifiedReply(targetID, classifieds);
343 return; 408 return;
344 } 409 }
345 410
346 parameters = (OSDMap)Params; 411 parameters = (OSDMap)Params;
347 412
348 OSDArray list = (OSDArray)parameters["result"]; 413 if(!parameters.ContainsKey("result") || parameters["result"] == null)
414 {
415 remoteClient.SendAvatarClassifiedReply(targetID, classifieds);
416 return;
417 }
349 418
419 OSDArray list = (OSDArray)parameters["result"];
350 420
351 foreach(OSD map in list) 421 foreach(OSD map in list)
352 { 422 {
@@ -360,7 +430,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
360 { 430 {
361 if (!m_classifiedCache.ContainsKey(cid)) 431 if (!m_classifiedCache.ContainsKey(cid))
362 { 432 {
363 m_classifiedCache.Add(cid,creatorId); 433 m_classifiedCache.Add(cid,targetID);
364 m_classifiedInterest.Add(cid, 0); 434 m_classifiedInterest.Add(cid, 0);
365 } 435 }
366 436
@@ -368,11 +438,20 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
368 } 438 }
369 } 439 }
370 440
371 remoteClient.SendAvatarClassifiedReply(new UUID(args[0]), classifieds); 441 lock(m_profilesCache)
442 {
443 if(!m_profilesCache.TryGetValue(targetID, out uce) || uce == null)
444 uce = new UserProfileCacheEntry();
445 uce.classifiedsLists = classifieds;
446
447 m_profilesCache.AddOrUpdate(targetID, uce, PROFILECACHEEXPIRE);
448 }
449
450 remoteClient.SendAvatarClassifiedReply(targetID, classifieds);
372 } 451 }
373 452
374 public void ClassifiedInfoRequest(UUID queryClassifiedID, IClientAPI remoteClient) 453 public void ClassifiedInfoRequest(UUID queryClassifiedID, IClientAPI remoteClient)
375 { 454 {
376 UUID target = remoteClient.AgentId; 455 UUID target = remoteClient.AgentId;
377 UserClassifiedAdd ad = new UserClassifiedAdd(); 456 UserClassifiedAdd ad = new UserClassifiedAdd();
378 ad.ClassifiedId = queryClassifiedID; 457 ad.ClassifiedId = queryClassifiedID;
@@ -380,7 +459,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
380 lock (m_classifiedCache) 459 lock (m_classifiedCache)
381 { 460 {
382 if (m_classifiedCache.ContainsKey(queryClassifiedID)) 461 if (m_classifiedCache.ContainsKey(queryClassifiedID))
383 { 462 {
384 target = m_classifiedCache[queryClassifiedID]; 463 target = m_classifiedCache[queryClassifiedID];
385 464
386 m_classifiedInterest[queryClassifiedID] --; 465 m_classifiedInterest[queryClassifiedID] --;
@@ -392,9 +471,33 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
392 } 471 }
393 } 472 }
394 } 473 }
395 474
475 UserProfileCacheEntry uce = null;
476 lock(m_profilesCache)
477 {
478 if(m_profilesCache.TryGetValue(target, out uce) && uce != null)
479 {
480 if(uce.classifieds != null && uce.classifieds.ContainsKey(queryClassifiedID))
481 {
482 ad = uce.classifieds[queryClassifiedID];
483 Vector3 gPos = new Vector3();
484 Vector3.TryParse(ad.GlobalPos, out gPos);
485
486 remoteClient.SendClassifiedInfoReply(ad.ClassifiedId, ad.CreatorId, (uint)ad.CreationDate,
487 (uint)ad.ExpirationDate, (uint)ad.Category, ad.Name, ad.Description,
488 ad.ParcelId, (uint)ad.ParentEstate, ad.SnapshotId, ad.SimName,
489 gPos, ad.ParcelName, ad.Flags, ad.Price);
490 return;
491 }
492 }
493 }
494
396 string serverURI = string.Empty; 495 string serverURI = string.Empty;
397 GetUserProfileServerURI(target, out serverURI); 496 bool foreign = GetUserProfileServerURI(target, out serverURI);
497 if(string.IsNullOrWhiteSpace(serverURI))
498 {
499 return;
500 }
398 501
399 object Ad = (object)ad; 502 object Ad = (object)ad;
400 if(!rpc.JsonRpcRequest(ref Ad, "classifieds_info_query", serverURI, UUID.Random().ToString())) 503 if(!rpc.JsonRpcRequest(ref Ad, "classifieds_info_query", serverURI, UUID.Random().ToString()))
@@ -408,6 +511,20 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
408 if(ad.CreatorId == UUID.Zero) 511 if(ad.CreatorId == UUID.Zero)
409 return; 512 return;
410 513
514 if(foreign)
515 cacheForeignImage(target, ad.SnapshotId);
516
517 lock(m_profilesCache)
518 {
519 if(!m_profilesCache.TryGetValue(target, out uce) || uce == null)
520 uce = new UserProfileCacheEntry();
521 if(uce.classifieds == null)
522 uce.classifieds = new Dictionary<UUID, UserClassifiedAdd>();
523 uce.classifieds[ad.ClassifiedId] = ad;
524
525 m_profilesCache.AddOrUpdate(target, uce, PROFILECACHEEXPIRE);
526 }
527
411 Vector3 globalPos = new Vector3(); 528 Vector3 globalPos = new Vector3();
412 Vector3.TryParse(ad.GlobalPos, out globalPos); 529 Vector3.TryParse(ad.GlobalPos, out globalPos);
413 530
@@ -458,36 +575,62 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
458 int queryclassifiedPrice, IClientAPI remoteClient) 575 int queryclassifiedPrice, IClientAPI remoteClient)
459 { 576 {
460 Scene s = (Scene)remoteClient.Scene; 577 Scene s = (Scene)remoteClient.Scene;
461 IMoneyModule money = s.RequestModuleInterface<IMoneyModule>(); 578 Vector3 pos = remoteClient.SceneAgent.AbsolutePosition;
579 ILandObject land = s.LandChannel.GetLandObject(pos.X, pos.Y);
580 UUID creatorId = remoteClient.AgentId;
581 ScenePresence p = FindPresence(creatorId);
462 582
463 if (money != null) 583 UserProfileCacheEntry uce = null;
584 lock(m_profilesCache)
585 m_profilesCache.TryGetValue(remoteClient.AgentId, out uce);
586
587 string serverURI = string.Empty;
588 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
589 if(string.IsNullOrWhiteSpace(serverURI))
464 { 590 {
465 if (!money.AmountCovered(remoteClient.AgentId, queryclassifiedPrice)) 591 return;
466 {
467 remoteClient.SendAgentAlertMessage("You do not have enough money to create requested classified.", false);
468 return;
469 }
470 money.ApplyCharge(remoteClient.AgentId, queryclassifiedPrice, MoneyTransactionType.ClassifiedCharge);
471 } 592 }
472 593
473 UserClassifiedAdd ad = new UserClassifiedAdd(); 594 if(foreign)
474 595 {
475 Vector3 pos = remoteClient.SceneAgent.AbsolutePosition; 596 remoteClient.SendAgentAlertMessage("Please change classifieds on your home grid", true);
476 ILandObject land = s.LandChannel.GetLandObject(pos.X, pos.Y); 597 if(uce != null && uce.classifiedsLists != null)
477 ScenePresence p = FindPresence(remoteClient.AgentId); 598 remoteClient.SendAvatarClassifiedReply(remoteClient.AgentId, uce.classifiedsLists);
478 599 return;
479 string serverURI = string.Empty; 600 }
480 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
481 601
482 if (land == null) 602 OSDMap parameters = new OSDMap {{"creatorId", OSD.FromUUID(creatorId)}};
603 OSD Params = (OSD)parameters;
604 if (!rpc.JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString()))
483 { 605 {
484 ad.ParcelName = string.Empty; 606 remoteClient.SendAgentAlertMessage("Error fetching classifieds", false);
607 return;
485 } 608 }
486 else 609 parameters = (OSDMap)Params;
610 OSDArray list = (OSDArray)parameters["result"];
611 bool exists = list.Cast<OSDMap>().Where(map => map.ContainsKey("classifieduuid"))
612 .Any(map => map["classifieduuid"].AsUUID().Equals(queryclassifiedID));
613
614 IMoneyModule money = null;
615 if (!exists)
487 { 616 {
488 ad.ParcelName = land.LandData.Name; 617 money = s.RequestModuleInterface<IMoneyModule>();
618 if (money != null)
619 {
620 if (!money.AmountCovered(remoteClient.AgentId, queryclassifiedPrice))
621 {
622 remoteClient.SendAgentAlertMessage("You do not have enough money to create this classified.", false);
623 if(uce != null && uce.classifiedsLists != null)
624 remoteClient.SendAvatarClassifiedReply(remoteClient.AgentId, uce.classifiedsLists);
625 return;
626 }
627// money.ApplyCharge(remoteClient.AgentId, queryclassifiedPrice, MoneyTransactionType.ClassifiedCharge);
628 }
489 } 629 }
490 630
631 UserClassifiedAdd ad = new UserClassifiedAdd();
632
633 ad.ParcelName = land == null ? string.Empty : land.LandData.Name;
491 ad.CreatorId = remoteClient.AgentId; 634 ad.CreatorId = remoteClient.AgentId;
492 ad.ClassifiedId = queryclassifiedID; 635 ad.ClassifiedId = queryclassifiedID;
493 ad.Category = Convert.ToInt32(queryCategory); 636 ad.Category = Convert.ToInt32(queryCategory);
@@ -507,10 +650,26 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
507 650
508 if(!rpc.JsonRpcRequest(ref Ad, "classified_update", serverURI, UUID.Random().ToString())) 651 if(!rpc.JsonRpcRequest(ref Ad, "classified_update", serverURI, UUID.Random().ToString()))
509 { 652 {
510 remoteClient.SendAgentAlertMessage( 653 remoteClient.SendAgentAlertMessage("Error updating classified", false);
511 "Error updating classified", false); 654 if(uce != null && uce.classifiedsLists != null)
655 remoteClient.SendAvatarClassifiedReply(remoteClient.AgentId, uce.classifiedsLists);
512 return; 656 return;
513 } 657 }
658
659 // only charge if it worked
660 if (money != null)
661 money.ApplyCharge(remoteClient.AgentId, queryclassifiedPrice, MoneyTransactionType.ClassifiedCharge);
662
663 // just flush cache for now
664 lock(m_profilesCache)
665 {
666 if(m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) && uce != null)
667 {
668 uce.classifieds = null;
669 uce.classifiedsLists = null;
670 }
671 }
672
514 } 673 }
515 674
516 /// <summary> 675 /// <summary>
@@ -524,12 +683,23 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
524 /// </param> 683 /// </param>
525 public void ClassifiedDelete(UUID queryClassifiedID, IClientAPI remoteClient) 684 public void ClassifiedDelete(UUID queryClassifiedID, IClientAPI remoteClient)
526 { 685 {
686
527 string serverURI = string.Empty; 687 string serverURI = string.Empty;
528 GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 688 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
689 if(string.IsNullOrWhiteSpace(serverURI))
690 return;
691
692 if(foreign)
693 {
694 remoteClient.SendAgentAlertMessage("Please change classifieds on your home grid", true);
695 return;
696 }
529 697
530 UUID classifiedId; 698 UUID classifiedId;
699 if(!UUID.TryParse(queryClassifiedID.ToString(), out classifiedId))
700 return;
701
531 OSDMap parameters= new OSDMap(); 702 OSDMap parameters= new OSDMap();
532 UUID.TryParse(queryClassifiedID.ToString(), out classifiedId);
533 parameters.Add("classifiedId", OSD.FromUUID(classifiedId)); 703 parameters.Add("classifiedId", OSD.FromUUID(classifiedId));
534 OSD Params = (OSD)parameters; 704 OSD Params = (OSD)parameters;
535 if(!rpc.JsonRpcRequest(ref Params, "classified_delete", serverURI, UUID.Random().ToString())) 705 if(!rpc.JsonRpcRequest(ref Params, "classified_delete", serverURI, UUID.Random().ToString()))
@@ -539,6 +709,17 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
539 return; 709 return;
540 } 710 }
541 711
712 // flush cache
713 UserProfileCacheEntry uce = null;
714 lock(m_profilesCache)
715 {
716 if(m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) && uce != null)
717 {
718 uce.classifieds = null;
719 uce.classifiedsLists = null;
720 }
721 }
722
542 parameters = (OSDMap)Params; 723 parameters = (OSDMap)Params;
543 } 724 }
544 #endregion Classified 725 #endregion Classified
@@ -564,33 +745,54 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
564 IClientAPI remoteClient = (IClientAPI)sender; 745 IClientAPI remoteClient = (IClientAPI)sender;
565 746
566 UUID targetId; 747 UUID targetId;
567 UUID.TryParse(args[0], out targetId); 748 if(!UUID.TryParse(args[0], out targetId))
749 return;
750
751 Dictionary<UUID, string> picks = new Dictionary<UUID, string>();
568 752
569 // Can't handle NPC yet...
570 ScenePresence p = FindPresence(targetId); 753 ScenePresence p = FindPresence(targetId);
754 if (p != null && p.IsNPC)
755 {
756 remoteClient.SendAvatarPicksReply(targetId, picks);
757 return;
758 }
571 759
572 if (null != p) 760 UserProfileCacheEntry uce = null;
761 lock(m_profilesCache)
573 { 762 {
574 if (p.PresenceType == PresenceType.Npc) 763 if(m_profilesCache.TryGetValue(targetId, out uce) && uce != null)
575 return; 764 {
765 if(uce != null && uce.picksList != null)
766 {
767 remoteClient.SendAvatarPicksReply(targetId, uce.picksList);
768 return;
769 }
770 }
576 } 771 }
577 772
578 string serverURI = string.Empty; 773 string serverURI = string.Empty;
579 GetUserProfileServerURI(targetId, out serverURI); 774 GetUserProfileServerURI(targetId, out serverURI);
580 775 if(string.IsNullOrWhiteSpace(serverURI))
581 Dictionary<UUID, string> picks = new Dictionary<UUID, string>(); 776 {
777 remoteClient.SendAvatarPicksReply(targetId, picks);
778 return;
779 }
582 780
583 OSDMap parameters= new OSDMap(); 781 OSDMap parameters= new OSDMap();
584 parameters.Add("creatorId", OSD.FromUUID(targetId)); 782 parameters.Add("creatorId", OSD.FromUUID(targetId));
585 OSD Params = (OSD)parameters; 783 OSD Params = (OSD)parameters;
586 if(!rpc.JsonRpcRequest(ref Params, "avatarpicksrequest", serverURI, UUID.Random().ToString())) 784 if(!rpc.JsonRpcRequest(ref Params, "avatarpicksrequest", serverURI, UUID.Random().ToString()))
587 { 785 {
588 remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks); 786 remoteClient.SendAvatarPicksReply(targetId, picks);
589 return; 787 return;
590 } 788 }
591 789
592 parameters = (OSDMap)Params; 790 parameters = (OSDMap)Params;
593 791 if(!parameters.ContainsKey("result") || parameters["result"] == null)
792 {
793 remoteClient.SendAvatarPicksReply(targetId, picks);
794 return;
795 }
594 OSDArray list = (OSDArray)parameters["result"]; 796 OSDArray list = (OSDArray)parameters["result"];
595 797
596 foreach(OSD map in list) 798 foreach(OSD map in list)
@@ -598,12 +800,19 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
598 OSDMap m = (OSDMap)map; 800 OSDMap m = (OSDMap)map;
599 UUID cid = m["pickuuid"].AsUUID(); 801 UUID cid = m["pickuuid"].AsUUID();
600 string name = m["name"].AsString(); 802 string name = m["name"].AsString();
601
602 m_log.DebugFormat("[PROFILES]: PicksRequest {0}", name);
603
604 picks[cid] = name; 803 picks[cid] = name;
605 } 804 }
606 remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks); 805
806 lock(m_profilesCache)
807 {
808 if(!m_profilesCache.TryGetValue(targetId, out uce) || uce == null)
809 uce = new UserProfileCacheEntry();
810 uce.picksList = picks;
811
812 m_profilesCache.AddOrUpdate(targetId, uce, PROFILECACHEEXPIRE);
813 }
814
815 remoteClient.SendAvatarPicksReply(targetId, picks);
607 } 816 }
608 817
609 /// <summary> 818 /// <summary>
@@ -623,21 +832,45 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
623 if (!(sender is IClientAPI)) 832 if (!(sender is IClientAPI))
624 return; 833 return;
625 834
835 UserProfilePick pick = new UserProfilePick ();
626 UUID targetID; 836 UUID targetID;
627 UUID.TryParse (args [0], out targetID); 837 if(!UUID.TryParse(args [0], out targetID))
628 string serverURI = string.Empty; 838 return;
629 GetUserProfileServerURI (targetID, out serverURI);
630 839
631 string theirGatekeeperURI; 840 pick.CreatorId = targetID;
632 GetUserGatekeeperURI (targetID, out theirGatekeeperURI); 841
842 if(!UUID.TryParse (args [1], out pick.PickId))
843 return;
633 844
634 IClientAPI remoteClient = (IClientAPI)sender; 845 IClientAPI remoteClient = (IClientAPI)sender;
846 UserProfileCacheEntry uce = null;
847 lock(m_profilesCache)
848 {
849 if(m_profilesCache.TryGetValue(targetID, out uce) && uce != null)
850 {
851 if(uce != null && uce.picks != null && uce.picks.ContainsKey(pick.PickId))
852 {
853 pick = uce.picks[pick.PickId];
854 Vector3 gPos = new Vector3(Vector3.Zero);
855 Vector3.TryParse(pick.GlobalPos, out gPos);
856 remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name,
857 pick.Desc,pick.SnapshotId,pick.ParcelName,pick.OriginalName,pick.SimName,
858 gPos,pick.SortOrder,pick.Enabled);
859 return;
860 }
861 }
862 }
635 863
636 UserProfilePick pick = new UserProfilePick (); 864 string serverURI = string.Empty;
637 UUID.TryParse (args [0], out pick.CreatorId); 865 bool foreign = GetUserProfileServerURI (targetID, out serverURI);
638 UUID.TryParse (args [1], out pick.PickId); 866 if(string.IsNullOrWhiteSpace(serverURI))
867 {
868 return;
869 }
870
871 string theirGatekeeperURI;
872 GetUserGatekeeperURI(targetID, out theirGatekeeperURI);
639 873
640
641 object Pick = (object)pick; 874 object Pick = (object)pick;
642 if (!rpc.JsonRpcRequest (ref Pick, "pickinforequest", serverURI, UUID.Random ().ToString ())) { 875 if (!rpc.JsonRpcRequest (ref Pick, "pickinforequest", serverURI, UUID.Random ().ToString ())) {
643 remoteClient.SendAgentAlertMessage ( 876 remoteClient.SendAgentAlertMessage (
@@ -645,15 +878,13 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
645 return; 878 return;
646 } 879 }
647 pick = (UserProfilePick)Pick; 880 pick = (UserProfilePick)Pick;
648 881 if(foreign)
882 cacheForeignImage(targetID, pick.SnapshotId);
883
649 Vector3 globalPos = new Vector3(Vector3.Zero); 884 Vector3 globalPos = new Vector3(Vector3.Zero);
650 885 Vector3.TryParse(pick.GlobalPos, out globalPos);
651 // Smoke and mirrors 886
652 if (pick.Gatekeeper == MyGatekeeper) 887 if (!string.IsNullOrWhiteSpace(MyGatekeeper) && pick.Gatekeeper != MyGatekeeper)
653 {
654 Vector3.TryParse(pick.GlobalPos,out globalPos);
655 }
656 else
657 { 888 {
658 // Setup the illusion 889 // Setup the illusion
659 string region = string.Format("{0} {1}",pick.Gatekeeper,pick.SimName); 890 string region = string.Format("{0} {1}",pick.Gatekeeper,pick.SimName);
@@ -661,26 +892,52 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
661 892
662 if(target == null) 893 if(target == null)
663 { 894 {
664 // This is a dead or unreachable region 895 // This is a unreachable region
665 } 896 }
666 else 897 else
667 { 898 {
668 // Work our slight of hand 899 // we have a proxy on map
669 int x = target.RegionLocX; 900 ulong oriHandle;
670 int y = target.RegionLocY; 901 uint oriX;
902 uint oriY;
903 if(Util.ParseFakeParcelID(pick.ParcelId, out oriHandle, out oriX, out oriY))
904 {
905 pick.ParcelId = Util.BuildFakeParcelID(target.RegionHandle, oriX, oriY);
906 globalPos.X = target.RegionLocX + oriX;
907 globalPos.Y = target.RegionLocY + oriY;
908 pick.GlobalPos = globalPos.ToString();
909 }
910 else
911 {
912 // this is a fail on large regions
913 uint gtmp = (uint)globalPos.X >> 8;
914 globalPos.X -= (gtmp << 8);
915
916 gtmp = (uint)globalPos.Y >> 8;
917 globalPos.Y -= (gtmp << 8);
671 918
672 dynamic synthX = globalPos.X - (globalPos.X/Constants.RegionSize) * Constants.RegionSize; 919 pick.ParcelId = Util.BuildFakeParcelID(target.RegionHandle, (uint)globalPos.X, (uint)globalPos.Y);
673 synthX += x;
674 globalPos.X = synthX;
675 920
676 dynamic synthY = globalPos.Y - (globalPos.Y/Constants.RegionSize) * Constants.RegionSize; 921 globalPos.X += target.RegionLocX;
677 synthY += y; 922 globalPos.Y += target.RegionLocY;
678 globalPos.Y = synthY; 923 pick.GlobalPos = globalPos.ToString();
924 }
679 } 925 }
680 } 926 }
681 927
682 m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString()); 928 m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString());
683 929
930 lock(m_profilesCache)
931 {
932 if(!m_profilesCache.TryGetValue(targetID, out uce) || uce == null)
933 uce = new UserProfileCacheEntry();
934 if(uce.picks == null)
935 uce.picks = new Dictionary<UUID, UserProfilePick>();
936 uce.picks[pick.PickId] = pick;
937
938 m_profilesCache.AddOrUpdate(targetID, uce, PROFILECACHEEXPIRE);
939 }
940
684 // Pull the rabbit out of the hat 941 // Pull the rabbit out of the hat
685 remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name, 942 remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name,
686 pick.Desc,pick.SnapshotId,pick.ParcelName,pick.OriginalName,pick.SimName, 943 pick.Desc,pick.SnapshotId,pick.ParcelName,pick.OriginalName,pick.SimName,
@@ -718,13 +975,17 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
718 /// Enabled. 975 /// Enabled.
719 /// </param> 976 /// </param>
720 public void PickInfoUpdate(IClientAPI remoteClient, UUID pickID, UUID creatorID, bool topPick, string name, string desc, UUID snapshotID, int sortOrder, bool enabled) 977 public void PickInfoUpdate(IClientAPI remoteClient, UUID pickID, UUID creatorID, bool topPick, string name, string desc, UUID snapshotID, int sortOrder, bool enabled)
721 { 978 {
722 //TODO: See how this works with NPC, May need to test
723 m_log.DebugFormat("[PROFILES]: Start PickInfoUpdate Name: {0} PickId: {1} SnapshotId: {2}", name, pickID.ToString(), snapshotID.ToString()); 979 m_log.DebugFormat("[PROFILES]: Start PickInfoUpdate Name: {0} PickId: {1} SnapshotId: {2}", name, pickID.ToString(), snapshotID.ToString());
724 980
725 UserProfilePick pick = new UserProfilePick(); 981 UserProfilePick pick = new UserProfilePick();
726 string serverURI = string.Empty; 982 string serverURI = string.Empty;
727 GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 983 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
984 if(string.IsNullOrWhiteSpace(serverURI))
985 {
986 return;
987 }
988
728 ScenePresence p = FindPresence(remoteClient.AgentId); 989 ScenePresence p = FindPresence(remoteClient.AgentId);
729 990
730 Vector3 avaPos = p.AbsolutePosition; 991 Vector3 avaPos = p.AbsolutePosition;
@@ -734,24 +995,27 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
734 avaPos.Z); 995 avaPos.Z);
735 996
736 string landParcelName = "My Parcel"; 997 string landParcelName = "My Parcel";
737 UUID landParcelID = p.currentParcelUUID; 998// UUID landParcelID = p.currentParcelUUID;
738 999
1000 // to locate parcels we use a fake id that encodes the region handle
1001 // since we do not have a global locator
1002 // this fails on HG
1003 UUID landParcelID = Util.BuildFakeParcelID(remoteClient.Scene.RegionInfo.RegionHandle, (uint)avaPos.X, (uint)avaPos.Y);
739 ILandObject land = p.Scene.LandChannel.GetLandObject(avaPos.X, avaPos.Y); 1004 ILandObject land = p.Scene.LandChannel.GetLandObject(avaPos.X, avaPos.Y);
740 1005
741 if (land != null) 1006 if (land != null)
742 { 1007 {
743 // If land found, use parcel uuid from here because the value from SP will be blank if the avatar hasnt moved 1008 // If land found, use parcel uuid from here because the value from SP will be blank if the avatar hasnt moved
744 landParcelName = land.LandData.Name; 1009 landParcelName = land.LandData.Name;
745 landParcelID = land.LandData.GlobalID; 1010// landParcelID = land.LandData.GlobalID;
746 } 1011 }
747 else 1012 else
748 { 1013 {
749 m_log.WarnFormat( 1014 m_log.WarnFormat(
750 "[PROFILES]: PickInfoUpdate found no parcel info at {0},{1} in {2}", 1015 "[PROFILES]: PickInfoUpdate found no parcel info at {0},{1} in {2}",
751 avaPos.X, avaPos.Y, p.Scene.Name); 1016 avaPos.X, avaPos.Y, p.Scene.Name);
752 } 1017 }
753 1018
754
755 pick.PickId = pickID; 1019 pick.PickId = pickID;
756 pick.CreatorId = creatorID; 1020 pick.CreatorId = creatorID;
757 pick.TopPick = topPick; 1021 pick.TopPick = topPick;
@@ -774,6 +1038,24 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
774 return; 1038 return;
775 } 1039 }
776 1040
1041 UserProfileCacheEntry uce = null;
1042 lock(m_profilesCache)
1043 {
1044 if(!m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) || uce == null)
1045 uce = new UserProfileCacheEntry();
1046 if(uce.picks == null)
1047 uce.picks = new Dictionary<UUID, UserProfilePick>();
1048 if(uce.picksList == null)
1049 uce.picksList = new Dictionary<UUID, string>();
1050 uce.picks[pick.PickId] = pick;
1051 uce.picksList[pick.PickId] = pick.Name;
1052 m_profilesCache.AddOrUpdate(remoteClient.AgentId, uce, PROFILECACHEEXPIRE);
1053 }
1054 remoteClient.SendAvatarPicksReply(remoteClient.AgentId, uce.picksList);
1055 remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name,
1056 pick.Desc,pick.SnapshotId,pick.ParcelName,pick.OriginalName,pick.SimName,
1057 posGlobal,pick.SortOrder,pick.Enabled);
1058
777 m_log.DebugFormat("[PROFILES]: Finish PickInfoUpdate {0} {1}", pick.Name, pick.PickId.ToString()); 1059 m_log.DebugFormat("[PROFILES]: Finish PickInfoUpdate {0} {1}", pick.Name, pick.PickId.ToString());
778 } 1060 }
779 1061
@@ -790,6 +1072,10 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
790 { 1072 {
791 string serverURI = string.Empty; 1073 string serverURI = string.Empty;
792 GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 1074 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
1075 if(string.IsNullOrWhiteSpace(serverURI))
1076 {
1077 return;
1078 }
793 1079
794 OSDMap parameters= new OSDMap(); 1080 OSDMap parameters= new OSDMap();
795 parameters.Add("pickId", OSD.FromUUID(queryPickID)); 1081 parameters.Add("pickId", OSD.FromUUID(queryPickID));
@@ -800,6 +1086,23 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
800 "Error picks delete", false); 1086 "Error picks delete", false);
801 return; 1087 return;
802 } 1088 }
1089
1090 UserProfileCacheEntry uce = null;
1091 lock(m_profilesCache)
1092 {
1093 if(m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) && uce != null)
1094 {
1095 if(uce.picks != null && uce.picks.ContainsKey(queryPickID))
1096 uce.picks.Remove(queryPickID);
1097 if(uce.picksList != null && uce.picksList.ContainsKey(queryPickID))
1098 uce.picksList.Remove(queryPickID);
1099 m_profilesCache.AddOrUpdate(remoteClient.AgentId, uce, PROFILECACHEEXPIRE);
1100 }
1101 }
1102 if(uce != null && uce.picksList != null)
1103 remoteClient.SendAvatarPicksReply(remoteClient.AgentId, uce.picksList);
1104 else
1105 remoteClient.SendAvatarPicksReply(remoteClient.AgentId, new Dictionary<UUID, string>());
803 } 1106 }
804 #endregion Picks 1107 #endregion Picks
805 1108
@@ -823,11 +1126,19 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
823 if (!(sender is IClientAPI)) 1126 if (!(sender is IClientAPI))
824 return; 1127 return;
825 1128
1129 if(!UUID.TryParse(args[0], out note.TargetId))
1130 return;
1131
826 IClientAPI remoteClient = (IClientAPI)sender; 1132 IClientAPI remoteClient = (IClientAPI)sender;
1133 note.UserId = remoteClient.AgentId;
1134
827 string serverURI = string.Empty; 1135 string serverURI = string.Empty;
828 GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 1136 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
829 note.UserId = remoteClient.AgentId; 1137 if(string.IsNullOrWhiteSpace(serverURI))
830 UUID.TryParse(args[0], out note.TargetId); 1138 {
1139 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
1140 return;
1141 }
831 1142
832 object Note = (object)note; 1143 object Note = (object)note;
833 if(!rpc.JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString())) 1144 if(!rpc.JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString()))
@@ -836,7 +1147,6 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
836 return; 1147 return;
837 } 1148 }
838 note = (UserProfileNotes) Note; 1149 note = (UserProfileNotes) Note;
839
840 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes); 1150 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
841 } 1151 }
842 1152
@@ -854,6 +1164,14 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
854 /// </param> 1164 /// </param>
855 public void NotesUpdate(IClientAPI remoteClient, UUID queryTargetID, string queryNotes) 1165 public void NotesUpdate(IClientAPI remoteClient, UUID queryTargetID, string queryNotes)
856 { 1166 {
1167 ScenePresence p = FindPresence(queryTargetID);
1168 if (p != null && p.IsNPC)
1169 {
1170 remoteClient.SendAgentAlertMessage(
1171 "Notes for NPCs not available", false);
1172 return;
1173 }
1174
857 UserProfileNotes note = new UserProfileNotes(); 1175 UserProfileNotes note = new UserProfileNotes();
858 1176
859 note.UserId = remoteClient.AgentId; 1177 note.UserId = remoteClient.AgentId;
@@ -862,6 +1180,8 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
862 1180
863 string serverURI = string.Empty; 1181 string serverURI = string.Empty;
864 GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 1182 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
1183 if(string.IsNullOrWhiteSpace(serverURI))
1184 return;
865 1185
866 object Note = note; 1186 object Note = note;
867 if(!rpc.JsonRpcRequest(ref Note, "avatar_notes_update", serverURI, UUID.Random().ToString())) 1187 if(!rpc.JsonRpcRequest(ref Note, "avatar_notes_update", serverURI, UUID.Random().ToString()))
@@ -873,6 +1193,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
873 } 1193 }
874 #endregion Notes 1194 #endregion Notes
875 1195
1196
876 #region User Preferences 1197 #region User Preferences
877 /// <summary> 1198 /// <summary>
878 /// Updates the user preferences. 1199 /// Updates the user preferences.
@@ -896,16 +1217,18 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
896 1217
897 string serverURI = string.Empty; 1218 string serverURI = string.Empty;
898 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 1219 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
1220 if(string.IsNullOrWhiteSpace(serverURI))
1221 return;
899 1222
900 object Pref = pref; 1223 object Pref = pref;
901 if(!rpc.JsonRpcRequest(ref Pref, "user_preferences_update", serverURI, UUID.Random().ToString())) 1224 if(!rpc.JsonRpcRequest(ref Pref, "user_preferences_update", serverURI, UUID.Random().ToString()))
902 { 1225 {
903 m_log.InfoFormat("[PROFILES]: UserPreferences update error"); 1226 m_log.InfoFormat("[PROFILES]: UserPreferences update error");
904 remoteClient.SendAgentAlertMessage("Error updating preferences", false); 1227 remoteClient.SendAgentAlertMessage("Error updating preferences", false);
905 return; 1228 return;
906 } 1229 }
907 } 1230 }
908 1231
909 /// <summary> 1232 /// <summary>
910 /// Users the preferences request. 1233 /// Users the preferences request.
911 /// </summary> 1234 /// </summary>
@@ -920,7 +1243,8 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
920 1243
921 string serverURI = string.Empty; 1244 string serverURI = string.Empty;
922 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 1245 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
923 1246 if(string.IsNullOrWhiteSpace(serverURI))
1247 return;
924 1248
925 object Pref = (object)pref; 1249 object Pref = (object)pref;
926 if(!rpc.JsonRpcRequest(ref Pref, "user_preferences_request", serverURI, UUID.Random().ToString())) 1250 if(!rpc.JsonRpcRequest(ref Pref, "user_preferences_request", serverURI, UUID.Random().ToString()))
@@ -932,7 +1256,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
932 pref = (UserPreferences) Pref; 1256 pref = (UserPreferences) Pref;
933 1257
934 remoteClient.SendUserInfoReply(pref.IMViaEmail, pref.Visible, pref.EMail); 1258 remoteClient.SendUserInfoReply(pref.IMViaEmail, pref.Visible, pref.EMail);
935 1259
936 } 1260 }
937 #endregion User Preferences 1261 #endregion User Preferences
938 1262
@@ -960,6 +1284,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
960 /// </param> 1284 /// </param>
961 public void AvatarInterestsUpdate(IClientAPI remoteClient, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages) 1285 public void AvatarInterestsUpdate(IClientAPI remoteClient, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages)
962 { 1286 {
1287
963 UserProfileProperties prop = new UserProfileProperties(); 1288 UserProfileProperties prop = new UserProfileProperties();
964 1289
965 prop.UserId = remoteClient.AgentId; 1290 prop.UserId = remoteClient.AgentId;
@@ -971,6 +1296,8 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
971 1296
972 string serverURI = string.Empty; 1297 string serverURI = string.Empty;
973 GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 1298 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
1299 if(string.IsNullOrWhiteSpace(serverURI))
1300 return;
974 1301
975 object Param = prop; 1302 object Param = prop;
976 if(!rpc.JsonRpcRequest(ref Param, "avatar_interests_update", serverURI, UUID.Random().ToString())) 1303 if(!rpc.JsonRpcRequest(ref Param, "avatar_interests_update", serverURI, UUID.Random().ToString()))
@@ -979,6 +1306,17 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
979 "Error updating interests", false); 1306 "Error updating interests", false);
980 return; 1307 return;
981 } 1308 }
1309
1310 // flush cache
1311 UserProfileCacheEntry uce = null;
1312 lock(m_profilesCache)
1313 {
1314 if(m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) && uce != null)
1315 {
1316 uce.props = null;
1317 }
1318 }
1319
982 } 1320 }
983 1321
984 public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID) 1322 public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
@@ -990,13 +1328,55 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
990 return; 1328 return;
991 } 1329 }
992 1330
993 // Can't handle NPC yet...
994 ScenePresence p = FindPresence(avatarID); 1331 ScenePresence p = FindPresence(avatarID);
995 1332 if (p != null && p.IsNPC)
996 if (null != p)
997 { 1333 {
998 if (p.PresenceType == PresenceType.Npc) 1334 remoteClient.SendAvatarProperties(avatarID, ((INPC)(p.ControllingClient)).profileAbout, ((INPC)(p.ControllingClient)).Born,
999 return; 1335 Utils.StringToBytes("Non Player Character (NPC)"), "NPCs have no life", 0x10,
1336 UUID.Zero, ((INPC)(p.ControllingClient)).profileImage, "", UUID.Zero);
1337 remoteClient.SendAvatarInterestsReply(avatarID, 0, "",
1338 0, "Getting into trouble", "Droidspeak");
1339 return;
1340 }
1341 UserProfileProperties props;
1342 UserProfileCacheEntry uce = null;
1343 lock(m_profilesCache)
1344 {
1345 if(m_profilesCache.TryGetValue(avatarID, out uce) && uce != null)
1346 {
1347 if(uce.props != null)
1348 {
1349 props = uce.props;
1350 uint cflags = uce.flags;
1351 // if on same region force online
1352 if(p != null && !p.IsDeleted)
1353 cflags |= 0x10;
1354
1355 remoteClient.SendAvatarProperties(props.UserId, props.AboutText,
1356 uce.born, uce.membershipType , props.FirstLifeText, cflags,
1357 props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
1358
1359 remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask,
1360 props.WantToText, (uint)props.SkillsMask,
1361 props.SkillsText, props.Language);
1362 return;
1363 }
1364 else
1365 {
1366 if(uce.ClientsWaitingProps == null)
1367 uce.ClientsWaitingProps = new HashSet<IClientAPI>();
1368 else if(uce.ClientsWaitingProps.Contains(remoteClient))
1369 return;
1370 uce.ClientsWaitingProps.Add(remoteClient);
1371 }
1372 }
1373 else
1374 {
1375 uce = new UserProfileCacheEntry();
1376 uce.ClientsWaitingProps = new HashSet<IClientAPI>();
1377 uce.ClientsWaitingProps.Add(remoteClient);
1378 m_profilesCache.AddOrUpdate(avatarID, uce, PROFILECACHEEXPIRE);
1379 }
1000 } 1380 }
1001 1381
1002 string serverURI = string.Empty; 1382 string serverURI = string.Empty;
@@ -1014,20 +1394,16 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1014 userInfo = new Dictionary<string, object>(); 1394 userInfo = new Dictionary<string, object>();
1015 } 1395 }
1016 1396
1017 Byte[] charterMember = new Byte[1]; 1397 Byte[] membershipType = new Byte[1];
1018 string born = String.Empty; 1398 string born = string.Empty;
1019 uint flags = 0x00; 1399 uint flags = 0x00;
1020 1400
1021 if (null != account) 1401 if (null != account)
1022 { 1402 {
1023 if (account.UserTitle == "") 1403 if (account.UserTitle == "")
1024 { 1404 membershipType[0] = (Byte)((account.UserFlags & 0xf00) >> 8);
1025 charterMember[0] = (Byte)((account.UserFlags & 0xf00) >> 8);
1026 }
1027 else 1405 else
1028 { 1406 membershipType = Utils.StringToBytes(account.UserTitle);
1029 charterMember = Utils.StringToBytes(account.UserTitle);
1030 }
1031 1407
1032 born = Util.ToDateTime(account.Created).ToString( 1408 born = Util.ToDateTime(account.Created).ToString(
1033 "M/d/yyyy", CultureInfo.InvariantCulture); 1409 "M/d/yyyy", CultureInfo.InvariantCulture);
@@ -1038,16 +1414,13 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1038 if (GetUserAccountData(avatarID, out userInfo) == true) 1414 if (GetUserAccountData(avatarID, out userInfo) == true)
1039 { 1415 {
1040 if ((string)userInfo["user_title"] == "") 1416 if ((string)userInfo["user_title"] == "")
1041 { 1417 membershipType[0] = (Byte)(((Byte)userInfo["user_flags"] & 0xf00) >> 8);
1042 charterMember[0] = (Byte)(((Byte)userInfo["user_flags"] & 0xf00) >> 8);
1043 }
1044 else 1418 else
1045 { 1419 membershipType = Utils.StringToBytes((string)userInfo["user_title"]);
1046 charterMember = Utils.StringToBytes((string)userInfo["user_title"]);
1047 }
1048 1420
1049 int val_born = (int)userInfo["user_created"]; 1421 int val_born = (int)userInfo["user_created"];
1050 born = Util.ToDateTime(val_born).ToString( 1422 if(val_born != 0)
1423 born = Util.ToDateTime(val_born).ToString(
1051 "M/d/yyyy", CultureInfo.InvariantCulture); 1424 "M/d/yyyy", CultureInfo.InvariantCulture);
1052 1425
1053 // picky, picky 1426 // picky, picky
@@ -1056,23 +1429,60 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1056 } 1429 }
1057 } 1430 }
1058 1431
1059 UserProfileProperties props = new UserProfileProperties(); 1432 props = new UserProfileProperties();
1433 props.UserId = avatarID;
1434
1060 string result = string.Empty; 1435 string result = string.Empty;
1436 if(!GetProfileData(ref props, foreign, serverURI, out result))
1437 {
1438 props.AboutText ="Profile not available at this time. User may still be unknown to this grid";
1439 }
1061 1440
1062 props.UserId = avatarID; 1441 if(!m_allowUserProfileWebURLs)
1442 props.WebUrl ="";
1063 1443
1064 if (!GetProfileData(ref props, foreign, out result)) 1444 HashSet<IClientAPI> clients;
1445 lock(m_profilesCache)
1065 { 1446 {
1066// m_log.DebugFormat("Error getting profile for {0}: {1}", avatarID, result); 1447 if(!m_profilesCache.TryGetValue(props.UserId, out uce) || uce == null)
1067 return; 1448 uce = new UserProfileCacheEntry();
1449 uce.props = props;
1450 uce.born = born;
1451 uce.membershipType = membershipType;
1452 uce.flags = flags;
1453 clients = uce.ClientsWaitingProps;
1454 uce.ClientsWaitingProps = null;
1455 m_profilesCache.AddOrUpdate(props.UserId, uce, PROFILECACHEEXPIRE);
1068 } 1456 }
1069 1457
1070 remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, charterMember , props.FirstLifeText, flags, 1458 // if on same region force online
1459 if(p != null && !p.IsDeleted)
1460 flags |= 0x10;
1461
1462 if(clients == null)
1463 {
1464 remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType , props.FirstLifeText, flags,
1071 props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId); 1465 props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
1072 1466
1467 remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText,
1468 (uint)props.SkillsMask, props.SkillsText, props.Language);
1469 }
1470 else
1471 {
1472 if(!clients.Contains(remoteClient))
1473 clients.Add(remoteClient);
1474 foreach(IClientAPI cli in clients)
1475 {
1476 if(!cli.IsActive)
1477 continue;
1478 cli.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType , props.FirstLifeText, flags,
1479 props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
1480
1481 cli.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText,
1482 (uint)props.SkillsMask, props.SkillsText, props.Language);
1073 1483
1074 remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, (uint)props.SkillsMask, 1484 }
1075 props.SkillsText, props.Language); 1485 }
1076 } 1486 }
1077 1487
1078 /// <summary> 1488 /// <summary>
@@ -1088,6 +1498,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1088 { 1498 {
1089 if (remoteClient.AgentId == newProfile.ID) 1499 if (remoteClient.AgentId == newProfile.ID)
1090 { 1500 {
1501
1091 UserProfileProperties prop = new UserProfileProperties(); 1502 UserProfileProperties prop = new UserProfileProperties();
1092 1503
1093 prop.UserId = remoteClient.AgentId; 1504 prop.UserId = remoteClient.AgentId;
@@ -1097,6 +1508,9 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1097 prop.FirstLifeImageId = newProfile.FirstLifeImage; 1508 prop.FirstLifeImageId = newProfile.FirstLifeImage;
1098 prop.FirstLifeText = newProfile.FirstLifeAboutText; 1509 prop.FirstLifeText = newProfile.FirstLifeAboutText;
1099 1510
1511 if(!m_allowUserProfileWebURLs)
1512 prop.WebUrl ="";
1513
1100 string serverURI = string.Empty; 1514 string serverURI = string.Empty;
1101 GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 1515 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
1102 1516
@@ -1109,6 +1523,16 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1109 return; 1523 return;
1110 } 1524 }
1111 1525
1526 // flush cache
1527 UserProfileCacheEntry uce = null;
1528 lock(m_profilesCache)
1529 {
1530 if(m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) && uce != null)
1531 {
1532 uce.props = null;
1533 }
1534 }
1535
1112 RequestAvatarProperties(remoteClient, newProfile.ID); 1536 RequestAvatarProperties(remoteClient, newProfile.ID);
1113 } 1537 }
1114 } 1538 }
@@ -1119,28 +1543,11 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1119 /// <returns> 1543 /// <returns>
1120 /// The profile data. 1544 /// The profile data.
1121 /// </returns> 1545 /// </returns>
1122 bool GetProfileData(ref UserProfileProperties properties, bool foreign, out string message) 1546 bool GetProfileData(ref UserProfileProperties properties, bool foreign, string serverURI, out string message)
1123 { 1547 {
1124 // Can't handle NPC yet...
1125 ScenePresence p = FindPresence(properties.UserId);
1126
1127 if (null != p)
1128 {
1129 if (p.PresenceType == PresenceType.Npc)
1130 {
1131 message = "Id points to NPC";
1132 return false;
1133 }
1134 }
1135
1136 string serverURI = string.Empty;
1137 GetUserProfileServerURI(properties.UserId, out serverURI);
1138
1139 // This is checking a friend on the home grid
1140 // Not HG friend
1141 if (String.IsNullOrEmpty(serverURI)) 1548 if (String.IsNullOrEmpty(serverURI))
1142 { 1549 {
1143 message = "No Presence - foreign friend"; 1550 message = "User profile service unknown at this time";
1144 return false; 1551 return false;
1145 } 1552 }
1146 1553
@@ -1161,7 +1568,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1161 { 1568 {
1162 m_log.Debug( 1569 m_log.Debug(
1163 string.Format( 1570 string.Format(
1164 "[PROFILES]: Request using the OpenProfile API for user {0} to {1} failed", 1571 "[PROFILES]: Request using the OpenProfile API for user {0} to {1} failed",
1165 properties.UserId, serverURI), 1572 properties.UserId, serverURI),
1166 e); 1573 e);
1167 1574
@@ -1178,10 +1585,14 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1178 1585
1179 return false; 1586 return false;
1180 } 1587 }
1181 // else, continue below
1182 } 1588 }
1183 1589
1184 properties = (UserProfileProperties)Prop; 1590 properties = (UserProfileProperties)Prop;
1591 if(foreign)
1592 {
1593 cacheForeignImage(properties.UserId, properties.ImageId);
1594 cacheForeignImage(properties.UserId, properties.FirstLifeImageId);
1595 }
1185 1596
1186 message = "Success"; 1597 message = "Success";
1187 return true; 1598 return true;
@@ -1189,49 +1600,6 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1189 #endregion Avatar Properties 1600 #endregion Avatar Properties
1190 1601
1191 #region Utils 1602 #region Utils
1192 bool GetImageAssets(UUID avatarId)
1193 {
1194 string profileServerURI = string.Empty;
1195 string assetServerURI = string.Empty;
1196
1197 bool foreign = GetUserProfileServerURI(avatarId, out profileServerURI);
1198
1199 if(!foreign)
1200 return true;
1201
1202 assetServerURI = UserManagementModule.GetUserServerURL(avatarId, "AssetServerURI");
1203
1204 if(string.IsNullOrEmpty(profileServerURI) || string.IsNullOrEmpty(assetServerURI))
1205 return false;
1206
1207 OSDMap parameters= new OSDMap();
1208 parameters.Add("avatarId", OSD.FromUUID(avatarId));
1209 OSD Params = (OSD)parameters;
1210 if(!rpc.JsonRpcRequest(ref Params, "image_assets_request", profileServerURI, UUID.Random().ToString()))
1211 {
1212 return false;
1213 }
1214
1215 parameters = (OSDMap)Params;
1216
1217 if (parameters.ContainsKey("result"))
1218 {
1219 OSDArray list = (OSDArray)parameters["result"];
1220
1221 foreach (OSD asset in list)
1222 {
1223 OSDString assetId = (OSDString)asset;
1224
1225 Scene.AssetService.Get(string.Format("{0}/{1}", assetServerURI, assetId.AsString()));
1226 }
1227 return true;
1228 }
1229 else
1230 {
1231 m_log.ErrorFormat("[PROFILES]: Problematic response for image_assets_request from {0}", profileServerURI);
1232 return false;
1233 }
1234 }
1235 1603
1236 /// <summary> 1604 /// <summary>
1237 /// Gets the user account data. 1605 /// Gets the user account data.
@@ -1336,7 +1704,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1336 { 1704 {
1337 bool local; 1705 bool local;
1338 local = UserManagementModule.IsLocalGridUser(userID); 1706 local = UserManagementModule.IsLocalGridUser(userID);
1339 1707
1340 if (!local) 1708 if (!local)
1341 { 1709 {
1342 serverURI = UserManagementModule.GetUserServerURL(userID, "GatekeeperURI"); 1710 serverURI = UserManagementModule.GetUserServerURL(userID, "GatekeeperURI");
@@ -1382,6 +1750,27 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1382 } 1750 }
1383 } 1751 }
1384 1752
1753 void cacheForeignImage(UUID agent, UUID imageID)
1754 {
1755 if(imageID == null || imageID == UUID.Zero)
1756 return;
1757
1758 string assetServerURI = UserManagementModule.GetUserServerURL(agent, "AssetServerURI");
1759 if(string.IsNullOrWhiteSpace(assetServerURI))
1760 return;
1761
1762 string imageIDstr = imageID.ToString();
1763
1764
1765 if(m_assetCache != null && m_assetCache.Check(imageIDstr))
1766 return;
1767
1768 if(Scene.AssetService.Get(imageIDstr) != null)
1769 return;
1770
1771 Scene.AssetService.Get(string.Format("{0}/{1}", assetServerURI, imageIDstr));
1772 }
1773
1385 /// <summary> 1774 /// <summary>
1386 /// Finds the presence. 1775 /// Finds the presence.
1387 /// </summary> 1776 /// </summary>
@@ -1402,5 +1791,180 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1402 return null; 1791 return null;
1403 } 1792 }
1404 #endregion Util 1793 #endregion Util
1794
1795 #region Web Util
1796 /// <summary>
1797 /// Sends json-rpc request with a serializable type.
1798 /// </summary>
1799 /// <returns>
1800 /// OSD Map.
1801 /// </returns>
1802 /// <param name='parameters'>
1803 /// Serializable type .
1804 /// </param>
1805 /// <param name='method'>
1806 /// Json-rpc method to call.
1807 /// </param>
1808 /// <param name='uri'>
1809 /// URI of json-rpc service.
1810 /// </param>
1811 /// <param name='jsonId'>
1812 /// Id for our call.
1813 /// </param>
1814 bool JsonRpcRequest(ref object parameters, string method, string uri, string jsonId)
1815 {
1816 if (jsonId == null)
1817 throw new ArgumentNullException ("jsonId");
1818 if (uri == null)
1819 throw new ArgumentNullException ("uri");
1820 if (method == null)
1821 throw new ArgumentNullException ("method");
1822 if (parameters == null)
1823 throw new ArgumentNullException ("parameters");
1824
1825 // Prep our payload
1826 OSDMap json = new OSDMap();
1827
1828 json.Add("jsonrpc", OSD.FromString("2.0"));
1829 json.Add("id", OSD.FromString(jsonId));
1830 json.Add("method", OSD.FromString(method));
1831
1832 json.Add("params", OSD.SerializeMembers(parameters));
1833
1834 string jsonRequestData = OSDParser.SerializeJsonString(json);
1835 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1836
1837 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1838
1839 webRequest.ContentType = "application/json-rpc";
1840 webRequest.Method = "POST";
1841
1842 WebResponse webResponse = null;
1843 try
1844 {
1845 using(Stream dataStream = webRequest.GetRequestStream())
1846 dataStream.Write(content,0,content.Length);
1847
1848 webResponse = webRequest.GetResponse();
1849 }
1850 catch (WebException e)
1851 {
1852 Console.WriteLine("Web Error" + e.Message);
1853 Console.WriteLine ("Please check input");
1854 return false;
1855 }
1856
1857 OSDMap mret = new OSDMap();
1858
1859 using (Stream rstream = webResponse.GetResponseStream())
1860 {
1861 try
1862 {
1863 mret = (OSDMap)OSDParser.DeserializeJson(rstream);
1864 }
1865 catch (Exception e)
1866 {
1867 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1868 if (webResponse != null)
1869 webResponse.Close();
1870 return false;
1871 }
1872 }
1873
1874 if (webResponse != null)
1875 webResponse.Close();
1876
1877 if (mret.ContainsKey("error"))
1878 return false;
1879
1880 // get params...
1881 OSD.DeserializeMembers(ref parameters, (OSDMap) mret["result"]);
1882 return true;
1883 }
1884
1885 /// <summary>
1886 /// Sends json-rpc request with OSD parameter.
1887 /// </summary>
1888 /// <returns>
1889 /// The rpc request.
1890 /// </returns>
1891 /// <param name='data'>
1892 /// data - incoming as parameters, outgong as result/error
1893 /// </param>
1894 /// <param name='method'>
1895 /// Json-rpc method to call.
1896 /// </param>
1897 /// <param name='uri'>
1898 /// URI of json-rpc service.
1899 /// </param>
1900 /// <param name='jsonId'>
1901 /// If set to <c>true</c> json identifier.
1902 /// </param>
1903 bool JsonRpcRequest(ref OSD data, string method, string uri, string jsonId)
1904 {
1905 OSDMap map = new OSDMap();
1906
1907 map["jsonrpc"] = "2.0";
1908 if(string.IsNullOrEmpty(jsonId))
1909 map["id"] = UUID.Random().ToString();
1910 else
1911 map["id"] = jsonId;
1912
1913 map["method"] = method;
1914 map["params"] = data;
1915
1916 string jsonRequestData = OSDParser.SerializeJsonString(map);
1917 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1918
1919 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1920 webRequest.ContentType = "application/json-rpc";
1921 webRequest.Method = "POST";
1922
1923 WebResponse webResponse = null;
1924 try
1925 {
1926 using(Stream dataStream = webRequest.GetRequestStream())
1927 dataStream.Write(content,0,content.Length);
1928
1929 webResponse = webRequest.GetResponse();
1930 }
1931 catch (WebException e)
1932 {
1933 Console.WriteLine("Web Error" + e.Message);
1934 Console.WriteLine ("Please check input");
1935 return false;
1936 }
1937
1938 OSDMap response = new OSDMap();
1939
1940 using (Stream rstream = webResponse.GetResponseStream())
1941 {
1942 try
1943 {
1944 response = (OSDMap)OSDParser.DeserializeJson(rstream);
1945 }
1946 catch (Exception e)
1947 {
1948 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1949 if (webResponse != null)
1950 webResponse.Close();
1951 return false;
1952 }
1953 }
1954
1955 if (webResponse != null)
1956 webResponse.Close();
1957
1958 if(response.ContainsKey("error"))
1959 {
1960 data = response["error"];
1961 return false;
1962 }
1963
1964 data = response;
1965
1966 return true;
1967 }
1968 #endregion Web Util
1405 } 1969 }
1406} 1970}