aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Avatar
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs59
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs16
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs93
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs449
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs1342
11 files changed, 1878 insertions, 104 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index f2f789b..a60b314 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -841,7 +841,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
841 m_scene.ForEachClient( 841 m_scene.ForEachClient(
842 client => 842 client =>
843 { if (client.AgentId != so.AttachedAvatar) 843 { if (client.AgentId != so.AttachedAvatar)
844 client.SendKillObject(m_scene.RegionInfo.RegionHandle, new List<uint>() { so.LocalId }); 844 client.SendKillObject(new List<uint>() { so.LocalId });
845 }); 845 });
846 } 846 }
847 847
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 1a38619..8f9b17e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -833,11 +833,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
833 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1); 833 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1);
834 834
835 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); 835 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
836 TestClient tc = new TestClient(acd, sceneA, sh.SceneManager); 836 TestClient tc = new TestClient(acd, sceneA);
837 List<TestClient> destinationTestClients = new List<TestClient>(); 837 List<TestClient> destinationTestClients = new List<TestClient>();
838 EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients); 838 EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients);
839 839
840 ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager); 840 ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
841 beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32); 841 beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32);
842 842
843 InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20); 843 InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20);
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index bc79944..09cc998 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -55,6 +55,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
55 55
56 private int m_savetime = 5; // seconds to wait before saving changed appearance 56 private int m_savetime = 5; // seconds to wait before saving changed appearance
57 private int m_sendtime = 2; // seconds to wait before sending changed appearance 57 private int m_sendtime = 2; // seconds to wait before sending changed appearance
58 private bool m_reusetextures = false;
58 59
59 private int m_checkTime = 500; // milliseconds to wait between checks for appearance updates 60 private int m_checkTime = 500; // milliseconds to wait between checks for appearance updates
60 private System.Timers.Timer m_updateTimer = new System.Timers.Timer(); 61 private System.Timers.Timer m_updateTimer = new System.Timers.Timer();
@@ -73,6 +74,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
73 { 74 {
74 m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime))); 75 m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime)));
75 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);
78
76 // 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);
77 } 80 }
78 81
@@ -131,6 +134,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
131 client.OnRequestWearables += Client_OnRequestWearables; 134 client.OnRequestWearables += Client_OnRequestWearables;
132 client.OnSetAppearance += Client_OnSetAppearance; 135 client.OnSetAppearance += Client_OnSetAppearance;
133 client.OnAvatarNowWearing += Client_OnAvatarNowWearing; 136 client.OnAvatarNowWearing += Client_OnAvatarNowWearing;
137 client.OnCachedTextureRequest += Client_OnCachedTextureRequest;
134 } 138 }
135 139
136 #endregion 140 #endregion
@@ -1068,6 +1072,61 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1068 QueueAppearanceSave(client.AgentId); 1072 QueueAppearanceSave(client.AgentId);
1069 } 1073 }
1070 } 1074 }
1075
1076 /// <summary>
1077 /// Respond to the cached textures request from the client
1078 /// </summary>
1079 /// <param name="client"></param>
1080 /// <param name="serial"></param>
1081 /// <param name="cachedTextureRequest"></param>
1082 private void Client_OnCachedTextureRequest(IClientAPI client, int serial, List<CachedTextureRequestArg> cachedTextureRequest)
1083 {
1084 // m_log.WarnFormat("[AVFACTORY]: Client_OnCachedTextureRequest called for {0} ({1})", client.Name, client.AgentId);
1085 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
1086
1087 List<CachedTextureResponseArg> cachedTextureResponse = new List<CachedTextureResponseArg>();
1088 foreach (CachedTextureRequestArg request in cachedTextureRequest)
1089 {
1090 UUID texture = UUID.Zero;
1091 int index = request.BakedTextureIndex;
1092
1093 if (m_reusetextures)
1094 {
1095 // this is the most insanely dumb way to do this... however it seems to
1096 // actually work. if the appearance has been reset because wearables have
1097 // changed then the texture entries are zero'd out until the bakes are
1098 // uploaded. on login, if the textures exist in the cache (eg if you logged
1099 // into the simulator recently, then the appearance will pull those and send
1100 // them back in the packet and you won't have to rebake. if the textures aren't
1101 // in the cache then the intial makeroot() call in scenepresence will zero
1102 // them out.
1103 //
1104 // a better solution (though how much better is an open question) is to
1105 // store the hashes in the appearance and compare them. Thats's coming.
1106
1107 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index];
1108 if (face != null)
1109 texture = face.TextureID;
1110
1111 // m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index);
1112 }
1113
1114 CachedTextureResponseArg response = new CachedTextureResponseArg();
1115 response.BakedTextureIndex = index;
1116 response.BakedTextureID = texture;
1117 response.HostName = null;
1118
1119 cachedTextureResponse.Add(response);
1120 }
1121
1122 // m_log.WarnFormat("[AVFACTORY]: serial is {0}",serial);
1123 // The serial number appears to be used to match requests and responses
1124 // in the texture transaction. We just send back the serial number
1125 // that was provided in the request. The viewer bumps this for us.
1126 client.SendCachedTextureResponse(sp, serial, cachedTextureResponse);
1127 }
1128
1129
1071 #endregion 1130 #endregion
1072 1131
1073 public void WriteBakedTexturesReport(IScenePresence sp, ReportOutputAction outputAction) 1132 public void WriteBakedTexturesReport(IScenePresence sp, ReportOutputAction outputAction)
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 8056030..41ea2a2 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -371,7 +371,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
371 foreach (string fid in outstanding) 371 foreach (string fid in outstanding)
372 { 372 {
373 UUID fromAgentID; 373 UUID fromAgentID;
374 string firstname = "Unknown", lastname = "User"; 374 string firstname = "Unknown", lastname = "UserFMSFOIN";
375 if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname)) 375 if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname))
376 { 376 {
377 m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid); 377 m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid);
@@ -397,7 +397,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
397 397
398 protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) 398 protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
399 { 399 {
400 first = "Unknown"; last = "User"; 400 first = "Unknown"; last = "UserFMGAI";
401 if (!UUID.TryParse(fid, out agentID)) 401 if (!UUID.TryParse(fid, out agentID))
402 return false; 402 return false;
403 403
@@ -685,7 +685,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
685 // 685 //
686 686
687 // Try local 687 // Try local
688 if (LocalFriendshipTerminated(exfriendID)) 688 if (LocalFriendshipTerminated(client.AgentId, exfriendID))
689 return; 689 return;
690 690
691 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { exfriendID.ToString() }); 691 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { exfriendID.ToString() });
@@ -827,13 +827,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
827 return false; 827 return false;
828 } 828 }
829 829
830 public bool LocalFriendshipTerminated(UUID exfriendID) 830 public bool LocalFriendshipTerminated(UUID userID, UUID exfriendID)
831 { 831 {
832 IClientAPI friendClient = LocateClientObject(exfriendID); 832 IClientAPI friendClient = LocateClientObject(exfriendID);
833 if (friendClient != null) 833 if (friendClient != null)
834 { 834 {
835 // the friend in this sim as root agent 835 // the friend in this sim as root agent
836 friendClient.SendTerminateFriend(exfriendID); 836 friendClient.SendTerminateFriend(userID);
837 // update local cache 837 // update local cache
838 RecacheFriends(friendClient); 838 RecacheFriends(friendClient);
839 // we're done 839 // we're done
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
index 637beef..08196f1 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
@@ -193,7 +193,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
193 if (!UUID.TryParse(request["ToID"].ToString(), out toID)) 193 if (!UUID.TryParse(request["ToID"].ToString(), out toID))
194 return FailureResult(); 194 return FailureResult();
195 195
196 if (m_FriendsModule.LocalFriendshipTerminated(toID)) 196 if (m_FriendsModule.LocalFriendshipTerminated(fromID, toID))
197 return SuccessResult(); 197 return SuccessResult();
198 198
199 return FailureResult(); 199 return FailureResult();
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
index bf5c0bb..b3e3aa2 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -293,7 +293,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
293 293
294 protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) 294 protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
295 { 295 {
296 first = "Unknown"; last = "User"; 296 first = "Unknown"; last = "UserHGGAI";
297 if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last)) 297 if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last))
298 return true; 298 return true;
299 299
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index fa8c3f3..5b12ecb 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -26,27 +26,25 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
30using Nini.Config;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Framework.Scenes;
34using OpenSim.Region.Framework.Interfaces;
35using System;
36using System.Reflection;
37using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
38using System.Collections.Specialized; 31using System.Collections.Specialized;
39using System.Reflection;
40using System.IO; 32using System.IO;
33using System.Reflection;
41using System.Web; 34using System.Web;
42using System.Xml; 35using System.Xml;
43using log4net; 36using log4net;
44using Mono.Addins; 37using Mono.Addins;
38using Nini.Config;
39using OpenMetaverse;
45using OpenMetaverse.Messages.Linden; 40using OpenMetaverse.Messages.Linden;
46using OpenMetaverse.StructuredData; 41using OpenMetaverse.StructuredData;
42using OpenSim.Framework;
47using OpenSim.Framework.Capabilities; 43using OpenSim.Framework.Capabilities;
48using OpenSim.Framework.Servers; 44using OpenSim.Framework.Servers;
49using OpenSim.Framework.Servers.HttpServer; 45using OpenSim.Framework.Servers.HttpServer;
46using OpenSim.Region.Framework.Scenes;
47using OpenSim.Region.Framework.Interfaces;
50using Caps = OpenSim.Framework.Capabilities.Caps; 48using Caps = OpenSim.Framework.Capabilities.Caps;
51using OSDArray = OpenMetaverse.StructuredData.OSDArray; 49using OSDArray = OpenMetaverse.StructuredData.OSDArray;
52using OSDMap = OpenMetaverse.StructuredData.OSDMap; 50using OSDMap = OpenMetaverse.StructuredData.OSDMap;
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index f122d00..e285f21 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -47,10 +47,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
47 47
48 /// <summary> 48 /// <summary>
49 private List<Scene> m_Scenelist = new List<Scene>(); 49 private List<Scene> m_Scenelist = new List<Scene>();
50// private Dictionary<UUID, Scene> m_AgentRegions =
51// new Dictionary<UUID, Scene>();
52 50
53 private IMessageTransferModule m_TransferModule = null; 51 private IMessageTransferModule m_TransferModule;
54 private bool m_Enabled = true; 52 private bool m_Enabled = true;
55 53
56 #region Region Module interface 54 #region Region Module interface
@@ -81,9 +79,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
81// scene.RegisterModuleInterface<IInventoryTransferModule>(this); 79// scene.RegisterModuleInterface<IInventoryTransferModule>(this);
82 80
83 scene.EventManager.OnNewClient += OnNewClient; 81 scene.EventManager.OnNewClient += OnNewClient;
84// scene.EventManager.OnClientClosed += ClientLoggedOut;
85 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; 82 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
86// scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene;
87 } 83 }
88 84
89 public void RegionLoaded(Scene scene) 85 public void RegionLoaded(Scene scene)
@@ -96,11 +92,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
96 m_log.Error("[INVENTORY TRANSFER]: No Message transfer module found, transfers will be local only"); 92 m_log.Error("[INVENTORY TRANSFER]: No Message transfer module found, transfers will be local only");
97 m_Enabled = false; 93 m_Enabled = false;
98 94
99 m_Scenelist.Clear(); 95// m_Scenelist.Clear();
100 scene.EventManager.OnNewClient -= OnNewClient; 96// scene.EventManager.OnNewClient -= OnNewClient;
101// scene.EventManager.OnClientClosed -= ClientLoggedOut;
102 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; 97 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
103// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene;
104 } 98 }
105 } 99 }
106 } 100 }
@@ -108,9 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
108 public void RemoveRegion(Scene scene) 102 public void RemoveRegion(Scene scene)
109 { 103 {
110 scene.EventManager.OnNewClient -= OnNewClient; 104 scene.EventManager.OnNewClient -= OnNewClient;
111// scene.EventManager.OnClientClosed -= ClientLoggedOut;
112 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; 105 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
113// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene;
114 m_Scenelist.Remove(scene); 106 m_Scenelist.Remove(scene);
115 } 107 }
116 108
@@ -139,11 +131,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
139 // Inventory giving is conducted via instant message 131 // Inventory giving is conducted via instant message
140 client.OnInstantMessage += OnInstantMessage; 132 client.OnInstantMessage += OnInstantMessage;
141 } 133 }
142
143// protected void OnSetRootAgentScene(UUID id, Scene scene)
144// {
145// m_AgentRegions[id] = scene;
146// }
147 134
148 private Scene FindClientScene(UUID agentId) 135 private Scene FindClientScene(UUID agentId)
149 { 136 {
@@ -188,9 +175,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
188 { 175 {
189 UUID folderID = new UUID(im.binaryBucket, 1); 176 UUID folderID = new UUID(im.binaryBucket, 1);
190 177
191 m_log.DebugFormat("[INVENTORY TRANSFER]: Inserting original folder {0} "+ 178 m_log.DebugFormat(
192 "into agent {1}'s inventory", 179 "[INVENTORY TRANSFER]: Inserting original folder {0} into agent {1}'s inventory",
193 folderID, new UUID(im.toAgentID)); 180 folderID, new UUID(im.toAgentID));
194 181
195 InventoryFolderBase folderCopy 182 InventoryFolderBase folderCopy
196 = scene.GiveInventoryFolder(recipientID, client.AgentId, folderID, UUID.Zero); 183 = scene.GiveInventoryFolder(recipientID, client.AgentId, folderID, UUID.Zero);
@@ -213,7 +200,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
213 user.ControllingClient.SendBulkUpdateInventory(folderCopy); 200 user.ControllingClient.SendBulkUpdateInventory(folderCopy);
214 201
215 // HACK!! 202 // HACK!!
216 // Insert the ID of the copied item into the IM so that we know which item to move to trash if it 203 // Insert the ID of the copied folder into the IM so that we know which item to move to trash if it
217 // is rejected. 204 // is rejected.
218 // XXX: This is probably a misuse of the session ID slot. 205 // XXX: This is probably a misuse of the session ID slot.
219 im.imSessionID = copyID.Guid; 206 im.imSessionID = copyID.Guid;
@@ -425,7 +412,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
425 { 412 {
426 folder = new InventoryFolderBase(inventoryID, client.AgentId); 413 folder = new InventoryFolderBase(inventoryID, client.AgentId);
427 folder = invService.GetFolder(folder); 414 folder = invService.GetFolder(folder);
428 415
429 if (folder != null & trashFolder != null) 416 if (folder != null & trashFolder != null)
430 { 417 {
431 previousParentFolderID = folder.ParentID; 418 previousParentFolderID = folder.ParentID;
@@ -477,70 +464,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
477 } 464 }
478 } 465 }
479 466
480// public bool NeedSceneCacheClear(UUID agentID, Scene scene)
481// {
482// if (!m_AgentRegions.ContainsKey(agentID))
483// {
484// // Since we can get here two ways, we need to scan
485// // the scenes here. This is somewhat more expensive
486// // but helps avoid a nasty bug
487// //
488//
489// foreach (Scene s in m_Scenelist)
490// {
491// ScenePresence presence;
492//
493// if (s.TryGetScenePresence(agentID, out presence))
494// {
495// // If the agent is in this scene, then we
496// // are being called twice in a single
497// // teleport. This is wasteful of cycles
498// // but harmless due to this 2nd level check
499// //
500// // If the agent is found in another scene
501// // then the list wasn't current
502// //
503// // If the agent is totally unknown, then what
504// // are we even doing here??
505// //
506// if (s == scene)
507// {
508// //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName);
509// return true;
510// }
511// else
512// {
513// //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName);
514// return false;
515// }
516// }
517// }
518// //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName);
519// return true;
520// }
521//
522// // The agent is left in current Scene, so we must be
523// // going to another instance
524// //
525// if (m_AgentRegions[agentID] == scene)
526// {
527// //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName);
528// m_AgentRegions.Remove(agentID);
529// return true;
530// }
531//
532// // Another region has claimed the agent
533// //
534// //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName);
535// return false;
536// }
537//
538// public void ClientLoggedOut(UUID agentID, Scene scene)
539// {
540// if (m_AgentRegions.ContainsKey(agentID))
541// m_AgentRegions.Remove(agentID);
542// }
543
544 /// <summary> 467 /// <summary>
545 /// 468 ///
546 /// </summary> 469 /// </summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs
new file mode 100644
index 0000000..162a0c3
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs
@@ -0,0 +1,449 @@
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 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net.Config;
32using Nini.Config;
33using NUnit.Framework;
34using OpenMetaverse;
35using OpenMetaverse.Assets;
36using OpenSim.Framework;
37using OpenSim.Region.CoreModules.Avatar.Inventory.Transfer;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using OpenSim.Tests.Common;
42using OpenSim.Tests.Common.Mock;
43
44namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
45{
46 [TestFixture]
47 public class InventoryTransferModuleTests : OpenSimTestCase
48 {
49 protected TestScene m_scene;
50
51 [SetUp]
52 public override void SetUp()
53 {
54 base.SetUp();
55
56 IConfigSource config = new IniConfigSource();
57 config.AddConfig("Messaging");
58 config.Configs["Messaging"].Set("InventoryTransferModule", "InventoryTransferModule");
59
60 m_scene = new SceneHelpers().SetupScene();
61 SceneHelpers.SetupSceneModules(m_scene, config, new InventoryTransferModule());
62 }
63
64 [Test]
65 public void TestAcceptGivenItem()
66 {
67// TestHelpers.EnableLogging();
68
69 UUID initialSessionId = TestHelpers.ParseTail(0x10);
70 UUID itemId = TestHelpers.ParseTail(0x100);
71 UUID assetId = TestHelpers.ParseTail(0x200);
72
73 UserAccount ua1
74 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
75 UserAccount ua2
76 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
77
78 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
79 TestClient giverClient = (TestClient)giverSp.ControllingClient;
80
81 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
82 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
83
84 // Create the object to test give
85 InventoryItemBase originalItem
86 = UserInventoryHelpers.CreateInventoryItem(
87 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object);
88
89 byte[] giveImBinaryBucket = new byte[17];
90 byte[] itemIdBytes = itemId.GetBytes();
91 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
92
93 GridInstantMessage giveIm
94 = new GridInstantMessage(
95 m_scene,
96 giverSp.UUID,
97 giverSp.Name,
98 receiverSp.UUID,
99 (byte)InstantMessageDialog.InventoryOffered,
100 false,
101 "inventory offered msg",
102 initialSessionId,
103 false,
104 Vector3.Zero,
105 giveImBinaryBucket,
106 true);
107
108 giverClient.HandleImprovedInstantMessage(giveIm);
109
110 // These details might not all be correct.
111 GridInstantMessage acceptIm
112 = new GridInstantMessage(
113 m_scene,
114 receiverSp.UUID,
115 receiverSp.Name,
116 giverSp.UUID,
117 (byte)InstantMessageDialog.InventoryAccepted,
118 false,
119 "inventory accepted msg",
120 initialSessionId,
121 false,
122 Vector3.Zero,
123 null,
124 true);
125
126 receiverClient.HandleImprovedInstantMessage(acceptIm);
127
128 // Test for item remaining in the giver's inventory (here we assume a copy item)
129 // TODO: Test no-copy items.
130 InventoryItemBase originalItemAfterGive
131 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
132
133 Assert.That(originalItemAfterGive, Is.Not.Null);
134 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID));
135
136 // Test for item successfully making it into the receiver's inventory
137 InventoryItemBase receivedItem
138 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Objects/givenObj");
139
140 Assert.That(receivedItem, Is.Not.Null);
141 Assert.That(receivedItem.ID, Is.Not.EqualTo(originalItem.ID));
142
143 // Test that on a delete, item still exists and is accessible for the giver.
144 m_scene.InventoryService.DeleteItems(receiverSp.UUID, new List<UUID>() { receivedItem.ID });
145
146 InventoryItemBase originalItemAfterDelete
147 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
148
149 Assert.That(originalItemAfterDelete, Is.Not.Null);
150
151 // TODO: Test scenario where giver deletes their item first.
152 }
153
154 /// <summary>
155 /// Test user rejection of a given item.
156 /// </summary>
157 /// <remarks>
158 /// A rejected item still ends up in the user's trash folder.
159 /// </remarks>
160 [Test]
161 public void TestRejectGivenItem()
162 {
163// TestHelpers.EnableLogging();
164
165 UUID initialSessionId = TestHelpers.ParseTail(0x10);
166 UUID itemId = TestHelpers.ParseTail(0x100);
167 UUID assetId = TestHelpers.ParseTail(0x200);
168
169 UserAccount ua1
170 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
171 UserAccount ua2
172 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
173
174 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
175 TestClient giverClient = (TestClient)giverSp.ControllingClient;
176
177 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
178 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
179
180 // Create the object to test give
181 InventoryItemBase originalItem
182 = UserInventoryHelpers.CreateInventoryItem(
183 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object);
184
185 GridInstantMessage receivedIm = null;
186 receiverClient.OnReceivedInstantMessage += im => receivedIm = im;
187
188 byte[] giveImBinaryBucket = new byte[17];
189 byte[] itemIdBytes = itemId.GetBytes();
190 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
191
192 GridInstantMessage giveIm
193 = new GridInstantMessage(
194 m_scene,
195 giverSp.UUID,
196 giverSp.Name,
197 receiverSp.UUID,
198 (byte)InstantMessageDialog.InventoryOffered,
199 false,
200 "inventory offered msg",
201 initialSessionId,
202 false,
203 Vector3.Zero,
204 giveImBinaryBucket,
205 true);
206
207 giverClient.HandleImprovedInstantMessage(giveIm);
208
209 // These details might not all be correct.
210 // Session ID is now the created item ID (!)
211 GridInstantMessage rejectIm
212 = new GridInstantMessage(
213 m_scene,
214 receiverSp.UUID,
215 receiverSp.Name,
216 giverSp.UUID,
217 (byte)InstantMessageDialog.InventoryDeclined,
218 false,
219 "inventory declined msg",
220 new UUID(receivedIm.imSessionID),
221 false,
222 Vector3.Zero,
223 null,
224 true);
225
226 receiverClient.HandleImprovedInstantMessage(rejectIm);
227
228 // Test for item remaining in the giver's inventory (here we assume a copy item)
229 // TODO: Test no-copy items.
230 InventoryItemBase originalItemAfterGive
231 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
232
233 Assert.That(originalItemAfterGive, Is.Not.Null);
234 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID));
235
236 // Test for item successfully making it into the receiver's inventory
237 InventoryItemBase receivedItem
238 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Trash/givenObj");
239
240 InventoryFolderBase trashFolder
241 = m_scene.InventoryService.GetFolderForType(receiverSp.UUID, AssetType.TrashFolder);
242
243 Assert.That(receivedItem, Is.Not.Null);
244 Assert.That(receivedItem.ID, Is.Not.EqualTo(originalItem.ID));
245 Assert.That(receivedItem.Folder, Is.EqualTo(trashFolder.ID));
246
247 // Test that on a delete, item still exists and is accessible for the giver.
248 m_scene.InventoryService.PurgeFolder(trashFolder);
249
250 InventoryItemBase originalItemAfterDelete
251 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
252
253 Assert.That(originalItemAfterDelete, Is.Not.Null);
254 }
255
256 [Test]
257 public void TestAcceptGivenFolder()
258 {
259 TestHelpers.InMethod();
260// TestHelpers.EnableLogging();
261
262 UUID initialSessionId = TestHelpers.ParseTail(0x10);
263 UUID folderId = TestHelpers.ParseTail(0x100);
264
265 UserAccount ua1
266 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
267 UserAccount ua2
268 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
269
270 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
271 TestClient giverClient = (TestClient)giverSp.ControllingClient;
272
273 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
274 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
275
276 InventoryFolderBase originalFolder
277 = UserInventoryHelpers.CreateInventoryFolder(
278 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true);
279
280 byte[] giveImBinaryBucket = new byte[17];
281 giveImBinaryBucket[0] = (byte)AssetType.Folder;
282 byte[] itemIdBytes = folderId.GetBytes();
283 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
284
285 GridInstantMessage giveIm
286 = new GridInstantMessage(
287 m_scene,
288 giverSp.UUID,
289 giverSp.Name,
290 receiverSp.UUID,
291 (byte)InstantMessageDialog.InventoryOffered,
292 false,
293 "inventory offered msg",
294 initialSessionId,
295 false,
296 Vector3.Zero,
297 giveImBinaryBucket,
298 true);
299
300 giverClient.HandleImprovedInstantMessage(giveIm);
301
302 // These details might not all be correct.
303 GridInstantMessage acceptIm
304 = new GridInstantMessage(
305 m_scene,
306 receiverSp.UUID,
307 receiverSp.Name,
308 giverSp.UUID,
309 (byte)InstantMessageDialog.InventoryAccepted,
310 false,
311 "inventory accepted msg",
312 initialSessionId,
313 false,
314 Vector3.Zero,
315 null,
316 true);
317
318 receiverClient.HandleImprovedInstantMessage(acceptIm);
319
320 // Test for item remaining in the giver's inventory (here we assume a copy item)
321 // TODO: Test no-copy items.
322 InventoryFolderBase originalFolderAfterGive
323 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
324
325 Assert.That(originalFolderAfterGive, Is.Not.Null);
326 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID));
327
328 // Test for item successfully making it into the receiver's inventory
329 InventoryFolderBase receivedFolder
330 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "f1");
331
332 Assert.That(receivedFolder, Is.Not.Null);
333 Assert.That(receivedFolder.ID, Is.Not.EqualTo(originalFolder.ID));
334
335 // Test that on a delete, item still exists and is accessible for the giver.
336 m_scene.InventoryService.DeleteFolders(receiverSp.UUID, new List<UUID>() { receivedFolder.ID });
337
338 InventoryFolderBase originalFolderAfterDelete
339 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
340
341 Assert.That(originalFolderAfterDelete, Is.Not.Null);
342
343 // TODO: Test scenario where giver deletes their item first.
344 }
345
346 /// <summary>
347 /// Test user rejection of a given item.
348 /// </summary>
349 /// <remarks>
350 /// A rejected item still ends up in the user's trash folder.
351 /// </remarks>
352 [Test]
353 public void TestRejectGivenFolder()
354 {
355 TestHelpers.InMethod();
356// TestHelpers.EnableLogging();
357
358 UUID initialSessionId = TestHelpers.ParseTail(0x10);
359 UUID folderId = TestHelpers.ParseTail(0x100);
360
361 UserAccount ua1
362 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
363 UserAccount ua2
364 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
365
366 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
367 TestClient giverClient = (TestClient)giverSp.ControllingClient;
368
369 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
370 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
371
372 // Create the folder to test give
373 InventoryFolderBase originalFolder
374 = UserInventoryHelpers.CreateInventoryFolder(
375 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true);
376
377 GridInstantMessage receivedIm = null;
378 receiverClient.OnReceivedInstantMessage += im => receivedIm = im;
379
380 byte[] giveImBinaryBucket = new byte[17];
381 giveImBinaryBucket[0] = (byte)AssetType.Folder;
382 byte[] itemIdBytes = folderId.GetBytes();
383 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
384
385 GridInstantMessage giveIm
386 = new GridInstantMessage(
387 m_scene,
388 giverSp.UUID,
389 giverSp.Name,
390 receiverSp.UUID,
391 (byte)InstantMessageDialog.InventoryOffered,
392 false,
393 "inventory offered msg",
394 initialSessionId,
395 false,
396 Vector3.Zero,
397 giveImBinaryBucket,
398 true);
399
400 giverClient.HandleImprovedInstantMessage(giveIm);
401
402 // These details might not all be correct.
403 // Session ID is now the created item ID (!)
404 GridInstantMessage rejectIm
405 = new GridInstantMessage(
406 m_scene,
407 receiverSp.UUID,
408 receiverSp.Name,
409 giverSp.UUID,
410 (byte)InstantMessageDialog.InventoryDeclined,
411 false,
412 "inventory declined msg",
413 new UUID(receivedIm.imSessionID),
414 false,
415 Vector3.Zero,
416 null,
417 true);
418
419 receiverClient.HandleImprovedInstantMessage(rejectIm);
420
421 // Test for item remaining in the giver's inventory (here we assume a copy item)
422 // TODO: Test no-copy items.
423 InventoryFolderBase originalFolderAfterGive
424 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
425
426 Assert.That(originalFolderAfterGive, Is.Not.Null);
427 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID));
428
429 // Test for folder successfully making it into the receiver's inventory
430 InventoryFolderBase receivedFolder
431 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "Trash/f1");
432
433 InventoryFolderBase trashFolder
434 = m_scene.InventoryService.GetFolderForType(receiverSp.UUID, AssetType.TrashFolder);
435
436 Assert.That(receivedFolder, Is.Not.Null);
437 Assert.That(receivedFolder.ID, Is.Not.EqualTo(originalFolder.ID));
438 Assert.That(receivedFolder.ParentID, Is.EqualTo(trashFolder.ID));
439
440 // Test that on a delete, item still exists and is accessible for the giver.
441 m_scene.InventoryService.PurgeFolder(trashFolder);
442
443 InventoryFolderBase originalFolderAfterDelete
444 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
445
446 Assert.That(originalFolderAfterDelete, Is.Not.Null);
447 }
448 }
449} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
index bf24030..2bb24ae 100644
--- a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
@@ -57,6 +57,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile
57 57
58 public void Initialise(IConfigSource config) 58 public void Initialise(IConfigSource config)
59 { 59 {
60 if(config.Configs["UserProfiles"] != null)
61 return;
62
60 m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled"); 63 m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled");
61 m_Enabled = true; 64 m_Enabled = true;
62 } 65 }
diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
new file mode 100644
index 0000000..322addd
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -0,0 +1,1342 @@
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 */
27
28using System;
29using System.IO;
30using System.Text;
31using System.Collections;
32using System.Collections.Generic;
33using System.Globalization;
34using System.Net;
35using System.Net.Sockets;
36using System.Reflection;
37using System.Xml;
38using OpenMetaverse;
39using OpenMetaverse.StructuredData;
40using log4net;
41using Nini.Config;
42using Nwc.XmlRpc;
43using OpenSim.Framework;
44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes;
46using OpenSim.Services.Interfaces;
47using Mono.Addins;
48using OpenSim.Services.Connectors.Hypergrid;
49
50namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
51{
52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserProfilesModule")]
53 public class UserProfileModule : IProfileModule, INonSharedRegionModule
54 {
55 /// <summary>
56 /// Logging
57 /// </summary>
58 static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59
60 // The pair of Dictionaries are used to handle the switching of classified ads
61 // by maintaining a cache of classified id to creator id mappings and an interest
62 // count. The entries are removed when the interest count reaches 0.
63 Dictionary<UUID,UUID> classifiedCache = new Dictionary<UUID, UUID>();
64 Dictionary<UUID,int> classifiedInterest = new Dictionary<UUID, int>();
65
66 public Scene Scene
67 {
68 get; private set;
69 }
70
71 /// <summary>
72 /// Gets or sets the ConfigSource.
73 /// </summary>
74 /// <value>
75 /// The configuration
76 /// </value>
77 public IConfigSource Config {
78 get;
79 set;
80 }
81
82 /// <summary>
83 /// Gets or sets the URI to the profile server.
84 /// </summary>
85 /// <value>
86 /// The profile server URI.
87 /// </value>
88 public string ProfileServerUri {
89 get;
90 set;
91 }
92
93 IProfileModule ProfileModule
94 {
95 get; set;
96 }
97
98 IUserManagement UserManagementModule
99 {
100 get; set;
101 }
102
103 /// <summary>
104 /// Gets or sets a value indicating whether this
105 /// <see cref="BlueWall.SlipStream.ProfileModule.UserProfileModule"/> is enabled.
106 /// </summary>
107 /// <value>
108 /// <c>true</c> if enabled; otherwise, <c>false</c>.
109 /// </value>
110 public bool Enabled {
111 get;
112 set;
113 }
114
115 #region IRegionModuleBase implementation
116 /// <summary>
117 /// This is called to initialize the region module. For shared modules, this is called exactly once, after
118 /// creating the single (shared) instance. For non-shared modules, this is called once on each instance, after
119 /// the instace for the region has been created.
120 /// </summary>
121 /// <param name='source'>
122 /// Source.
123 /// </param>
124 public void Initialise(IConfigSource source)
125 {
126 Config = source;
127 ReplaceableInterface = typeof(IProfileModule);
128
129 IConfig profileConfig = Config.Configs["UserProfiles"];
130
131 if (profileConfig == null)
132 {
133 m_log.Debug("[PROFILES]: UserProfiles disabled, no configuration");
134 Enabled = false;
135 return;
136 }
137
138 // If we find ProfileURL then we configure for FULL support
139 // else we setup for BASIC support
140 ProfileServerUri = profileConfig.GetString("ProfileServiceURL", "");
141 if (ProfileServerUri == "")
142 {
143 Enabled = false;
144 return;
145 }
146
147 m_log.Debug("[PROFILES]: Full Profiles Enabled");
148 ReplaceableInterface = null;
149 Enabled = true;
150 }
151
152 /// <summary>
153 /// Adds the region.
154 /// </summary>
155 /// <param name='scene'>
156 /// Scene.
157 /// </param>
158 public void AddRegion(Scene scene)
159 {
160 if(!Enabled)
161 return;
162
163 Scene = scene;
164 Scene.RegisterModuleInterface<IProfileModule>(this);
165 Scene.EventManager.OnNewClient += OnNewClient;
166 Scene.EventManager.OnMakeRootAgent += HandleOnMakeRootAgent;
167
168 UserManagementModule = Scene.RequestModuleInterface<IUserManagement>();
169 }
170
171 void HandleOnMakeRootAgent (ScenePresence obj)
172 {
173 if(obj.PresenceType == PresenceType.Npc)
174 return;
175
176 GetImageAssets(((IScenePresence)obj).UUID);
177 }
178
179 /// <summary>
180 /// Removes the region.
181 /// </summary>
182 /// <param name='scene'>
183 /// Scene.
184 /// </param>
185 public void RemoveRegion(Scene scene)
186 {
187 if(!Enabled)
188 return;
189 }
190
191 /// <summary>
192 /// This will be called once for every scene loaded. In a shared module this will be multiple times in one
193 /// instance, while a nonshared module instance will only be called once. This method is called after AddRegion
194 /// has been called in all modules for that scene, providing an opportunity to request another module's
195 /// interface, or hook an event from another module.
196 /// </summary>
197 /// <param name='scene'>
198 /// Scene.
199 /// </param>
200 public void RegionLoaded(Scene scene)
201 {
202 if(!Enabled)
203 return;
204 }
205
206 /// <summary>
207 /// If this returns non-null, it is the type of an interface that this module intends to register. This will
208 /// cause the loader to defer loading of this module until all other modules have been loaded. If no other
209 /// module has registered the interface by then, this module will be activated, else it will remain inactive,
210 /// letting the other module take over. This should return non-null ONLY in modules that are intended to be
211 /// easily replaceable, e.g. stub implementations that the developer expects to be replaced by third party
212 /// provided modules.
213 /// </summary>
214 /// <value>
215 /// The replaceable interface.
216 /// </value>
217 public Type ReplaceableInterface
218 {
219 get; private set;
220 }
221
222 /// <summary>
223 /// Called as the instance is closed.
224 /// </summary>
225 public void Close()
226 {
227 }
228
229 /// <value>
230 /// The name of the module
231 /// </value>
232 /// <summary>
233 /// Gets the module name.
234 /// </summary>
235 public string Name
236 {
237 get { return "UserProfileModule"; }
238 }
239 #endregion IRegionModuleBase implementation
240
241 #region Region Event Handlers
242 /// <summary>
243 /// Raises the new client event.
244 /// </summary>
245 /// <param name='client'>
246 /// Client.
247 /// </param>
248 void OnNewClient(IClientAPI client)
249 {
250 //Profile
251 client.OnRequestAvatarProperties += RequestAvatarProperties;
252 client.OnUpdateAvatarProperties += AvatarPropertiesUpdate;
253 client.OnAvatarInterestUpdate += AvatarInterestsUpdate;
254
255 // Classifieds
256 client.AddGenericPacketHandler("avatarclassifiedsrequest", ClassifiedsRequest);
257 client.OnClassifiedInfoUpdate += ClassifiedInfoUpdate;
258 client.OnClassifiedInfoRequest += ClassifiedInfoRequest;
259 client.OnClassifiedDelete += ClassifiedDelete;
260
261 // Picks
262 client.AddGenericPacketHandler("avatarpicksrequest", PicksRequest);
263 client.AddGenericPacketHandler("pickinforequest", PickInfoRequest);
264 client.OnPickInfoUpdate += PickInfoUpdate;
265 client.OnPickDelete += PickDelete;
266
267 // Notes
268 client.AddGenericPacketHandler("avatarnotesrequest", NotesRequest);
269 client.OnAvatarNotesUpdate += NotesUpdate;
270 }
271 #endregion Region Event Handlers
272
273 #region Classified
274 ///
275 /// <summary>
276 /// Handles the avatar classifieds request.
277 /// </summary>
278 /// <param name='sender'>
279 /// Sender.
280 /// </param>
281 /// <param name='method'>
282 /// Method.
283 /// </param>
284 /// <param name='args'>
285 /// Arguments.
286 /// </param>
287 public void ClassifiedsRequest(Object sender, string method, List<String> args)
288 {
289 if (!(sender is IClientAPI))
290 return;
291
292 IClientAPI remoteClient = (IClientAPI)sender;
293
294 UUID targetID;
295 UUID.TryParse(args[0], out targetID);
296
297 // Can't handle NPC yet...
298 ScenePresence p = FindPresence(targetID);
299
300 if (null != p)
301 {
302 if (p.PresenceType == PresenceType.Npc)
303 return;
304 }
305
306 string serverURI = string.Empty;
307 bool foreign = GetUserProfileServerURI(targetID, out serverURI);
308 UUID creatorId = UUID.Zero;
309
310 OSDMap parameters= new OSDMap();
311 UUID.TryParse(args[0], out creatorId);
312 parameters.Add("creatorId", OSD.FromUUID(creatorId));
313 OSD Params = (OSD)parameters;
314 if(!JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString()))
315 {
316 // Error Handling here!
317 // if(parameters.ContainsKey("message")
318 }
319
320 parameters = (OSDMap)Params;
321
322 OSDArray list = (OSDArray)parameters["result"];
323
324 Dictionary<UUID, string> classifieds = new Dictionary<UUID, string>();
325
326 foreach(OSD map in list)
327 {
328 OSDMap m = (OSDMap)map;
329 UUID cid = m["classifieduuid"].AsUUID();
330 string name = m["name"].AsString();
331
332 classifieds[cid] = name;
333
334 if(!classifiedCache.ContainsKey(cid))
335 {
336 lock(classifiedCache)
337 classifiedCache.Add(cid,creatorId);
338 lock(classifiedInterest)
339 classifiedInterest.Add(cid, 0);
340 }
341
342 lock(classifiedInterest)
343 classifiedInterest[cid] ++;
344 }
345
346 remoteClient.SendAvatarClassifiedReply(new UUID(args[0]), classifieds);
347 }
348
349 public void ClassifiedInfoRequest(UUID queryClassifiedID, IClientAPI remoteClient)
350 {
351 UUID target = remoteClient.AgentId;
352 UserClassifiedAdd ad = new UserClassifiedAdd();
353 ad.ClassifiedId = queryClassifiedID;
354
355 if(classifiedCache.ContainsKey(queryClassifiedID))
356 {
357 target = classifiedCache[queryClassifiedID];
358
359 lock(classifiedInterest)
360 classifiedInterest[queryClassifiedID] --;
361
362 if(classifiedInterest[queryClassifiedID] == 0)
363 {
364 lock(classifiedInterest)
365 classifiedInterest.Remove(queryClassifiedID);
366 lock(classifiedCache)
367 classifiedCache.Remove(queryClassifiedID);
368 }
369 }
370
371 string serverURI = string.Empty;
372 bool foreign = GetUserProfileServerURI(target, out serverURI);
373
374 object Ad = (object)ad;
375 if(!JsonRpcRequest(ref Ad, "classifieds_info_query", serverURI, UUID.Random().ToString()))
376 {
377 remoteClient.SendAgentAlertMessage(
378 "Error getting classified info", false);
379 return;
380 }
381 ad = (UserClassifiedAdd) Ad;
382
383 if(ad.CreatorId == UUID.Zero)
384 return;
385
386 Vector3 globalPos = new Vector3();
387 Vector3.TryParse(ad.GlobalPos, out globalPos);
388
389 remoteClient.SendClassifiedInfoReply(ad.ClassifiedId, ad.CreatorId, (uint)ad.CreationDate, (uint)ad.ExpirationDate,
390 (uint)ad.Category, ad.Name, ad.Description, ad.ParcelId, (uint)ad.ParentEstate,
391 ad.SnapshotId, ad.SimName, globalPos, ad.ParcelName, ad.Flags, ad.Price);
392
393 }
394
395 /// <summary>
396 /// Classifieds info update.
397 /// </summary>
398 /// <param name='queryclassifiedID'>
399 /// Queryclassified I.
400 /// </param>
401 /// <param name='queryCategory'>
402 /// Query category.
403 /// </param>
404 /// <param name='queryName'>
405 /// Query name.
406 /// </param>
407 /// <param name='queryDescription'>
408 /// Query description.
409 /// </param>
410 /// <param name='queryParcelID'>
411 /// Query parcel I.
412 /// </param>
413 /// <param name='queryParentEstate'>
414 /// Query parent estate.
415 /// </param>
416 /// <param name='querySnapshotID'>
417 /// Query snapshot I.
418 /// </param>
419 /// <param name='queryGlobalPos'>
420 /// Query global position.
421 /// </param>
422 /// <param name='queryclassifiedFlags'>
423 /// Queryclassified flags.
424 /// </param>
425 /// <param name='queryclassifiedPrice'>
426 /// Queryclassified price.
427 /// </param>
428 /// <param name='remoteClient'>
429 /// Remote client.
430 /// </param>
431 public void ClassifiedInfoUpdate(UUID queryclassifiedID, uint queryCategory, string queryName, string queryDescription, UUID queryParcelID,
432 uint queryParentEstate, UUID querySnapshotID, Vector3 queryGlobalPos, byte queryclassifiedFlags,
433 int queryclassifiedPrice, IClientAPI remoteClient)
434 {
435 UserClassifiedAdd ad = new UserClassifiedAdd();
436
437 Scene s = (Scene) remoteClient.Scene;
438 Vector3 pos = remoteClient.SceneAgent.AbsolutePosition;
439 ILandObject land = s.LandChannel.GetLandObject(pos.X, pos.Y);
440 ScenePresence p = FindPresence(remoteClient.AgentId);
441 Vector3 avaPos = p.AbsolutePosition;
442
443 string serverURI = string.Empty;
444 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
445
446 if (land == null)
447 {
448 ad.ParcelName = string.Empty;
449 }
450 else
451 {
452 ad.ParcelName = land.LandData.Name;
453 }
454
455 ad.CreatorId = remoteClient.AgentId;
456 ad.ClassifiedId = queryclassifiedID;
457 ad.Category = Convert.ToInt32(queryCategory);
458 ad.Name = queryName;
459 ad.Description = queryDescription;
460 ad.ParentEstate = Convert.ToInt32(queryParentEstate);
461 ad.SnapshotId = querySnapshotID;
462 ad.SimName = remoteClient.Scene.RegionInfo.RegionName;
463 ad.GlobalPos = queryGlobalPos.ToString ();
464 ad.Flags = queryclassifiedFlags;
465 ad.Price = queryclassifiedPrice;
466 ad.ParcelId = p.currentParcelUUID;
467
468 object Ad = ad;
469
470 OSD X = OSD.SerializeMembers(Ad);
471
472 if(!JsonRpcRequest(ref Ad, "classified_update", serverURI, UUID.Random().ToString()))
473 {
474 remoteClient.SendAgentAlertMessage(
475 "Error updating classified", false);
476 }
477 }
478
479 /// <summary>
480 /// Classifieds delete.
481 /// </summary>
482 /// <param name='queryClassifiedID'>
483 /// Query classified I.
484 /// </param>
485 /// <param name='remoteClient'>
486 /// Remote client.
487 /// </param>
488 public void ClassifiedDelete(UUID queryClassifiedID, IClientAPI remoteClient)
489 {
490 string serverURI = string.Empty;
491 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
492
493 UUID classifiedId;
494 OSDMap parameters= new OSDMap();
495 UUID.TryParse(queryClassifiedID.ToString(), out classifiedId);
496 parameters.Add("classifiedId", OSD.FromUUID(classifiedId));
497 OSD Params = (OSD)parameters;
498 if(!JsonRpcRequest(ref Params, "classified_delete", serverURI, UUID.Random().ToString()))
499 {
500 remoteClient.SendAgentAlertMessage(
501 "Error classified delete", false);
502 }
503
504 parameters = (OSDMap)Params;
505 }
506 #endregion Classified
507
508 #region Picks
509 /// <summary>
510 /// Handles the avatar picks request.
511 /// </summary>
512 /// <param name='sender'>
513 /// Sender.
514 /// </param>
515 /// <param name='method'>
516 /// Method.
517 /// </param>
518 /// <param name='args'>
519 /// Arguments.
520 /// </param>
521 public void PicksRequest(Object sender, string method, List<String> args)
522 {
523 if (!(sender is IClientAPI))
524 return;
525
526 IClientAPI remoteClient = (IClientAPI)sender;
527
528 UUID targetId;
529 UUID.TryParse(args[0], out targetId);
530
531 // Can't handle NPC yet...
532 ScenePresence p = FindPresence(targetId);
533
534 if (null != p)
535 {
536 if (p.PresenceType == PresenceType.Npc)
537 return;
538 }
539
540 string serverURI = string.Empty;
541 bool foreign = GetUserProfileServerURI(targetId, out serverURI);
542
543 OSDMap parameters= new OSDMap();
544 parameters.Add("creatorId", OSD.FromUUID(targetId));
545 OSD Params = (OSD)parameters;
546 if(!JsonRpcRequest(ref Params, "avatarpicksrequest", serverURI, UUID.Random().ToString()))
547 {
548 remoteClient.SendAgentAlertMessage(
549 "Error requesting picks", false);
550 return;
551 }
552
553 parameters = (OSDMap)Params;
554
555 OSDArray list = (OSDArray)parameters["result"];
556
557 Dictionary<UUID, string> picks = new Dictionary<UUID, string>();
558
559 foreach(OSD map in list)
560 {
561 OSDMap m = (OSDMap)map;
562 UUID cid = m["pickuuid"].AsUUID();
563 string name = m["name"].AsString();
564
565 m_log.DebugFormat("[PROFILES]: PicksRequest {0}", name);
566
567 picks[cid] = name;
568 }
569 remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks);
570 }
571
572 /// <summary>
573 /// Handles the pick info request.
574 /// </summary>
575 /// <param name='sender'>
576 /// Sender.
577 /// </param>
578 /// <param name='method'>
579 /// Method.
580 /// </param>
581 /// <param name='args'>
582 /// Arguments.
583 /// </param>
584 public void PickInfoRequest(Object sender, string method, List<String> args)
585 {
586 if (!(sender is IClientAPI))
587 return;
588
589 UUID targetID;
590 UUID.TryParse(args[0], out targetID);
591 string serverURI = string.Empty;
592 bool foreign = GetUserProfileServerURI(targetID, out serverURI);
593 IClientAPI remoteClient = (IClientAPI)sender;
594
595 UserProfilePick pick = new UserProfilePick();
596 UUID.TryParse(args[0], out pick.CreatorId);
597 UUID.TryParse(args[1], out pick.PickId);
598
599
600 object Pick = (object)pick;
601 if(!JsonRpcRequest(ref Pick, "pickinforequest", serverURI, UUID.Random().ToString()))
602 {
603 remoteClient.SendAgentAlertMessage(
604 "Error selecting pick", false);
605 }
606 pick = (UserProfilePick) Pick;
607 if(pick.SnapshotId == UUID.Zero)
608 {
609 // In case of a new UserPick, the data may not be ready and we would send wrong data, skip it...
610 m_log.DebugFormat("[PROFILES]: PickInfoRequest: SnapshotID is {0}", UUID.Zero.ToString());
611 return;
612 }
613
614 Vector3 globalPos;
615 Vector3.TryParse(pick.GlobalPos,out globalPos);
616
617 m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString());
618
619 remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name,
620 pick.Desc,pick.SnapshotId,pick.User,pick.OriginalName,pick.SimName,
621 globalPos,pick.SortOrder,pick.Enabled);
622 }
623
624 /// <summary>
625 /// Updates the userpicks
626 /// </summary>
627 /// <param name='remoteClient'>
628 /// Remote client.
629 /// </param>
630 /// <param name='pickID'>
631 /// Pick I.
632 /// </param>
633 /// <param name='creatorID'>
634 /// the creator of the pick
635 /// </param>
636 /// <param name='topPick'>
637 /// Top pick.
638 /// </param>
639 /// <param name='name'>
640 /// Name.
641 /// </param>
642 /// <param name='desc'>
643 /// Desc.
644 /// </param>
645 /// <param name='snapshotID'>
646 /// Snapshot I.
647 /// </param>
648 /// <param name='sortOrder'>
649 /// Sort order.
650 /// </param>
651 /// <param name='enabled'>
652 /// Enabled.
653 /// </param>
654 public void PickInfoUpdate(IClientAPI remoteClient, UUID pickID, UUID creatorID, bool topPick, string name, string desc, UUID snapshotID, int sortOrder, bool enabled)
655 {
656
657 m_log.DebugFormat("[PROFILES]: Start PickInfoUpdate Name: {0} PickId: {1} SnapshotId: {2}", name, pickID.ToString(), snapshotID.ToString());
658 UserProfilePick pick = new UserProfilePick();
659 string serverURI = string.Empty;
660 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
661 ScenePresence p = FindPresence(remoteClient.AgentId);
662
663 Vector3 avaPos = p.AbsolutePosition;
664 // Getting the global position for the Avatar
665 Vector3 posGlobal = new Vector3(remoteClient.Scene.RegionInfo.RegionLocX*Constants.RegionSize + avaPos.X,
666 remoteClient.Scene.RegionInfo.RegionLocY*Constants.RegionSize + avaPos.Y,
667 avaPos.Z);
668
669 string landOwnerName = string.Empty;
670 ILandObject land = p.Scene.LandChannel.GetLandObject(avaPos.X, avaPos.Y);
671 if(land.LandData.IsGroupOwned)
672 {
673 IGroupsModule groupMod = p.Scene.RequestModuleInterface<IGroupsModule>();
674 UUID groupId = land.LandData.GroupID;
675 GroupRecord groupRecord = groupMod.GetGroupRecord(groupId);
676 landOwnerName = groupRecord.GroupName;
677 }
678 else
679 {
680 IUserAccountService accounts = p.Scene.RequestModuleInterface<IUserAccountService>();
681 UserAccount user = accounts.GetUserAccount(p.Scene.RegionInfo.ScopeID, land.LandData.OwnerID);
682 landOwnerName = user.Name;
683 }
684
685 pick.PickId = pickID;
686 pick.CreatorId = creatorID;
687 pick.TopPick = topPick;
688 pick.Name = name;
689 pick.Desc = desc;
690 pick.ParcelId = p.currentParcelUUID;
691 pick.SnapshotId = snapshotID;
692 pick.User = landOwnerName;
693 pick.SimName = remoteClient.Scene.RegionInfo.RegionName;
694 pick.GlobalPos = posGlobal.ToString();
695 pick.SortOrder = sortOrder;
696 pick.Enabled = enabled;
697
698 object Pick = (object)pick;
699 if(!JsonRpcRequest(ref Pick, "picks_update", serverURI, UUID.Random().ToString()))
700 {
701 remoteClient.SendAgentAlertMessage(
702 "Error updating pick", false);
703 }
704
705 m_log.DebugFormat("[PROFILES]: Finish PickInfoUpdate {0} {1}", pick.Name, pick.PickId.ToString());
706 }
707
708 /// <summary>
709 /// Delete a Pick
710 /// </summary>
711 /// <param name='remoteClient'>
712 /// Remote client.
713 /// </param>
714 /// <param name='queryPickID'>
715 /// Query pick I.
716 /// </param>
717 public void PickDelete(IClientAPI remoteClient, UUID queryPickID)
718 {
719 string serverURI = string.Empty;
720 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
721
722 OSDMap parameters= new OSDMap();
723 parameters.Add("pickId", OSD.FromUUID(queryPickID));
724 OSD Params = (OSD)parameters;
725 if(!JsonRpcRequest(ref Params, "picks_delete", serverURI, UUID.Random().ToString()))
726 {
727 remoteClient.SendAgentAlertMessage(
728 "Error picks delete", false);
729 }
730 }
731 #endregion Picks
732
733 #region Notes
734 /// <summary>
735 /// Handles the avatar notes request.
736 /// </summary>
737 /// <param name='sender'>
738 /// Sender.
739 /// </param>
740 /// <param name='method'>
741 /// Method.
742 /// </param>
743 /// <param name='args'>
744 /// Arguments.
745 /// </param>
746 public void NotesRequest(Object sender, string method, List<String> args)
747 {
748 UserProfileNotes note = new UserProfileNotes();
749
750 if (!(sender is IClientAPI))
751 return;
752
753 IClientAPI remoteClient = (IClientAPI)sender;
754 string serverURI = string.Empty;
755 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
756 note.TargetId = remoteClient.AgentId;
757 UUID.TryParse(args[0], out note.UserId);
758
759 object Note = (object)note;
760 if(!JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString()))
761 {
762 remoteClient.SendAgentAlertMessage(
763 "Error requesting note", false);
764 }
765 note = (UserProfileNotes) Note;
766
767 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
768 }
769
770 /// <summary>
771 /// Avatars the notes update.
772 /// </summary>
773 /// <param name='remoteClient'>
774 /// Remote client.
775 /// </param>
776 /// <param name='queryTargetID'>
777 /// Query target I.
778 /// </param>
779 /// <param name='queryNotes'>
780 /// Query notes.
781 /// </param>
782 public void NotesUpdate(IClientAPI remoteClient, UUID queryTargetID, string queryNotes)
783 {
784 UserProfileNotes note = new UserProfileNotes();
785
786 note.UserId = remoteClient.AgentId;
787 note.TargetId = queryTargetID;
788 note.Notes = queryNotes;
789
790 string serverURI = string.Empty;
791 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
792
793 object Note = note;
794 if(!JsonRpcRequest(ref Note, "avatar_notes_update", serverURI, UUID.Random().ToString()))
795 {
796 remoteClient.SendAgentAlertMessage(
797 "Error updating note", false);
798 }
799 }
800 #endregion Notes
801
802 #region Avatar Properties
803 /// <summary>
804 /// Update the avatars interests .
805 /// </summary>
806 /// <param name='remoteClient'>
807 /// Remote client.
808 /// </param>
809 /// <param name='wantmask'>
810 /// Wantmask.
811 /// </param>
812 /// <param name='wanttext'>
813 /// Wanttext.
814 /// </param>
815 /// <param name='skillsmask'>
816 /// Skillsmask.
817 /// </param>
818 /// <param name='skillstext'>
819 /// Skillstext.
820 /// </param>
821 /// <param name='languages'>
822 /// Languages.
823 /// </param>
824 public void AvatarInterestsUpdate(IClientAPI remoteClient, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages)
825 {
826 UserProfileProperties prop = new UserProfileProperties();
827
828 prop.UserId = remoteClient.AgentId;
829 prop.WantToMask = (int)wantmask;
830 prop.WantToText = wanttext;
831 prop.SkillsMask = (int)skillsmask;
832 prop.SkillsText = skillstext;
833 prop.Language = languages;
834
835 string serverURI = string.Empty;
836 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
837
838 object Param = prop;
839 if(!JsonRpcRequest(ref Param, "avatar_interests_update", serverURI, UUID.Random().ToString()))
840 {
841 remoteClient.SendAgentAlertMessage(
842 "Error updating interests", false);
843 }
844 }
845
846 public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
847 {
848 if ( String.IsNullOrEmpty(avatarID.ToString()) || String.IsNullOrEmpty(remoteClient.AgentId.ToString()))
849 {
850 // Looking for a reason that some viewers are sending null Id's
851 m_log.DebugFormat("[PROFILES]: This should not happen remoteClient.AgentId {0} - avatarID {1}", remoteClient.AgentId, avatarID);
852 return;
853 }
854
855 // Can't handle NPC yet...
856 ScenePresence p = FindPresence(avatarID);
857
858 if (null != p)
859 {
860 if (p.PresenceType == PresenceType.Npc)
861 return;
862 }
863
864 string serverURI = string.Empty;
865 bool foreign = GetUserProfileServerURI(avatarID, out serverURI);
866
867 UserAccount account = null;
868 Dictionary<string,object> userInfo;
869
870 if (!foreign)
871 {
872 account = Scene.UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, avatarID);
873 }
874 else
875 {
876 userInfo = new Dictionary<string, object>();
877 }
878
879 Byte[] charterMember = new Byte[1];
880 string born = String.Empty;
881 uint flags = 0x00;
882
883 if (null != account)
884 {
885 if (account.UserTitle == "")
886 {
887 charterMember[0] = (Byte)((account.UserFlags & 0xf00) >> 8);
888 }
889 else
890 {
891 charterMember = Utils.StringToBytes(account.UserTitle);
892 }
893
894 born = Util.ToDateTime(account.Created).ToString(
895 "M/d/yyyy", CultureInfo.InvariantCulture);
896 flags = (uint)(account.UserFlags & 0xff);
897 }
898 else
899 {
900 if (GetUserAccountData(avatarID, out userInfo) == true)
901 {
902 if ((string)userInfo["user_title"] == "")
903 {
904 charterMember[0] = (Byte)(((Byte)userInfo["user_flags"] & 0xf00) >> 8);
905 }
906 else
907 {
908 charterMember = Utils.StringToBytes((string)userInfo["user_title"]);
909 }
910
911 int val_born = (int)userInfo["user_created"];
912 born = Util.ToDateTime(val_born).ToString(
913 "M/d/yyyy", CultureInfo.InvariantCulture);
914
915 // picky, picky
916 int val_flags = (int)userInfo["user_flags"];
917 flags = (uint)(val_flags & 0xff);
918 }
919 }
920
921 UserProfileProperties props = new UserProfileProperties();
922 string result = string.Empty;
923
924 props.UserId = avatarID;
925 GetProfileData(ref props, out result);
926
927 remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, charterMember , props.FirstLifeText, flags,
928 props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
929
930
931 remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, (uint)props.SkillsMask,
932 props.SkillsText, props.Language);
933 }
934
935 /// <summary>
936 /// Updates the avatar properties.
937 /// </summary>
938 /// <param name='remoteClient'>
939 /// Remote client.
940 /// </param>
941 /// <param name='newProfile'>
942 /// New profile.
943 /// </param>
944 public void AvatarPropertiesUpdate(IClientAPI remoteClient, UserProfileData newProfile)
945 {
946 if (remoteClient.AgentId == newProfile.ID)
947 {
948 UserProfileProperties prop = new UserProfileProperties();
949
950 prop.UserId = remoteClient.AgentId;
951 prop.WebUrl = newProfile.ProfileUrl;
952 prop.ImageId = newProfile.Image;
953 prop.AboutText = newProfile.AboutText;
954 prop.FirstLifeImageId = newProfile.FirstLifeImage;
955 prop.FirstLifeText = newProfile.FirstLifeAboutText;
956
957 string serverURI = string.Empty;
958 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
959
960 object Prop = prop;
961
962 if(!JsonRpcRequest(ref Prop, "avatar_properties_update", serverURI, UUID.Random().ToString()))
963 {
964 remoteClient.SendAgentAlertMessage(
965 "Error updating properties", false);
966 }
967
968 RequestAvatarProperties(remoteClient, newProfile.ID);
969 }
970 }
971
972
973 /// <summary>
974 /// Gets the profile data.
975 /// </summary>
976 /// <returns>
977 /// The profile data.
978 /// </returns>
979 /// <param name='userID'>
980 /// User I.
981 /// </param>
982 bool GetProfileData(ref UserProfileProperties properties, out string message)
983 {
984 // Can't handle NPC yet...
985 ScenePresence p = FindPresence(properties.UserId);
986
987 if (null != p)
988 {
989 if (p.PresenceType == PresenceType.Npc)
990 {
991 message = "Id points to NPC";
992 return false;
993 }
994 }
995
996 string serverURI = string.Empty;
997 bool foreign = GetUserProfileServerURI(properties.UserId, out serverURI);
998
999 // This is checking a friend on the home grid
1000 // Not HG friend
1001 if ( String.IsNullOrEmpty(serverURI))
1002 {
1003 message = "No Presence - foreign friend";
1004 return false;
1005 }
1006
1007 object Prop = (object)properties;
1008 JsonRpcRequest(ref Prop, "avatar_properties_request", serverURI, UUID.Random().ToString());
1009 properties = (UserProfileProperties)Prop;
1010
1011 message = "Success";
1012 return true;
1013 }
1014 #endregion Avatar Properties
1015
1016 #region Utils
1017 bool GetImageAssets(UUID avatarId)
1018 {
1019 string profileServerURI = string.Empty;
1020 string assetServerURI = string.Empty;
1021
1022 bool foreign = GetUserProfileServerURI(avatarId, out profileServerURI);
1023
1024 if(!foreign)
1025 return true;
1026
1027 assetServerURI = UserManagementModule.GetUserServerURL(avatarId, "AssetServerURI");
1028
1029 OSDMap parameters= new OSDMap();
1030 parameters.Add("avatarId", OSD.FromUUID(avatarId));
1031 OSD Params = (OSD)parameters;
1032 if(!JsonRpcRequest(ref Params, "image_assets_request", profileServerURI, UUID.Random().ToString()))
1033 {
1034 // Error Handling here!
1035 // if(parameters.ContainsKey("message")
1036 return false;
1037 }
1038
1039 parameters = (OSDMap)Params;
1040
1041 OSDArray list = (OSDArray)parameters["result"];
1042
1043 foreach(OSD asset in list)
1044 {
1045 OSDString assetId = (OSDString)asset;
1046
1047 Scene.AssetService.Get(string.Format("{0}/{1}",assetServerURI, assetId.AsString()), this,
1048 delegate (string assetID, Object s, AssetBase a)
1049 {
1050 // m_log.DebugFormat("[PROFILES]: Getting Image Assets {0}", assetID);
1051 return;
1052 });
1053 }
1054 return true;
1055 }
1056
1057 /// <summary>
1058 /// Gets the user account data.
1059 /// </summary>
1060 /// <returns>
1061 /// The user profile data.
1062 /// </returns>
1063 /// <param name='userID'>
1064 /// If set to <c>true</c> user I.
1065 /// </param>
1066 /// <param name='userInfo'>
1067 /// If set to <c>true</c> user info.
1068 /// </param>
1069 bool GetUserAccountData(UUID userID, out Dictionary<string, object> userInfo)
1070 {
1071 Dictionary<string,object> info = new Dictionary<string, object>();
1072
1073 if (UserManagementModule.IsLocalGridUser(userID))
1074 {
1075 // Is local
1076 IUserAccountService uas = Scene.UserAccountService;
1077 UserAccount account = uas.GetUserAccount(Scene.RegionInfo.ScopeID, userID);
1078
1079 info["user_flags"] = account.UserFlags;
1080 info["user_created"] = account.Created;
1081
1082 if (!String.IsNullOrEmpty(account.UserTitle))
1083 info["user_title"] = account.UserTitle;
1084 else
1085 info["user_title"] = "";
1086
1087 userInfo = info;
1088
1089 return false;
1090 }
1091 else
1092 {
1093 // Is Foreign
1094 string home_url = UserManagementModule.GetUserServerURL(userID, "HomeURI");
1095
1096 if (String.IsNullOrEmpty(home_url))
1097 {
1098 info["user_flags"] = 0;
1099 info["user_created"] = 0;
1100 info["user_title"] = "Unavailable";
1101
1102 userInfo = info;
1103 return true;
1104 }
1105
1106 UserAgentServiceConnector uConn = new UserAgentServiceConnector(home_url);
1107
1108 Dictionary<string, object> account = uConn.GetUserInfo(userID);
1109
1110 if (account.Count > 0)
1111 {
1112 if (account.ContainsKey("user_flags"))
1113 info["user_flags"] = account["user_flags"];
1114 else
1115 info["user_flags"] = "";
1116
1117 if (account.ContainsKey("user_created"))
1118 info["user_created"] = account["user_created"];
1119 else
1120 info["user_created"] = "";
1121
1122 info["user_title"] = "HG Visitor";
1123 }
1124 else
1125 {
1126 info["user_flags"] = 0;
1127 info["user_created"] = 0;
1128 info["user_title"] = "HG Visitor";
1129 }
1130 userInfo = info;
1131 return true;
1132 }
1133 }
1134
1135 /// <summary>
1136 /// Gets the user profile server UR.
1137 /// </summary>
1138 /// <returns>
1139 /// The user profile server UR.
1140 /// </returns>
1141 /// <param name='userID'>
1142 /// If set to <c>true</c> user I.
1143 /// </param>
1144 /// <param name='serverURI'>
1145 /// If set to <c>true</c> server UR.
1146 /// </param>
1147 bool GetUserProfileServerURI(UUID userID, out string serverURI)
1148 {
1149 bool local;
1150 local = UserManagementModule.IsLocalGridUser(userID);
1151
1152 if (!local)
1153 {
1154 serverURI = UserManagementModule.GetUserServerURL(userID, "ProfileServerURI");
1155 // Is Foreign
1156 return true;
1157 }
1158 else
1159 {
1160 serverURI = ProfileServerUri;
1161 // Is local
1162 return false;
1163 }
1164 }
1165
1166 /// <summary>
1167 /// Finds the presence.
1168 /// </summary>
1169 /// <returns>
1170 /// The presence.
1171 /// </returns>
1172 /// <param name='clientID'>
1173 /// Client I.
1174 /// </param>
1175 ScenePresence FindPresence(UUID clientID)
1176 {
1177 ScenePresence p;
1178
1179 p = Scene.GetScenePresence(clientID);
1180 if (p != null && !p.IsChildAgent)
1181 return p;
1182
1183 return null;
1184 }
1185 #endregion Util
1186
1187 #region Web Util
1188 /// <summary>
1189 /// Sends json-rpc request with a serializable type.
1190 /// </summary>
1191 /// <returns>
1192 /// OSD Map.
1193 /// </returns>
1194 /// <param name='parameters'>
1195 /// Serializable type .
1196 /// </param>
1197 /// <param name='method'>
1198 /// Json-rpc method to call.
1199 /// </param>
1200 /// <param name='uri'>
1201 /// URI of json-rpc service.
1202 /// </param>
1203 /// <param name='jsonId'>
1204 /// Id for our call.
1205 /// </param>
1206 bool JsonRpcRequest(ref object parameters, string method, string uri, string jsonId)
1207 {
1208 if (jsonId == null)
1209 throw new ArgumentNullException ("jsonId");
1210 if (uri == null)
1211 throw new ArgumentNullException ("uri");
1212 if (method == null)
1213 throw new ArgumentNullException ("method");
1214 if (parameters == null)
1215 throw new ArgumentNullException ("parameters");
1216
1217 // Prep our payload
1218 OSDMap json = new OSDMap();
1219
1220 json.Add("jsonrpc", OSD.FromString("2.0"));
1221 json.Add("id", OSD.FromString(jsonId));
1222 json.Add("method", OSD.FromString(method));
1223 // Experiment
1224 json.Add("params", OSD.SerializeMembers(parameters));
1225
1226 string jsonRequestData = OSDParser.SerializeJsonString(json);
1227 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1228
1229 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1230 // webRequest.Credentials = new NetworkCredential(rpcUser, rpcPass);
1231 webRequest.ContentType = "application/json-rpc";
1232 webRequest.Method = "POST";
1233
1234 Stream dataStream = webRequest.GetRequestStream();
1235 dataStream.Write(content, 0, content.Length);
1236 dataStream.Close();
1237
1238 WebResponse webResponse = null;
1239 try
1240 {
1241 webResponse = webRequest.GetResponse();
1242 }
1243 catch (WebException e)
1244 {
1245 Console.WriteLine("Web Error" + e.Message);
1246 Console.WriteLine ("Please check input");
1247 return false;
1248 }
1249
1250 byte[] buf = new byte[8192];
1251 Stream rstream = webResponse.GetResponseStream();
1252 OSDMap mret = (OSDMap)OSDParser.DeserializeJson(rstream);
1253
1254 if(mret.ContainsKey("error"))
1255 return false;
1256
1257 // get params...
1258 OSD.DeserializeMembers(ref parameters, (OSDMap) mret["result"]);
1259 return true;
1260 }
1261
1262 /// <summary>
1263 /// Sends json-rpc request with OSD parameter.
1264 /// </summary>
1265 /// <returns>
1266 /// The rpc request.
1267 /// </returns>
1268 /// <param name='data'>
1269 /// data - incoming as parameters, outgong as result/error
1270 /// </param>
1271 /// <param name='method'>
1272 /// Json-rpc method to call.
1273 /// </param>
1274 /// <param name='uri'>
1275 /// URI of json-rpc service.
1276 /// </param>
1277 /// <param name='jsonId'>
1278 /// If set to <c>true</c> json identifier.
1279 /// </param>
1280 bool JsonRpcRequest(ref OSD data, string method, string uri, string jsonId)
1281 {
1282 OSDMap map = new OSDMap();
1283
1284 map["jsonrpc"] = "2.0";
1285 if(string.IsNullOrEmpty(jsonId))
1286 map["id"] = UUID.Random().ToString();
1287 else
1288 map["id"] = jsonId;
1289
1290 map["method"] = method;
1291 map["params"] = data;
1292
1293 string jsonRequestData = OSDParser.SerializeJsonString(map);
1294 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1295
1296 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1297 webRequest.ContentType = "application/json-rpc";
1298 webRequest.Method = "POST";
1299
1300 Stream dataStream = webRequest.GetRequestStream();
1301 dataStream.Write(content, 0, content.Length);
1302 dataStream.Close();
1303
1304 WebResponse webResponse = null;
1305 try
1306 {
1307 webResponse = webRequest.GetResponse();
1308 }
1309 catch (WebException e)
1310 {
1311 Console.WriteLine("Web Error" + e.Message);
1312 Console.WriteLine ("Please check input");
1313 return false;
1314 }
1315
1316 byte[] buf = new byte[8192];
1317 Stream rstream = webResponse.GetResponseStream();
1318
1319 OSDMap response = new OSDMap();
1320 try
1321 {
1322 response = (OSDMap)OSDParser.DeserializeJson(rstream);
1323 }
1324 catch (Exception e)
1325 {
1326 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1327 return false;
1328 }
1329
1330 if(response.ContainsKey("error"))
1331 {
1332 data = response["error"];
1333 return false;
1334 }
1335
1336 data = response;
1337
1338 return true;
1339 }
1340 #endregion Web Util
1341 }
1342}