aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Capabilities/Handlers
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Capabilities/Handlers')
-rw-r--r--OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs299
-rw-r--r--OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs76
2 files changed, 375 insertions, 0 deletions
diff --git a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs
new file mode 100644
index 0000000..6fd7946
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs
@@ -0,0 +1,299 @@
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;
30using System.Collections.Generic;
31using System.Reflection;
32using log4net;
33using Nini.Config;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36using OpenSim.Framework;
37using OpenSim.Framework.Capabilities;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Framework.Servers.HttpServer;
40using OpenSim.Services.Interfaces;
41using Caps = OpenSim.Framework.Capabilities.Caps;
42
43namespace OpenSim.Capabilities.Handlers
44{
45
46 public class WebFetchInvDescHandler
47 {
48 private static readonly ILog m_log =
49 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private IInventoryService m_InventoryService;
52 private ILibraryService m_LibraryService;
53 private object m_fetchLock = new Object();
54
55 public WebFetchInvDescHandler(IInventoryService invService, ILibraryService libService)
56 {
57 m_InventoryService = invService;
58 m_LibraryService = libService;
59 }
60
61 public string FetchInventoryDescendentsRequest(string request, string path, string param, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
62 {
63 // nasty temporary hack here, the linden client falsely
64 // identifies the uuid 00000000-0000-0000-0000-000000000000
65 // as a string which breaks us
66 //
67 // correctly mark it as a uuid
68 //
69 request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
70
71 // another hack <integer>1</integer> results in a
72 // System.ArgumentException: Object type System.Int32 cannot
73 // be converted to target type: System.Boolean
74 //
75 request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
76 request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
77
78 Hashtable hash = new Hashtable();
79 try
80 {
81 hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
82 }
83 catch (LLSD.LLSDParseException pe)
84 {
85 m_log.Error("[AGENT INVENTORY]: Fetch error: " + pe.Message);
86 m_log.Error("Request: " + request.ToString());
87 }
88
89 ArrayList foldersrequested = (ArrayList)hash["folders"];
90
91 string response = "";
92 lock (m_fetchLock)
93 {
94 for (int i = 0; i < foldersrequested.Count; i++)
95 {
96 string inventoryitemstr = "";
97 Hashtable inventoryhash = (Hashtable)foldersrequested[i];
98
99 LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
100
101 try
102 {
103 LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
104 }
105 catch (Exception e)
106 {
107 m_log.Debug("[CAPS]: caught exception doing OSD deserialize" + e);
108 }
109 LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
110
111 inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
112 inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
113 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
114
115 response += inventoryitemstr;
116 }
117
118
119 if (response.Length == 0)
120 {
121 // Ter-guess: If requests fail a lot, the client seems to stop requesting descendants.
122 // Therefore, I'm concluding that the client only has so many threads available to do requests
123 // and when a thread stalls.. is stays stalled.
124 // Therefore we need to return something valid
125 response = "<llsd><map><key>folders</key><array /></map></llsd>";
126 }
127 else
128 {
129 response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
130 }
131
132 //m_log.DebugFormat("[CAPS]: Replying to CAPS fetch inventory request with following xml");
133 //m_log.Debug("[CAPS] "+response);
134
135 }
136 return response;
137 }
138
139 /// <summary>
140 /// Construct an LLSD reply packet to a CAPS inventory request
141 /// </summary>
142 /// <param name="invFetch"></param>
143 /// <returns></returns>
144 private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch)
145 {
146 LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
147 LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
148 contents.agent_id = invFetch.owner_id;
149 contents.owner_id = invFetch.owner_id;
150 contents.folder_id = invFetch.folder_id;
151
152 reply.folders.Array.Add(contents);
153 InventoryCollection inv = new InventoryCollection();
154 inv.Folders = new List<InventoryFolderBase>();
155 inv.Items = new List<InventoryItemBase>();
156 int version = 0;
157
158 inv = Fetch(invFetch.owner_id, invFetch.folder_id, invFetch.owner_id, invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version);
159
160 if (inv.Folders != null)
161 {
162 foreach (InventoryFolderBase invFolder in inv.Folders)
163 {
164 contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
165 }
166 }
167
168 if (inv.Items != null)
169 {
170 foreach (InventoryItemBase invItem in inv.Items)
171 {
172 contents.items.Array.Add(ConvertInventoryItem(invItem));
173 }
174 }
175
176 contents.descendents = contents.items.Array.Count + contents.categories.Array.Count;
177 contents.version = version;
178
179 return reply;
180 }
181
182 public InventoryCollection Fetch(UUID agentID, UUID folderID, UUID ownerID,
183 bool fetchFolders, bool fetchItems, int sortOrder, out int version)
184 {
185 m_log.DebugFormat(
186 "[WEBFETCHINVENTORYDESCENDANTS]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
187 fetchFolders, fetchItems, folderID, agentID);
188
189 version = 0;
190 InventoryFolderImpl fold;
191 if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
192 if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null)
193 {
194 InventoryCollection ret = new InventoryCollection();
195 ret.Folders = new List<InventoryFolderBase>();
196 ret.Items = fold.RequestListOfItems();
197
198 return ret;
199 }
200
201 InventoryCollection contents = new InventoryCollection();
202
203 if (folderID != UUID.Zero)
204 {
205 contents = m_InventoryService.GetFolderContent(agentID, folderID);
206 InventoryFolderBase containingFolder = new InventoryFolderBase();
207 containingFolder.ID = folderID;
208 containingFolder.Owner = agentID;
209 containingFolder = m_InventoryService.GetFolder(containingFolder);
210 if (containingFolder != null)
211 version = containingFolder.Version;
212 }
213 else
214 {
215 // Lost itemsm don't really need a version
216 version = 1;
217 }
218
219 return contents;
220
221 }
222 /// <summary>
223 /// Convert an internal inventory folder object into an LLSD object.
224 /// </summary>
225 /// <param name="invFolder"></param>
226 /// <returns></returns>
227 private LLSDInventoryFolder ConvertInventoryFolder(InventoryFolderBase invFolder)
228 {
229 LLSDInventoryFolder llsdFolder = new LLSDInventoryFolder();
230 llsdFolder.folder_id = invFolder.ID;
231 llsdFolder.parent_id = invFolder.ParentID;
232 llsdFolder.name = invFolder.Name;
233 if (invFolder.Type < 0 || invFolder.Type >= TaskInventoryItem.Types.Length)
234 llsdFolder.type = "-1";
235 else
236 llsdFolder.type = TaskInventoryItem.Types[invFolder.Type];
237 llsdFolder.preferred_type = "-1";
238
239 return llsdFolder;
240 }
241
242 /// <summary>
243 /// Convert an internal inventory item object into an LLSD object.
244 /// </summary>
245 /// <param name="invItem"></param>
246 /// <returns></returns>
247 private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem)
248 {
249 LLSDInventoryItem llsdItem = new LLSDInventoryItem();
250 llsdItem.asset_id = invItem.AssetID;
251 llsdItem.created_at = invItem.CreationDate;
252 llsdItem.desc = invItem.Description;
253 llsdItem.flags = (int)invItem.Flags;
254 llsdItem.item_id = invItem.ID;
255 llsdItem.name = invItem.Name;
256 llsdItem.parent_id = invItem.Folder;
257 try
258 {
259 // TODO reevaluate after upgrade to libomv >= r2566. Probably should use UtilsConversions.
260 llsdItem.type = TaskInventoryItem.Types[invItem.AssetType];
261 llsdItem.inv_type = TaskInventoryItem.InvTypes[invItem.InvType];
262 }
263 catch (Exception e)
264 {
265 m_log.ErrorFormat("[CAPS]: Problem setting asset {0} inventory {1} types while converting inventory item {2}: {3}", invItem.AssetType, invItem.InvType, invItem.Name, e.Message);
266 }
267 llsdItem.permissions = new LLSDPermissions();
268 llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
269 llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions;
270 llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions;
271 llsdItem.permissions.group_id = invItem.GroupID;
272 llsdItem.permissions.group_mask = (int)invItem.GroupPermissions;
273 llsdItem.permissions.is_owner_group = invItem.GroupOwned;
274 llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions;
275 llsdItem.permissions.owner_id = invItem.Owner;
276 llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
277 llsdItem.sale_info = new LLSDSaleInfo();
278 llsdItem.sale_info.sale_price = invItem.SalePrice;
279 switch (invItem.SaleType)
280 {
281 default:
282 llsdItem.sale_info.sale_type = "not";
283 break;
284 case 1:
285 llsdItem.sale_info.sale_type = "original";
286 break;
287 case 2:
288 llsdItem.sale_info.sale_type = "copy";
289 break;
290 case 3:
291 llsdItem.sale_info.sale_type = "contents";
292 break;
293 }
294
295 return llsdItem;
296 }
297
298 }
299}
diff --git a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs
new file mode 100644
index 0000000..92eeb14
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs
@@ -0,0 +1,76 @@
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 Nini.Config;
30using OpenSim.Server.Base;
31using OpenSim.Services.Interfaces;
32using OpenSim.Framework.Servers.HttpServer;
33using OpenSim.Server.Handlers.Base;
34using OpenMetaverse;
35
36namespace OpenSim.Capabilities.Handlers
37{
38 public class WebFetchInvDescServerConnector : ServiceConnector
39 {
40 private IInventoryService m_InventoryService;
41 private ILibraryService m_LibraryService;
42 private string m_ConfigName = "CapsService";
43
44 public WebFetchInvDescServerConnector(IConfigSource config, IHttpServer server, string configName) :
45 base(config, server, configName)
46 {
47 if (configName != String.Empty)
48 m_ConfigName = configName;
49
50 IConfig serverConfig = config.Configs[m_ConfigName];
51 if (serverConfig == null)
52 throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
53
54 string invService = serverConfig.GetString("InventoryService", String.Empty);
55
56 if (invService == String.Empty)
57 throw new Exception("No InventoryService in config file");
58
59 Object[] args = new Object[] { config };
60 m_InventoryService =
61 ServerUtils.LoadPlugin<IInventoryService>(invService, args);
62
63 if (m_InventoryService == null)
64 throw new Exception(String.Format("Failed to load InventoryService from {0}; config is {1}", invService, m_ConfigName));
65
66 string libService = serverConfig.GetString("LibraryService", String.Empty);
67 m_LibraryService =
68 ServerUtils.LoadPlugin<ILibraryService>(libService, args);
69
70 WebFetchInvDescHandler webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
71 IRequestHandler reqHandler = new RestStreamHandler("POST", "/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/, webFetchHandler.FetchInventoryDescendentsRequest);
72 server.AddStreamHandler(reqHandler);
73 }
74
75 }
76}