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.cs4
-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/UserProfiles/UserProfileModule.cs1332
9 files changed, 1861 insertions, 100 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index cb724aa..0f03ad0 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..4613344 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
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/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
new file mode 100644
index 0000000..a97c9b4
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -0,0 +1,1332 @@
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 Enabled = false;
134 return;
135 }
136
137 // If we find ProfileURL then we configure for FULL support
138 // else we setup for BASIC support
139 ProfileServerUri = profileConfig.GetString("ProfileServiceURL", "");
140 if (ProfileServerUri == "")
141 {
142 Enabled = false;
143 return;
144 }
145
146 m_log.Debug("[PROFILES]: Full Profiles Enabled");
147 ReplaceableInterface = null;
148 Enabled = true;
149 }
150
151 /// <summary>
152 /// Adds the region.
153 /// </summary>
154 /// <param name='scene'>
155 /// Scene.
156 /// </param>
157 public void AddRegion(Scene scene)
158 {
159 if(!Enabled)
160 return;
161
162 Scene = scene;
163 Scene.RegisterModuleInterface<IProfileModule>(this);
164 Scene.EventManager.OnNewClient += OnNewClient;
165 Scene.EventManager.OnMakeRootAgent += HandleOnMakeRootAgent;
166
167 UserManagementModule = Scene.RequestModuleInterface<IUserManagement>();
168 }
169
170 void HandleOnMakeRootAgent (ScenePresence obj)
171 {
172 if(obj.PresenceType == PresenceType.Npc)
173 return;
174
175 GetImageAssets(((IScenePresence)obj).UUID);
176 }
177
178 /// <summary>
179 /// Removes the region.
180 /// </summary>
181 /// <param name='scene'>
182 /// Scene.
183 /// </param>
184 public void RemoveRegion(Scene scene)
185 {
186 if(!Enabled)
187 return;
188 }
189
190 /// <summary>
191 /// This will be called once for every scene loaded. In a shared module this will be multiple times in one
192 /// instance, while a nonshared module instance will only be called once. This method is called after AddRegion
193 /// has been called in all modules for that scene, providing an opportunity to request another module's
194 /// interface, or hook an event from another module.
195 /// </summary>
196 /// <param name='scene'>
197 /// Scene.
198 /// </param>
199 public void RegionLoaded(Scene scene)
200 {
201 if(!Enabled)
202 return;
203 }
204
205 /// <summary>
206 /// If this returns non-null, it is the type of an interface that this module intends to register. This will
207 /// cause the loader to defer loading of this module until all other modules have been loaded. If no other
208 /// module has registered the interface by then, this module will be activated, else it will remain inactive,
209 /// letting the other module take over. This should return non-null ONLY in modules that are intended to be
210 /// easily replaceable, e.g. stub implementations that the developer expects to be replaced by third party
211 /// provided modules.
212 /// </summary>
213 /// <value>
214 /// The replaceable interface.
215 /// </value>
216 public Type ReplaceableInterface
217 {
218 get; private set;
219 }
220
221 /// <summary>
222 /// Called as the instance is closed.
223 /// </summary>
224 public void Close()
225 {
226 }
227
228 /// <value>
229 /// The name of the module
230 /// </value>
231 /// <summary>
232 /// Gets the module name.
233 /// </summary>
234 public string Name
235 {
236 get { return "UserProfileModule"; }
237 }
238 #endregion IRegionModuleBase implementation
239
240 #region Region Event Handlers
241 /// <summary>
242 /// Raises the new client event.
243 /// </summary>
244 /// <param name='client'>
245 /// Client.
246 /// </param>
247 void OnNewClient(IClientAPI client)
248 {
249 //Profile
250 client.OnRequestAvatarProperties += RequestAvatarProperties;
251 client.OnUpdateAvatarProperties += AvatarPropertiesUpdate;
252 client.OnAvatarInterestUpdate += AvatarInterestsUpdate;
253
254 // Classifieds
255 client.AddGenericPacketHandler("avatarclassifiedsrequest", ClassifiedsRequest);
256 client.OnClassifiedInfoUpdate += ClassifiedInfoUpdate;
257 client.OnClassifiedInfoRequest += ClassifiedInfoRequest;
258 client.OnClassifiedDelete += ClassifiedDelete;
259
260 // Picks
261 client.AddGenericPacketHandler("avatarpicksrequest", PicksRequest);
262 client.AddGenericPacketHandler("pickinforequest", PickInfoRequest);
263 client.OnPickInfoUpdate += PickInfoUpdate;
264 client.OnPickDelete += PickDelete;
265
266 // Notes
267 client.AddGenericPacketHandler("avatarnotesrequest", NotesRequest);
268 client.OnAvatarNotesUpdate += NotesUpdate;
269 }
270 #endregion Region Event Handlers
271
272 #region Classified
273 ///
274 /// <summary>
275 /// Handles the avatar classifieds request.
276 /// </summary>
277 /// <param name='sender'>
278 /// Sender.
279 /// </param>
280 /// <param name='method'>
281 /// Method.
282 /// </param>
283 /// <param name='args'>
284 /// Arguments.
285 /// </param>
286 public void ClassifiedsRequest(Object sender, string method, List<String> args)
287 {
288 if (!(sender is IClientAPI))
289 return;
290
291 IClientAPI remoteClient = (IClientAPI)sender;
292
293 UUID targetID;
294 UUID.TryParse(args[0], out targetID);
295
296 // Can't handle NPC yet...
297 ScenePresence p = FindPresence(targetID);
298
299 if (null != p)
300 {
301 if (p.PresenceType == PresenceType.Npc)
302 return;
303 }
304
305 string serverURI = string.Empty;
306 bool foreign = GetUserProfileServerURI(targetID, out serverURI);
307 UUID creatorId = UUID.Zero;
308
309 OSDMap parameters= new OSDMap();
310 UUID.TryParse(args[0], out creatorId);
311 parameters.Add("creatorId", OSD.FromUUID(creatorId));
312 OSD Params = (OSD)parameters;
313 if(!JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString()))
314 {
315 // Error Handling here!
316 // if(parameters.ContainsKey("message")
317 }
318
319 parameters = (OSDMap)Params;
320
321 OSDArray list = (OSDArray)parameters["result"];
322
323 Dictionary<UUID, string> classifieds = new Dictionary<UUID, string>();
324
325 foreach(OSD map in list)
326 {
327 OSDMap m = (OSDMap)map;
328 UUID cid = m["classifieduuid"].AsUUID();
329 string name = m["name"].AsString();
330
331 classifieds[cid] = name;
332
333 if(!classifiedCache.ContainsKey(cid))
334 {
335 lock(classifiedCache)
336 classifiedCache.Add(cid,creatorId);
337 lock(classifiedInterest)
338 classifiedInterest.Add(cid, 0);
339 }
340
341 lock(classifiedInterest)
342 classifiedInterest[cid] ++;
343 }
344
345 remoteClient.SendAvatarClassifiedReply(new UUID(args[0]), classifieds);
346 }
347
348 public void ClassifiedInfoRequest(UUID queryClassifiedID, IClientAPI remoteClient)
349 {
350 UUID target = remoteClient.AgentId;
351 UserClassifiedAdd ad = new UserClassifiedAdd();
352 ad.ClassifiedId = queryClassifiedID;
353
354 if(classifiedCache.ContainsKey(queryClassifiedID))
355 {
356 target = classifiedCache[queryClassifiedID];
357
358 lock(classifiedInterest)
359 classifiedInterest[queryClassifiedID] --;
360
361 if(classifiedInterest[queryClassifiedID] == 0)
362 {
363 lock(classifiedInterest)
364 classifiedInterest.Remove(queryClassifiedID);
365 lock(classifiedCache)
366 classifiedCache.Remove(queryClassifiedID);
367 }
368 }
369
370 string serverURI = string.Empty;
371 bool foreign = GetUserProfileServerURI(target, out serverURI);
372
373 object Ad = (object)ad;
374 if(!JsonRpcRequest(ref Ad, "classifieds_info_query", serverURI, UUID.Random().ToString()))
375 {
376 remoteClient.SendAgentAlertMessage(
377 "Error getting classified info", false);
378 return;
379 }
380 ad = (UserClassifiedAdd) Ad;
381
382 if(ad.CreatorId == UUID.Zero)
383 return;
384
385 Vector3 globalPos = new Vector3();
386 Vector3.TryParse(ad.GlobalPos, out globalPos);
387
388 remoteClient.SendClassifiedInfoReply(ad.ClassifiedId, ad.CreatorId, (uint)ad.CreationDate, (uint)ad.ExpirationDate,
389 (uint)ad.Category, ad.Name, ad.Description, ad.ParcelId, (uint)ad.ParentEstate,
390 ad.SnapshotId, ad.SimName, globalPos, ad.ParcelName, ad.Flags, ad.Price);
391
392 }
393
394 /// <summary>
395 /// Classifieds info update.
396 /// </summary>
397 /// <param name='queryclassifiedID'>
398 /// Queryclassified I.
399 /// </param>
400 /// <param name='queryCategory'>
401 /// Query category.
402 /// </param>
403 /// <param name='queryName'>
404 /// Query name.
405 /// </param>
406 /// <param name='queryDescription'>
407 /// Query description.
408 /// </param>
409 /// <param name='queryParcelID'>
410 /// Query parcel I.
411 /// </param>
412 /// <param name='queryParentEstate'>
413 /// Query parent estate.
414 /// </param>
415 /// <param name='querySnapshotID'>
416 /// Query snapshot I.
417 /// </param>
418 /// <param name='queryGlobalPos'>
419 /// Query global position.
420 /// </param>
421 /// <param name='queryclassifiedFlags'>
422 /// Queryclassified flags.
423 /// </param>
424 /// <param name='queryclassifiedPrice'>
425 /// Queryclassified price.
426 /// </param>
427 /// <param name='remoteClient'>
428 /// Remote client.
429 /// </param>
430 public void ClassifiedInfoUpdate(UUID queryclassifiedID, uint queryCategory, string queryName, string queryDescription, UUID queryParcelID,
431 uint queryParentEstate, UUID querySnapshotID, Vector3 queryGlobalPos, byte queryclassifiedFlags,
432 int queryclassifiedPrice, IClientAPI remoteClient)
433 {
434 UserClassifiedAdd ad = new UserClassifiedAdd();
435
436 Scene s = (Scene) remoteClient.Scene;
437 Vector3 pos = remoteClient.SceneAgent.AbsolutePosition;
438 ILandObject land = s.LandChannel.GetLandObject(pos.X, pos.Y);
439 ScenePresence p = FindPresence(remoteClient.AgentId);
440 Vector3 avaPos = p.AbsolutePosition;
441
442 string serverURI = string.Empty;
443 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
444
445 if (land == null)
446 {
447 ad.ParcelName = string.Empty;
448 }
449 else
450 {
451 ad.ParcelName = land.LandData.Name;
452 }
453
454 ad.CreatorId = remoteClient.AgentId;
455 ad.ClassifiedId = queryclassifiedID;
456 ad.Category = Convert.ToInt32(queryCategory);
457 ad.Name = queryName;
458 ad.Description = queryDescription;
459 ad.ParentEstate = Convert.ToInt32(queryParentEstate);
460 ad.SnapshotId = querySnapshotID;
461 ad.SimName = remoteClient.Scene.RegionInfo.RegionName;
462 ad.GlobalPos = queryGlobalPos.ToString ();
463 ad.Flags = queryclassifiedFlags;
464 ad.Price = queryclassifiedPrice;
465 ad.ParcelId = p.currentParcelUUID;
466
467 object Ad = ad;
468
469 OSD X = OSD.SerializeMembers(Ad);
470
471 if(!JsonRpcRequest(ref Ad, "classified_update", serverURI, UUID.Random().ToString()))
472 {
473 remoteClient.SendAgentAlertMessage(
474 "Error updating classified", false);
475 }
476 }
477
478 /// <summary>
479 /// Classifieds delete.
480 /// </summary>
481 /// <param name='queryClassifiedID'>
482 /// Query classified I.
483 /// </param>
484 /// <param name='remoteClient'>
485 /// Remote client.
486 /// </param>
487 public void ClassifiedDelete(UUID queryClassifiedID, IClientAPI remoteClient)
488 {
489 string serverURI = string.Empty;
490 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
491
492 UUID classifiedId;
493 OSDMap parameters= new OSDMap();
494 UUID.TryParse(queryClassifiedID.ToString(), out classifiedId);
495 parameters.Add("classifiedId", OSD.FromUUID(classifiedId));
496 OSD Params = (OSD)parameters;
497 if(!JsonRpcRequest(ref Params, "classified_delete", serverURI, UUID.Random().ToString()))
498 {
499 remoteClient.SendAgentAlertMessage(
500 "Error classified delete", false);
501 }
502
503 parameters = (OSDMap)Params;
504 }
505 #endregion Classified
506
507 #region Picks
508 /// <summary>
509 /// Handles the avatar picks request.
510 /// </summary>
511 /// <param name='sender'>
512 /// Sender.
513 /// </param>
514 /// <param name='method'>
515 /// Method.
516 /// </param>
517 /// <param name='args'>
518 /// Arguments.
519 /// </param>
520 public void PicksRequest(Object sender, string method, List<String> args)
521 {
522 if (!(sender is IClientAPI))
523 return;
524
525 IClientAPI remoteClient = (IClientAPI)sender;
526
527 UUID targetId;
528 UUID.TryParse(args[0], out targetId);
529
530 // Can't handle NPC yet...
531 ScenePresence p = FindPresence(targetId);
532
533 if (null != p)
534 {
535 if (p.PresenceType == PresenceType.Npc)
536 return;
537 }
538
539 string serverURI = string.Empty;
540 bool foreign = GetUserProfileServerURI(targetId, out serverURI);
541
542 OSDMap parameters= new OSDMap();
543 parameters.Add("creatorId", OSD.FromUUID(targetId));
544 OSD Params = (OSD)parameters;
545 if(!JsonRpcRequest(ref Params, "avatarpicksrequest", serverURI, UUID.Random().ToString()))
546 {
547 remoteClient.SendAgentAlertMessage(
548 "Error requesting picks", false);
549 return;
550 }
551
552 parameters = (OSDMap)Params;
553
554 OSDArray list = (OSDArray)parameters["result"];
555
556 Dictionary<UUID, string> picks = new Dictionary<UUID, string>();
557
558 foreach(OSD map in list)
559 {
560 OSDMap m = (OSDMap)map;
561 UUID cid = m["pickuuid"].AsUUID();
562 string name = m["name"].AsString();
563
564 m_log.DebugFormat("[PROFILES]: PicksRequest {0}", name);
565
566 picks[cid] = name;
567 }
568 remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks);
569 }
570
571 /// <summary>
572 /// Handles the pick info request.
573 /// </summary>
574 /// <param name='sender'>
575 /// Sender.
576 /// </param>
577 /// <param name='method'>
578 /// Method.
579 /// </param>
580 /// <param name='args'>
581 /// Arguments.
582 /// </param>
583 public void PickInfoRequest(Object sender, string method, List<String> args)
584 {
585 if (!(sender is IClientAPI))
586 return;
587
588 UUID targetID;
589 UUID.TryParse(args[0], out targetID);
590 string serverURI = string.Empty;
591 bool foreign = GetUserProfileServerURI(targetID, out serverURI);
592 IClientAPI remoteClient = (IClientAPI)sender;
593
594 UserProfilePick pick = new UserProfilePick();
595 UUID.TryParse(args[0], out pick.CreatorId);
596 UUID.TryParse(args[1], out pick.PickId);
597
598
599 object Pick = (object)pick;
600 if(!JsonRpcRequest(ref Pick, "pickinforequest", serverURI, UUID.Random().ToString()))
601 {
602 remoteClient.SendAgentAlertMessage(
603 "Error selecting pick", false);
604 }
605 pick = (UserProfilePick) Pick;
606 if(pick.SnapshotId == UUID.Zero)
607 {
608 // In case of a new UserPick, the data may not be ready and we would send wrong data, skip it...
609 m_log.DebugFormat("[PROFILES]: PickInfoRequest: SnapshotID is {0}", UUID.Zero.ToString());
610 return;
611 }
612
613 Vector3 globalPos;
614 Vector3.TryParse(pick.GlobalPos,out globalPos);
615
616 m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString());
617
618 remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name,
619 pick.Desc,pick.SnapshotId,pick.User,pick.OriginalName,pick.SimName,
620 globalPos,pick.SortOrder,pick.Enabled);
621 }
622
623 /// <summary>
624 /// Updates the userpicks
625 /// </summary>
626 /// <param name='remoteClient'>
627 /// Remote client.
628 /// </param>
629 /// <param name='pickID'>
630 /// Pick I.
631 /// </param>
632 /// <param name='creatorID'>
633 /// the creator of the pick
634 /// </param>
635 /// <param name='topPick'>
636 /// Top pick.
637 /// </param>
638 /// <param name='name'>
639 /// Name.
640 /// </param>
641 /// <param name='desc'>
642 /// Desc.
643 /// </param>
644 /// <param name='snapshotID'>
645 /// Snapshot I.
646 /// </param>
647 /// <param name='sortOrder'>
648 /// Sort order.
649 /// </param>
650 /// <param name='enabled'>
651 /// Enabled.
652 /// </param>
653 public void PickInfoUpdate(IClientAPI remoteClient, UUID pickID, UUID creatorID, bool topPick, string name, string desc, UUID snapshotID, int sortOrder, bool enabled)
654 {
655
656 m_log.DebugFormat("[PROFILES]: Start PickInfoUpdate Name: {0} PickId: {1} SnapshotId: {2}", name, pickID.ToString(), snapshotID.ToString());
657 UserProfilePick pick = new UserProfilePick();
658 string serverURI = string.Empty;
659 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
660 ScenePresence p = FindPresence(remoteClient.AgentId);
661
662 Vector3 avaPos = p.AbsolutePosition;
663 // Getting the global position for the Avatar
664 Vector3 posGlobal = new Vector3(remoteClient.Scene.RegionInfo.RegionLocX*Constants.RegionSize + avaPos.X,
665 remoteClient.Scene.RegionInfo.RegionLocY*Constants.RegionSize + avaPos.Y,
666 avaPos.Z);
667
668 string landOwnerName = string.Empty;
669 ILandObject land = p.Scene.LandChannel.GetLandObject(avaPos.X, avaPos.Y);
670 if(land.LandData.IsGroupOwned)
671 {
672 IGroupsModule groupMod = p.Scene.RequestModuleInterface<IGroupsModule>();
673 UUID groupId = land.LandData.GroupID;
674 GroupRecord groupRecord = groupMod.GetGroupRecord(groupId);
675 landOwnerName = groupRecord.GroupName;
676 }
677 else
678 {
679 IUserAccountService accounts = p.Scene.RequestModuleInterface<IUserAccountService>();
680 UserAccount user = accounts.GetUserAccount(p.Scene.RegionInfo.ScopeID, land.LandData.OwnerID);
681 landOwnerName = user.Name;
682 }
683
684 pick.PickId = pickID;
685 pick.CreatorId = creatorID;
686 pick.TopPick = topPick;
687 pick.Name = name;
688 pick.Desc = desc;
689 pick.ParcelId = p.currentParcelUUID;
690 pick.SnapshotId = snapshotID;
691 pick.User = landOwnerName;
692 pick.SimName = remoteClient.Scene.RegionInfo.RegionName;
693 pick.GlobalPos = posGlobal.ToString();
694 pick.SortOrder = sortOrder;
695 pick.Enabled = enabled;
696
697 object Pick = (object)pick;
698 if(!JsonRpcRequest(ref Pick, "picks_update", serverURI, UUID.Random().ToString()))
699 {
700 remoteClient.SendAgentAlertMessage(
701 "Error updating pick", false);
702 }
703
704 m_log.DebugFormat("[PROFILES]: Finish PickInfoUpdate {0} {1}", pick.Name, pick.PickId.ToString());
705 }
706
707 /// <summary>
708 /// Delete a Pick
709 /// </summary>
710 /// <param name='remoteClient'>
711 /// Remote client.
712 /// </param>
713 /// <param name='queryPickID'>
714 /// Query pick I.
715 /// </param>
716 public void PickDelete(IClientAPI remoteClient, UUID queryPickID)
717 {
718 string serverURI = string.Empty;
719 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
720
721 OSDMap parameters= new OSDMap();
722 parameters.Add("pickId", OSD.FromUUID(queryPickID));
723 OSD Params = (OSD)parameters;
724 if(!JsonRpcRequest(ref Params, "picks_delete", serverURI, UUID.Random().ToString()))
725 {
726 remoteClient.SendAgentAlertMessage(
727 "Error picks delete", false);
728 }
729 }
730 #endregion Picks
731
732 #region Notes
733 /// <summary>
734 /// Handles the avatar notes request.
735 /// </summary>
736 /// <param name='sender'>
737 /// Sender.
738 /// </param>
739 /// <param name='method'>
740 /// Method.
741 /// </param>
742 /// <param name='args'>
743 /// Arguments.
744 /// </param>
745 public void NotesRequest(Object sender, string method, List<String> args)
746 {
747 UserProfileNotes note = new UserProfileNotes();
748
749 if (!(sender is IClientAPI))
750 return;
751
752 IClientAPI remoteClient = (IClientAPI)sender;
753 string serverURI = string.Empty;
754 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
755 note.TargetId = remoteClient.AgentId;
756 UUID.TryParse(args[0], out note.UserId);
757
758 object Note = (object)note;
759 if(!JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString()))
760 {
761 remoteClient.SendAgentAlertMessage(
762 "Error requesting note", false);
763 }
764 note = (UserProfileNotes) Note;
765
766 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
767 }
768
769 /// <summary>
770 /// Avatars the notes update.
771 /// </summary>
772 /// <param name='remoteClient'>
773 /// Remote client.
774 /// </param>
775 /// <param name='queryTargetID'>
776 /// Query target I.
777 /// </param>
778 /// <param name='queryNotes'>
779 /// Query notes.
780 /// </param>
781 public void NotesUpdate(IClientAPI remoteClient, UUID queryTargetID, string queryNotes)
782 {
783 UserProfileNotes note = new UserProfileNotes();
784
785 note.UserId = remoteClient.AgentId;
786 note.TargetId = queryTargetID;
787 note.Notes = queryNotes;
788
789 string serverURI = string.Empty;
790 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
791
792 object Note = note;
793 if(!JsonRpcRequest(ref Note, "avatar_notes_update", serverURI, UUID.Random().ToString()))
794 {
795 remoteClient.SendAgentAlertMessage(
796 "Error updating note", false);
797 }
798 }
799 #endregion Notes
800
801 #region Avatar Properties
802 /// <summary>
803 /// Update the avatars interests .
804 /// </summary>
805 /// <param name='remoteClient'>
806 /// Remote client.
807 /// </param>
808 /// <param name='wantmask'>
809 /// Wantmask.
810 /// </param>
811 /// <param name='wanttext'>
812 /// Wanttext.
813 /// </param>
814 /// <param name='skillsmask'>
815 /// Skillsmask.
816 /// </param>
817 /// <param name='skillstext'>
818 /// Skillstext.
819 /// </param>
820 /// <param name='languages'>
821 /// Languages.
822 /// </param>
823 public void AvatarInterestsUpdate(IClientAPI remoteClient, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages)
824 {
825 UserProfileProperties prop = new UserProfileProperties();
826
827 prop.UserId = remoteClient.AgentId;
828 prop.WantToMask = (int)wantmask;
829 prop.WantToText = wanttext;
830 prop.SkillsMask = (int)skillsmask;
831 prop.SkillsText = skillstext;
832 prop.Language = languages;
833
834 string serverURI = string.Empty;
835 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
836
837 object Param = prop;
838 if(!JsonRpcRequest(ref Param, "avatar_interests_update", serverURI, UUID.Random().ToString()))
839 {
840 remoteClient.SendAgentAlertMessage(
841 "Error updating interests", false);
842 }
843 }
844
845 public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
846 {
847 if ( String.IsNullOrEmpty(avatarID.ToString()) || String.IsNullOrEmpty(remoteClient.AgentId.ToString()))
848 {
849 // Looking for a reason that some viewers are sending null Id's
850 m_log.DebugFormat("[PROFILES]: This should not happen remoteClient.AgentId {0} - avatarID {1}", remoteClient.AgentId, avatarID);
851 return;
852 }
853
854 // Can't handle NPC yet...
855 ScenePresence p = FindPresence(avatarID);
856
857 if (null != p)
858 {
859 if (p.PresenceType == PresenceType.Npc)
860 return;
861 }
862
863 string serverURI = string.Empty;
864 bool foreign = GetUserProfileServerURI(avatarID, out serverURI);
865
866 UserAccount account = null;
867 Dictionary<string,object> userInfo;
868
869 if (!foreign)
870 {
871 account = Scene.UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, avatarID);
872 }
873 else
874 {
875 userInfo = new Dictionary<string, object>();
876 }
877
878 Byte[] charterMember = new Byte[1];
879 string born = String.Empty;
880 uint flags = 0x00;
881
882 if (null != account)
883 {
884 if (account.UserTitle == "")
885 {
886 charterMember[0] = (Byte)((account.UserFlags & 0xf00) >> 8);
887 }
888 else
889 {
890 charterMember = Utils.StringToBytes(account.UserTitle);
891 }
892
893 born = Util.ToDateTime(account.Created).ToString(
894 "M/d/yyyy", CultureInfo.InvariantCulture);
895 flags = (uint)(account.UserFlags & 0xff);
896 }
897 else
898 {
899 if (GetUserAccountData(avatarID, out userInfo) == true)
900 {
901 if ((string)userInfo["user_title"] == "")
902 {
903 charterMember[0] = (Byte)(((Byte)userInfo["user_flags"] & 0xf00) >> 8);
904 }
905 else
906 {
907 charterMember = Utils.StringToBytes((string)userInfo["user_title"]);
908 }
909
910 int val_born = (int)userInfo["user_created"];
911 born = Util.ToDateTime(val_born).ToString(
912 "M/d/yyyy", CultureInfo.InvariantCulture);
913
914 // picky, picky
915 int val_flags = (int)userInfo["user_flags"];
916 flags = (uint)(val_flags & 0xff);
917 }
918 }
919
920 UserProfileProperties props = new UserProfileProperties();
921 string result = string.Empty;
922
923 props.UserId = avatarID;
924 GetProfileData(ref props, out result);
925
926 remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, charterMember , props.FirstLifeText, flags,
927 props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
928
929
930 remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, (uint)props.SkillsMask,
931 props.SkillsText, props.Language);
932 }
933
934 /// <summary>
935 /// Updates the avatar properties.
936 /// </summary>
937 /// <param name='remoteClient'>
938 /// Remote client.
939 /// </param>
940 /// <param name='newProfile'>
941 /// New profile.
942 /// </param>
943 public void AvatarPropertiesUpdate(IClientAPI remoteClient, UserProfileData newProfile)
944 {
945 if (remoteClient.AgentId == newProfile.ID)
946 {
947 UserProfileProperties prop = new UserProfileProperties();
948
949 prop.UserId = remoteClient.AgentId;
950 prop.WebUrl = newProfile.ProfileUrl;
951 prop.ImageId = newProfile.Image;
952 prop.AboutText = newProfile.AboutText;
953 prop.FirstLifeImageId = newProfile.FirstLifeImage;
954 prop.FirstLifeText = newProfile.FirstLifeAboutText;
955
956 string serverURI = string.Empty;
957 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
958
959 object Prop = prop;
960
961 if(!JsonRpcRequest(ref Prop, "avatar_properties_update", serverURI, UUID.Random().ToString()))
962 {
963 remoteClient.SendAgentAlertMessage(
964 "Error updating properties", false);
965 }
966
967 RequestAvatarProperties(remoteClient, newProfile.ID);
968 }
969 }
970
971
972 /// <summary>
973 /// Gets the profile data.
974 /// </summary>
975 /// <returns>
976 /// The profile data.
977 /// </returns>
978 /// <param name='userID'>
979 /// User I.
980 /// </param>
981 bool GetProfileData(ref UserProfileProperties properties, out string message)
982 {
983 // Can't handle NPC yet...
984 ScenePresence p = FindPresence(properties.UserId);
985
986 if (null != p)
987 {
988 if (p.PresenceType == PresenceType.Npc)
989 {
990 message = "Id points to NPC";
991 return false;
992 }
993 }
994
995 string serverURI = string.Empty;
996 bool foreign = GetUserProfileServerURI(properties.UserId, out serverURI);
997
998 // This is checking a friend on the home grid
999 // Not HG friend
1000 if ( String.IsNullOrEmpty(serverURI))
1001 {
1002 message = "No Presence - foreign friend";
1003 return false;
1004 }
1005
1006 object Prop = (object)properties;
1007 JsonRpcRequest(ref Prop, "avatar_properties_request", serverURI, UUID.Random().ToString());
1008 properties = (UserProfileProperties)Prop;
1009
1010 message = "Success";
1011 return true;
1012 }
1013 #endregion Avatar Properties
1014
1015 #region Utils
1016 bool GetImageAssets(UUID avatarId)
1017 {
1018 string profileServerURI = string.Empty;
1019 string assetServerURI = string.Empty;
1020
1021 bool foreign = GetUserProfileServerURI(avatarId, out profileServerURI);
1022
1023 if(!foreign)
1024 return true;
1025
1026 assetServerURI = UserManagementModule.GetUserServerURL(avatarId, "AssetServerURI");
1027
1028 OSDMap parameters= new OSDMap();
1029 parameters.Add("avatarId", OSD.FromUUID(avatarId));
1030 OSD Params = (OSD)parameters;
1031 if(!JsonRpcRequest(ref Params, "image_assets_request", profileServerURI, UUID.Random().ToString()))
1032 {
1033 // Error Handling here!
1034 // if(parameters.ContainsKey("message")
1035 return false;
1036 }
1037
1038 parameters = (OSDMap)Params;
1039
1040 OSDArray list = (OSDArray)parameters["result"];
1041
1042 foreach(OSD asset in list)
1043 {
1044 OSDString assetId = (OSDString)asset;
1045
1046 Scene.AssetService.Get(string.Format("{0}/{1}",assetServerURI, assetId.AsString()), this,
1047 delegate (string assetID, Object s, AssetBase a)
1048 {
1049 // m_log.DebugFormat("[PROFILES]: Getting Image Assets {0}", assetID);
1050 return;
1051 });
1052 }
1053 return true;
1054 }
1055
1056 /// <summary>
1057 /// Gets the user account data.
1058 /// </summary>
1059 /// <returns>
1060 /// The user profile data.
1061 /// </returns>
1062 /// <param name='userID'>
1063 /// If set to <c>true</c> user I.
1064 /// </param>
1065 /// <param name='userInfo'>
1066 /// If set to <c>true</c> user info.
1067 /// </param>
1068 bool GetUserAccountData(UUID userID, out Dictionary<string, object> userInfo)
1069 {
1070 Dictionary<string,object> info = new Dictionary<string, object>();
1071
1072 if (UserManagementModule.IsLocalGridUser(userID))
1073 {
1074 // Is local
1075 IUserAccountService uas = Scene.UserAccountService;
1076 UserAccount account = uas.GetUserAccount(Scene.RegionInfo.ScopeID, userID);
1077
1078 info["user_flags"] = account.UserFlags;
1079 info["user_created"] = account.Created;
1080
1081 if (!String.IsNullOrEmpty(account.UserTitle))
1082 info["user_title"] = account.UserTitle;
1083 else
1084 info["user_title"] = "";
1085
1086 userInfo = info;
1087
1088 return false;
1089 }
1090 else
1091 {
1092 // Is Foreign
1093 string home_url = UserManagementModule.GetUserServerURL(userID, "HomeURI");
1094
1095 if (String.IsNullOrEmpty(home_url))
1096 {
1097 info["user_flags"] = 0;
1098 info["user_created"] = 0;
1099 info["user_title"] = "Unavailable";
1100
1101 userInfo = info;
1102 return true;
1103 }
1104
1105 UserAgentServiceConnector uConn = new UserAgentServiceConnector(home_url);
1106
1107 Dictionary<string, object> account = uConn.GetUserInfo(userID);
1108
1109 if (account.Count > 0)
1110 {
1111 if (account.ContainsKey("user_flags"))
1112 info["user_flags"] = account["user_flags"];
1113 else
1114 info["user_flags"] = "";
1115
1116 if (account.ContainsKey("user_created"))
1117 info["user_created"] = account["user_created"];
1118 else
1119 info["user_created"] = "";
1120
1121 info["user_title"] = "HG Visitor";
1122 }
1123 else
1124 {
1125 info["user_flags"] = 0;
1126 info["user_created"] = 0;
1127 info["user_title"] = "HG Visitor";
1128 }
1129 userInfo = info;
1130 return true;
1131 }
1132 }
1133
1134 /// <summary>
1135 /// Gets the user profile server UR.
1136 /// </summary>
1137 /// <returns>
1138 /// The user profile server UR.
1139 /// </returns>
1140 /// <param name='userID'>
1141 /// If set to <c>true</c> user I.
1142 /// </param>
1143 /// <param name='serverURI'>
1144 /// If set to <c>true</c> server UR.
1145 /// </param>
1146 bool GetUserProfileServerURI(UUID userID, out string serverURI)
1147 {
1148 bool local;
1149 local = UserManagementModule.IsLocalGridUser(userID);
1150
1151 if (!local)
1152 {
1153 serverURI = UserManagementModule.GetUserServerURL(userID, "ProfileServerURI");
1154 // Is Foreign
1155 return true;
1156 }
1157 else
1158 {
1159 serverURI = ProfileServerUri;
1160 // Is local
1161 return false;
1162 }
1163 }
1164
1165 /// <summary>
1166 /// Finds the presence.
1167 /// </summary>
1168 /// <returns>
1169 /// The presence.
1170 /// </returns>
1171 /// <param name='clientID'>
1172 /// Client I.
1173 /// </param>
1174 ScenePresence FindPresence(UUID clientID)
1175 {
1176 ScenePresence p;
1177
1178 p = Scene.GetScenePresence(clientID);
1179 if (p != null && !p.IsChildAgent)
1180 return p;
1181
1182 return null;
1183 }
1184 #endregion Util
1185
1186 #region Web Util
1187 /// <summary>
1188 /// Sends json-rpc request with a serializable type.
1189 /// </summary>
1190 /// <returns>
1191 /// OSD Map.
1192 /// </returns>
1193 /// <param name='parameters'>
1194 /// Serializable type .
1195 /// </param>
1196 /// <param name='method'>
1197 /// Json-rpc method to call.
1198 /// </param>
1199 /// <param name='uri'>
1200 /// URI of json-rpc service.
1201 /// </param>
1202 /// <param name='jsonId'>
1203 /// Id for our call.
1204 /// </param>
1205 bool JsonRpcRequest(ref object parameters, string method, string uri, string jsonId)
1206 {
1207 if (jsonId == null)
1208 throw new ArgumentNullException ("jsonId");
1209 if (uri == null)
1210 throw new ArgumentNullException ("uri");
1211 if (method == null)
1212 throw new ArgumentNullException ("method");
1213 if (parameters == null)
1214 throw new ArgumentNullException ("parameters");
1215
1216 // Prep our payload
1217 OSDMap json = new OSDMap();
1218
1219 json.Add("jsonrpc", OSD.FromString("2.0"));
1220 json.Add("id", OSD.FromString(jsonId));
1221 json.Add("method", OSD.FromString(method));
1222 // Experiment
1223 json.Add("params", OSD.SerializeMembers(parameters));
1224
1225 string jsonRequestData = OSDParser.SerializeJsonString(json);
1226 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1227
1228 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1229 // webRequest.Credentials = new NetworkCredential(rpcUser, rpcPass);
1230 webRequest.ContentType = "application/json-rpc";
1231 webRequest.Method = "POST";
1232
1233 Stream dataStream = webRequest.GetRequestStream();
1234 dataStream.Write(content, 0, content.Length);
1235 dataStream.Close();
1236
1237 WebResponse webResponse = null;
1238 try
1239 {
1240 webResponse = webRequest.GetResponse();
1241 }
1242 catch (WebException e)
1243 {
1244 Console.WriteLine("Web Error" + e.Message);
1245 Console.WriteLine ("Please check input");
1246 return false;
1247 }
1248
1249 byte[] buf = new byte[8192];
1250 Stream rstream = webResponse.GetResponseStream();
1251 OSDMap mret = (OSDMap)OSDParser.DeserializeJson(rstream);
1252
1253 if(mret.ContainsKey("error"))
1254 return false;
1255
1256 // get params...
1257 OSD.DeserializeMembers(ref parameters, (OSDMap) mret["result"]);
1258 return true;
1259 }
1260
1261 /// <summary>
1262 /// Sends json-rpc request with OSD parameter.
1263 /// </summary>
1264 /// <returns>
1265 /// The rpc request.
1266 /// </returns>
1267 /// <param name='data'>
1268 /// data - incoming as parameters, outgong as result/error
1269 /// </param>
1270 /// <param name='method'>
1271 /// Json-rpc method to call.
1272 /// </param>
1273 /// <param name='uri'>
1274 /// URI of json-rpc service.
1275 /// </param>
1276 /// <param name='jsonId'>
1277 /// If set to <c>true</c> json identifier.
1278 /// </param>
1279 bool JsonRpcRequest(ref OSD data, string method, string uri, string jsonId)
1280 {
1281 OSDMap map = new OSDMap();
1282
1283 map["jsonrpc"] = "2.0";
1284 if(string.IsNullOrEmpty(jsonId))
1285 map["id"] = UUID.Random().ToString();
1286 else
1287 map["id"] = jsonId;
1288
1289 map["method"] = method;
1290 map["params"] = data;
1291
1292 string jsonRequestData = OSDParser.SerializeJsonString(map);
1293 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1294
1295 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1296 webRequest.ContentType = "application/json-rpc";
1297 webRequest.Method = "POST";
1298
1299 Stream dataStream = webRequest.GetRequestStream();
1300 dataStream.Write(content, 0, content.Length);
1301 dataStream.Close();
1302
1303 WebResponse webResponse = null;
1304 try
1305 {
1306 webResponse = webRequest.GetResponse();
1307 }
1308 catch (WebException e)
1309 {
1310 Console.WriteLine("Web Error" + e.Message);
1311 Console.WriteLine ("Please check input");
1312 return false;
1313 }
1314
1315 byte[] buf = new byte[8192];
1316 Stream rstream = webResponse.GetResponseStream();
1317
1318 OSDMap response = new OSDMap();
1319 response = (OSDMap)OSDParser.DeserializeJson(rstream);
1320 if(response.ContainsKey("error"))
1321 {
1322 data = response["error"];
1323 return false;
1324 }
1325
1326 data = response;
1327
1328 return true;
1329 }
1330 #endregion Web Util
1331 }
1332}