aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Capabilities
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Capabilities')
-rw-r--r--OpenSim/Capabilities/Caps.cs7
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs848
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs (renamed from OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs)8
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs (renamed from OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs)41
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventory2HandlerTests.cs170
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs292
-rw-r--r--OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs120
-rw-r--r--OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesServerConnector.cs (renamed from OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2ServerConnector.cs)32
-rw-r--r--OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs187
-rw-r--r--OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs29
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs7
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs4
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs3
-rw-r--r--OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Capabilities/LLSD.cs29
15 files changed, 1679 insertions, 100 deletions
diff --git a/OpenSim/Capabilities/Caps.cs b/OpenSim/Capabilities/Caps.cs
index b35e6b4..3efab8e 100644
--- a/OpenSim/Capabilities/Caps.cs
+++ b/OpenSim/Capabilities/Caps.cs
@@ -51,8 +51,7 @@ namespace OpenSim.Framework.Capabilities
51 51
52 public class Caps 52 public class Caps
53 { 53 {
54// private static readonly ILog m_log = 54// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56 55
57 private string m_httpListenerHostName; 56 private string m_httpListenerHostName;
58 private uint m_httpListenPort; 57 private uint m_httpListenPort;
@@ -155,6 +154,10 @@ namespace OpenSim.Framework.Capabilities
155 154
156 public void RegisterPollHandler(string capName, PollServiceEventArgs pollServiceHandler) 155 public void RegisterPollHandler(string capName, PollServiceEventArgs pollServiceHandler)
157 { 156 {
157// m_log.DebugFormat(
158// "[CAPS]: Registering handler with name {0}, url {1} for {2}",
159// capName, pollServiceHandler.Url, m_agentID, m_regionName);
160
158 m_pollServiceHandlers.Add(capName, pollServiceHandler); 161 m_pollServiceHandlers.Add(capName, pollServiceHandler);
159 162
160 m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler.Url, pollServiceHandler); 163 m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler.Url, pollServiceHandler);
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs
new file mode 100644
index 0000000..7197049
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs
@@ -0,0 +1,848 @@
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.Linq;
32using System.Reflection;
33using log4net;
34using Nini.Config;
35using OpenMetaverse;
36using OpenMetaverse.StructuredData;
37using OpenSim.Framework;
38using OpenSim.Framework.Capabilities;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Services.Interfaces;
42using Caps = OpenSim.Framework.Capabilities.Caps;
43
44namespace OpenSim.Capabilities.Handlers
45{
46 public class FetchInvDescHandler
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 IScene m_Scene;
54// private object m_fetchLock = new Object();
55
56 public FetchInvDescHandler(IInventoryService invService, ILibraryService libService, IScene s)
57 {
58 m_InventoryService = invService;
59 m_LibraryService = libService;
60 m_Scene = s;
61 }
62
63
64 public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
65 {
66 //m_log.DebugFormat("[XXX]: FetchInventoryDescendentsRequest in {0}, {1}", (m_Scene == null) ? "none" : m_Scene.Name, request);
67
68 // nasty temporary hack here, the linden client falsely
69 // identifies the uuid 00000000-0000-0000-0000-000000000000
70 // as a string which breaks us
71 //
72 // correctly mark it as a uuid
73 //
74 request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
75
76 // another hack <integer>1</integer> results in a
77 // System.ArgumentException: Object type System.Int32 cannot
78 // be converted to target type: System.Boolean
79 //
80 request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
81 request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
82
83 Hashtable hash = new Hashtable();
84 try
85 {
86 hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
87 }
88 catch (LLSD.LLSDParseException e)
89 {
90 m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
91 m_log.Error("Request: " + request);
92 }
93
94 ArrayList foldersrequested = (ArrayList)hash["folders"];
95
96 string response = "";
97 string bad_folders_response = "";
98
99 List<LLSDFetchInventoryDescendents> folders = new List<LLSDFetchInventoryDescendents>();
100 for (int i = 0; i < foldersrequested.Count; i++)
101 {
102 Hashtable inventoryhash = (Hashtable)foldersrequested[i];
103
104 LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
105
106 try
107 {
108 LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
109 }
110 catch (Exception e)
111 {
112 m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
113 continue;
114 }
115
116 // Filter duplicate folder ids that bad viewers may send
117 if (folders.Find(f => f.folder_id == llsdRequest.folder_id) == null)
118 folders.Add(llsdRequest);
119
120 }
121
122 if (folders.Count > 0)
123 {
124 List<UUID> bad_folders = new List<UUID>();
125 List<InventoryCollectionWithDescendents> invcollSet = Fetch(folders, bad_folders);
126 //m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count);
127
128 if (invcollSet == null)
129 {
130 m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Multiple folder fetch failed. Trying old protocol.");
131#pragma warning disable 0612
132 return FetchInventoryDescendentsRequest(foldersrequested, httpRequest, httpResponse);
133#pragma warning restore 0612
134 }
135
136 string inventoryitemstr = string.Empty;
137 foreach (InventoryCollectionWithDescendents icoll in invcollSet)
138 {
139 LLSDInventoryDescendents reply = ToLLSD(icoll.Collection, icoll.Descendents);
140
141 inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
142 inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
143 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
144
145 response += inventoryitemstr;
146 }
147
148 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders));
149 foreach (UUID bad in bad_folders)
150 bad_folders_response += "<uuid>" + bad + "</uuid>";
151 }
152
153 if (response.Length == 0)
154 {
155 /* Viewers expect a bad_folders array when not available */
156 if (bad_folders_response.Length != 0)
157 {
158 response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
159 }
160 else
161 {
162 response = "<llsd><map><key>folders</key><array /></map></llsd>";
163 }
164 }
165 else
166 {
167 if (bad_folders_response.Length != 0)
168 {
169 response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
170 }
171 else
172 {
173 response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
174 }
175 }
176
177 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request for {0} folders. Item count {1}", folders.Count, item_count);
178 //m_log.Debug("[WEB FETCH INV DESC HANDLER] " + response);
179
180 return response;
181
182 }
183
184 /// <summary>
185 /// Construct an LLSD reply packet to a CAPS inventory request
186 /// </summary>
187 /// <param name="invFetch"></param>
188 /// <returns></returns>
189 private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch)
190 {
191 LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
192 LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
193 contents.agent_id = invFetch.owner_id;
194 contents.owner_id = invFetch.owner_id;
195 contents.folder_id = invFetch.folder_id;
196
197 reply.folders.Array.Add(contents);
198 InventoryCollection inv = new InventoryCollection();
199 inv.Folders = new List<InventoryFolderBase>();
200 inv.Items = new List<InventoryItemBase>();
201 int version = 0;
202 int descendents = 0;
203
204#pragma warning disable 0612
205 inv = Fetch(
206 invFetch.owner_id, invFetch.folder_id, invFetch.owner_id,
207 invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents);
208#pragma warning restore 0612
209
210 if (inv != null && inv.Folders != null)
211 {
212 foreach (InventoryFolderBase invFolder in inv.Folders)
213 {
214 contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
215 }
216
217 descendents += inv.Folders.Count;
218 }
219
220 if (inv != null && inv.Items != null)
221 {
222 foreach (InventoryItemBase invItem in inv.Items)
223 {
224 contents.items.Array.Add(ConvertInventoryItem(invItem));
225 }
226 }
227
228 contents.descendents = descendents;
229 contents.version = version;
230
231 //m_log.DebugFormat(
232 // "[WEB FETCH INV DESC HANDLER]: Replying to request for folder {0} (fetch items {1}, fetch folders {2}) with {3} items and {4} folders for agent {5}",
233 // invFetch.folder_id,
234 // invFetch.fetch_items,
235 // invFetch.fetch_folders,
236 // contents.items.Array.Count,
237 // contents.categories.Array.Count,
238 // invFetch.owner_id);
239
240 return reply;
241 }
242
243 private LLSDInventoryDescendents ToLLSD(InventoryCollection inv, int descendents)
244 {
245 LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
246 LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
247 contents.agent_id = inv.OwnerID;
248 contents.owner_id = inv.OwnerID;
249 contents.folder_id = inv.FolderID;
250
251 reply.folders.Array.Add(contents);
252
253 if (inv.Folders != null)
254 {
255 foreach (InventoryFolderBase invFolder in inv.Folders)
256 {
257 contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
258 }
259
260 descendents += inv.Folders.Count;
261 }
262
263 if (inv.Items != null)
264 {
265 foreach (InventoryItemBase invItem in inv.Items)
266 {
267 contents.items.Array.Add(ConvertInventoryItem(invItem));
268 }
269 }
270
271 contents.descendents = descendents;
272 contents.version = inv.Version;
273
274 return reply;
275 }
276 /// <summary>
277 /// Old style. Soon to be deprecated.
278 /// </summary>
279 /// <param name="request"></param>
280 /// <param name="httpRequest"></param>
281 /// <param name="httpResponse"></param>
282 /// <returns></returns>
283 [Obsolete]
284 private string FetchInventoryDescendentsRequest(ArrayList foldersrequested, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
285 {
286 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count);
287
288 string response = "";
289 string bad_folders_response = "";
290
291 for (int i = 0; i < foldersrequested.Count; i++)
292 {
293 string inventoryitemstr = "";
294 Hashtable inventoryhash = (Hashtable)foldersrequested[i];
295
296 LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
297
298 try
299 {
300 LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
301 }
302 catch (Exception e)
303 {
304 m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
305 }
306
307 LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
308
309 if (null == reply)
310 {
311 bad_folders_response += "<uuid>" + llsdRequest.folder_id.ToString() + "</uuid>";
312 }
313 else
314 {
315 inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
316 inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
317 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
318 }
319
320 response += inventoryitemstr;
321 }
322
323 if (response.Length == 0)
324 {
325 /* Viewers expect a bad_folders array when not available */
326 if (bad_folders_response.Length != 0)
327 {
328 response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
329 }
330 else
331 {
332 response = "<llsd><map><key>folders</key><array /></map></llsd>";
333 }
334 }
335 else
336 {
337 if (bad_folders_response.Length != 0)
338 {
339 response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
340 }
341 else
342 {
343 response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
344 }
345 }
346
347 // m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request");
348 //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);
349
350 return response;
351
352 // }
353 }
354
355 /// <summary>
356 /// Handle the caps inventory descendents fetch.
357 /// </summary>
358 /// <param name="agentID"></param>
359 /// <param name="folderID"></param>
360 /// <param name="ownerID"></param>
361 /// <param name="fetchFolders"></param>
362 /// <param name="fetchItems"></param>
363 /// <param name="sortOrder"></param>
364 /// <param name="version"></param>
365 /// <returns>An empty InventoryCollection if the inventory look up failed</returns>
366 [Obsolete]
367 private InventoryCollection Fetch(
368 UUID agentID, UUID folderID, UUID ownerID,
369 bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents)
370 {
371 //m_log.DebugFormat(
372 // "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
373 // fetchFolders, fetchItems, folderID, agentID);
374
375 // FIXME MAYBE: We're not handling sortOrder!
376
377 version = 0;
378 descendents = 0;
379
380 InventoryFolderImpl fold;
381 if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
382 {
383 if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null)
384 {
385 InventoryCollection ret = new InventoryCollection();
386 ret.Folders = new List<InventoryFolderBase>();
387 ret.Items = fold.RequestListOfItems();
388 descendents = ret.Folders.Count + ret.Items.Count;
389
390 return ret;
391 }
392 }
393
394 InventoryCollection contents = new InventoryCollection();
395
396 if (folderID != UUID.Zero)
397 {
398 InventoryCollection fetchedContents = m_InventoryService.GetFolderContent(agentID, folderID);
399
400 if (fetchedContents == null)
401 {
402 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID);
403 return contents;
404 }
405 contents = fetchedContents;
406 InventoryFolderBase containingFolder = new InventoryFolderBase();
407 containingFolder.ID = folderID;
408 containingFolder.Owner = agentID;
409 containingFolder = m_InventoryService.GetFolder(containingFolder);
410
411 if (containingFolder != null)
412 {
413 //m_log.DebugFormat(
414 // "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}",
415 // containingFolder.Name, containingFolder.ID, agentID);
416
417 version = containingFolder.Version;
418
419 if (fetchItems)
420 {
421 List<InventoryItemBase> itemsToReturn = contents.Items;
422 List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
423
424 // descendents must only include the links, not the linked items we add
425 descendents = originalItems.Count;
426
427 // Add target items for links in this folder before the links themselves.
428 foreach (InventoryItemBase item in originalItems)
429 {
430 if (item.AssetType == (int)AssetType.Link)
431 {
432 InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
433
434 // Take care of genuinely broken links where the target doesn't exist
435 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
436 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
437 // rather than having to keep track of every folder requested in the recursion.
438 if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
439 itemsToReturn.Insert(0, linkedItem);
440 }
441 }
442
443 // Now scan for folder links and insert the items they target and those links at the head of the return data
444 foreach (InventoryItemBase item in originalItems)
445 {
446 if (item.AssetType == (int)AssetType.LinkFolder)
447 {
448 InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID);
449 List<InventoryItemBase> links = linkedFolderContents.Items;
450
451 itemsToReturn.InsertRange(0, links);
452
453 foreach (InventoryItemBase link in linkedFolderContents.Items)
454 {
455 // Take care of genuinely broken links where the target doesn't exist
456 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
457 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
458 // rather than having to keep track of every folder requested in the recursion.
459 if (link != null)
460 {
461// m_log.DebugFormat(
462// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}",
463// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name);
464
465 InventoryItemBase linkedItem
466 = m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
467
468 if (linkedItem != null)
469 itemsToReturn.Insert(0, linkedItem);
470 }
471 }
472 }
473 }
474 }
475
476// foreach (InventoryItemBase item in contents.Items)
477// {
478// m_log.DebugFormat(
479// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}",
480// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID);
481// }
482
483 // =====
484
485//
486// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
487// {
488// m_log.DebugFormat(
489// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}",
490// linkedItem.Name, folderID, agentID);
491//
492// contents.Items.Add(linkedItem);
493// }
494//
495// // If the folder requested contains links, then we need to send those folders first, otherwise the links
496// // will be broken in the viewer.
497// HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>();
498// foreach (InventoryItemBase item in contents.Items)
499// {
500// if (item.AssetType == (int)AssetType.Link)
501// {
502// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
503//
504// // Take care of genuinely broken links where the target doesn't exist
505// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
506// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
507// // rather than having to keep track of every folder requested in the recursion.
508// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
509// {
510// // We don't need to send the folder if source and destination of the link are in the same
511// // folder.
512// if (linkedItem.Folder != containingFolder.ID)
513// linkedItemFolderIdsToSend.Add(linkedItem.Folder);
514// }
515// }
516// }
517//
518// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend)
519// {
520// m_log.DebugFormat(
521// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}",
522// linkedItemFolderId, folderID, agentID);
523//
524// int dummyVersion;
525// InventoryCollection linkedCollection
526// = Fetch(
527// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion);
528//
529// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId);
530// linkedFolder.Owner = agentID;
531// linkedFolder = m_InventoryService.GetFolder(linkedFolder);
532//
533//// contents.Folders.AddRange(linkedCollection.Folders);
534//
535// contents.Folders.Add(linkedFolder);
536// contents.Items.AddRange(linkedCollection.Items);
537// }
538// }
539 }
540 }
541 else
542 {
543 // Lost items don't really need a version
544 version = 1;
545 }
546
547 return contents;
548
549 }
550
551 private void AddLibraryFolders(List<LLSDFetchInventoryDescendents> fetchFolders, List<InventoryCollectionWithDescendents> result)
552 {
553 InventoryFolderImpl fold;
554 if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null)
555 {
556 List<LLSDFetchInventoryDescendents> libfolders = fetchFolders.FindAll(f => f.owner_id == m_LibraryService.LibraryRootFolder.Owner);
557 fetchFolders.RemoveAll(f => libfolders.Contains(f));
558
559 //m_log.DebugFormat("[XXX]: Found {0} library folders in request", libfolders.Count);
560
561 foreach (LLSDFetchInventoryDescendents f in libfolders)
562 {
563 if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null)
564 {
565 InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents();
566 ret.Collection = new InventoryCollection();
567 ret.Collection.Folders = new List<InventoryFolderBase>();
568 ret.Collection.Items = fold.RequestListOfItems();
569 ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner;
570 ret.Collection.FolderID = f.folder_id;
571 ret.Collection.Version = fold.Version;
572
573 ret.Descendents = ret.Collection.Items.Count;
574 result.Add(ret);
575
576 //m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID);
577 }
578 }
579 }
580 }
581
582 private List<InventoryCollectionWithDescendents> Fetch(List<LLSDFetchInventoryDescendents> fetchFolders, List<UUID> bad_folders)
583 {
584 //m_log.DebugFormat(
585 // "[WEB FETCH INV DESC HANDLER]: Fetching {0} folders for owner {1}", fetchFolders.Count, fetchFolders[0].owner_id);
586
587 // FIXME MAYBE: We're not handling sortOrder!
588
589 List<InventoryCollectionWithDescendents> result = new List<InventoryCollectionWithDescendents>();
590
591 AddLibraryFolders(fetchFolders, result);
592
593 // Filter folder Zero right here. Some viewers (Firestorm) send request for folder Zero, which doesn't make sense
594 // and can kill the sim (all root folders have parent_id Zero)
595 LLSDFetchInventoryDescendents zero = fetchFolders.Find(f => f.folder_id == UUID.Zero);
596 if (zero != null)
597 {
598 fetchFolders.Remove(zero);
599 BadFolder(zero, null, bad_folders);
600 }
601
602 if (fetchFolders.Count > 0)
603 {
604 UUID[] fids = new UUID[fetchFolders.Count];
605 int i = 0;
606 foreach (LLSDFetchInventoryDescendents f in fetchFolders)
607 fids[i++] = f.folder_id;
608
609 //m_log.DebugFormat("[XXX]: {0}", string.Join(",", fids));
610
611 InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(fetchFolders[0].owner_id, fids);
612
613 if (fetchedContents == null || (fetchedContents != null && fetchedContents.Length == 0))
614 {
615 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of multiple folders for user {0}", fetchFolders[0].owner_id);
616 foreach (LLSDFetchInventoryDescendents freq in fetchFolders)
617 BadFolder(freq, null, bad_folders);
618 return null;
619 }
620
621 i = 0;
622 // Do some post-processing. May need to fetch more from inv server for links
623 foreach (InventoryCollection contents in fetchedContents)
624 {
625 // Find the original request
626 LLSDFetchInventoryDescendents freq = fetchFolders[i++];
627
628 InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents();
629 coll.Collection = contents;
630
631 if (BadFolder(freq, contents, bad_folders))
632 continue;
633
634 // Next: link management
635 ProcessLinks(freq, coll);
636
637 result.Add(coll);
638 }
639 }
640
641 return result;
642 }
643
644 private bool BadFolder(LLSDFetchInventoryDescendents freq, InventoryCollection contents, List<UUID> bad_folders)
645 {
646 bool bad = false;
647 if (contents == null)
648 {
649 bad_folders.Add(freq.folder_id);
650 bad = true;
651 }
652
653 // The inventory server isn't sending FolderID in the collection...
654 // Must fetch it individually
655 else if (contents.FolderID == UUID.Zero)
656 {
657 InventoryFolderBase containingFolder = new InventoryFolderBase();
658 containingFolder.ID = freq.folder_id;
659 containingFolder.Owner = freq.owner_id;
660 containingFolder = m_InventoryService.GetFolder(containingFolder);
661
662 if (containingFolder != null)
663 {
664 contents.FolderID = containingFolder.ID;
665 contents.OwnerID = containingFolder.Owner;
666 contents.Version = containingFolder.Version;
667 }
668 else
669 {
670 // Was it really a request for folder Zero?
671 // This is an overkill, but Firestorm really asks for folder Zero.
672 // I'm leaving the code here for the time being, but commented.
673 if (freq.folder_id == UUID.Zero)
674 {
675 //coll.Collection.OwnerID = freq.owner_id;
676 //coll.Collection.FolderID = contents.FolderID;
677 //containingFolder = m_InventoryService.GetRootFolder(freq.owner_id);
678 //if (containingFolder != null)
679 //{
680 // m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Request for parent of folder {0}", containingFolder.ID);
681 // coll.Collection.Folders.Clear();
682 // coll.Collection.Folders.Add(containingFolder);
683 // if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null)
684 // {
685 // InventoryFolderBase lib = new InventoryFolderBase(m_LibraryService.LibraryRootFolder.ID, m_LibraryService.LibraryRootFolder.Owner);
686 // lib.Name = m_LibraryService.LibraryRootFolder.Name;
687 // lib.Type = m_LibraryService.LibraryRootFolder.Type;
688 // lib.Version = m_LibraryService.LibraryRootFolder.Version;
689 // coll.Collection.Folders.Add(lib);
690 // }
691 // coll.Collection.Items.Clear();
692 //}
693 }
694 else
695 {
696 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id);
697 bad_folders.Add(freq.folder_id);
698 }
699 bad = true;
700 }
701 }
702
703 return bad;
704 }
705
706 private void ProcessLinks(LLSDFetchInventoryDescendents freq, InventoryCollectionWithDescendents coll)
707 {
708 InventoryCollection contents = coll.Collection;
709
710 if (freq.fetch_items && contents.Items != null)
711 {
712 List<InventoryItemBase> itemsToReturn = contents.Items;
713
714 // descendents must only include the links, not the linked items we add
715 coll.Descendents = itemsToReturn.Count;
716
717 // Add target items for links in this folder before the links themselves.
718 List<UUID> itemIDs = new List<UUID>();
719 List<UUID> folderIDs = new List<UUID>();
720 foreach (InventoryItemBase item in itemsToReturn)
721 {
722 //m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType);
723 if (item.AssetType == (int)AssetType.Link)
724 itemIDs.Add(item.AssetID);
725
726 else if (item.AssetType == (int)AssetType.LinkFolder)
727 folderIDs.Add(item.AssetID);
728 }
729
730 //m_log.DebugFormat("[XXX]: folder {0} has {1} links and {2} linkfolders", contents.FolderID, itemIDs.Count, folderIDs.Count);
731
732 // Scan for folder links and insert the items they target and those links at the head of the return data
733 if (folderIDs.Count > 0)
734 {
735 InventoryCollection[] linkedFolders = m_InventoryService.GetMultipleFoldersContent(coll.Collection.OwnerID, folderIDs.ToArray());
736 foreach (InventoryCollection linkedFolderContents in linkedFolders)
737 {
738 if (linkedFolderContents == null)
739 continue;
740
741 List<InventoryItemBase> links = linkedFolderContents.Items;
742
743 itemsToReturn.InsertRange(0, links);
744
745 }
746 }
747
748 if (itemIDs.Count > 0)
749 {
750 InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray());
751 if (linked == null)
752 {
753 // OMG!!! One by one!!! This is fallback code, in case the backend isn't updated
754 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one.");
755 linked = new InventoryItemBase[itemIDs.Count];
756 int i = 0;
757 InventoryItemBase item = new InventoryItemBase();
758 item.Owner = freq.owner_id;
759 foreach (UUID id in itemIDs)
760 {
761 item.ID = id;
762 linked[i++] = m_InventoryService.GetItem(item);
763 }
764 }
765
766 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Processing folder {0}. Existing items:", freq.folder_id);
767 //foreach (InventoryItemBase item in itemsToReturn)
768 // m_log.DebugFormat("[XXX]: {0} {1} {2}", item.Name, item.AssetType, item.Folder);
769
770 if (linked != null)
771 {
772 foreach (InventoryItemBase linkedItem in linked)
773 {
774 // Take care of genuinely broken links where the target doesn't exist
775 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
776 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
777 // rather than having to keep track of every folder requested in the recursion.
778 if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
779 {
780 itemsToReturn.Insert(0, linkedItem);
781 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder);
782 }
783 }
784 }
785 }
786 }
787
788 }
789
790 /// <summary>
791 /// Convert an internal inventory folder object into an LLSD object.
792 /// </summary>
793 /// <param name="invFolder"></param>
794 /// <returns></returns>
795 private LLSDInventoryFolder ConvertInventoryFolder(InventoryFolderBase invFolder)
796 {
797 LLSDInventoryFolder llsdFolder = new LLSDInventoryFolder();
798 llsdFolder.folder_id = invFolder.ID;
799 llsdFolder.parent_id = invFolder.ParentID;
800 llsdFolder.name = invFolder.Name;
801 llsdFolder.type = invFolder.Type;
802 llsdFolder.preferred_type = -1;
803
804 return llsdFolder;
805 }
806
807 /// <summary>
808 /// Convert an internal inventory item object into an LLSD object.
809 /// </summary>
810 /// <param name="invItem"></param>
811 /// <returns></returns>
812 private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem)
813 {
814 LLSDInventoryItem llsdItem = new LLSDInventoryItem();
815 llsdItem.asset_id = invItem.AssetID;
816 llsdItem.created_at = invItem.CreationDate;
817 llsdItem.desc = invItem.Description;
818 llsdItem.flags = (int)invItem.Flags;
819 llsdItem.item_id = invItem.ID;
820 llsdItem.name = invItem.Name;
821 llsdItem.parent_id = invItem.Folder;
822 llsdItem.type = invItem.AssetType;
823 llsdItem.inv_type = invItem.InvType;
824
825 llsdItem.permissions = new LLSDPermissions();
826 llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
827 llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions;
828 llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions;
829 llsdItem.permissions.group_id = invItem.GroupID;
830 llsdItem.permissions.group_mask = (int)invItem.GroupPermissions;
831 llsdItem.permissions.is_owner_group = invItem.GroupOwned;
832 llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions;
833 llsdItem.permissions.owner_id = invItem.Owner;
834 llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
835 llsdItem.sale_info = new LLSDSaleInfo();
836 llsdItem.sale_info.sale_price = invItem.SalePrice;
837 llsdItem.sale_info.sale_type = invItem.SaleType;
838
839 return llsdItem;
840 }
841 }
842
843 class InventoryCollectionWithDescendents
844 {
845 public InventoryCollection Collection;
846 public int Descendents;
847 }
848} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs
index 5d86557..9dcfaa4 100644
--- a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs
@@ -35,13 +35,13 @@ using OpenMetaverse;
35 35
36namespace OpenSim.Capabilities.Handlers 36namespace OpenSim.Capabilities.Handlers
37{ 37{
38 public class WebFetchInvDescServerConnector : ServiceConnector 38 public class FetchInvDescServerConnector : ServiceConnector
39 { 39 {
40 private IInventoryService m_InventoryService; 40 private IInventoryService m_InventoryService;
41 private ILibraryService m_LibraryService; 41 private ILibraryService m_LibraryService;
42 private string m_ConfigName = "CapsService"; 42 private string m_ConfigName = "CapsService";
43 43
44 public WebFetchInvDescServerConnector(IConfigSource config, IHttpServer server, string configName) : 44 public FetchInvDescServerConnector(IConfigSource config, IHttpServer server, string configName) :
45 base(config, server, configName) 45 base(config, server, configName)
46 { 46 {
47 if (configName != String.Empty) 47 if (configName != String.Empty)
@@ -67,13 +67,13 @@ namespace OpenSim.Capabilities.Handlers
67 m_LibraryService = 67 m_LibraryService =
68 ServerUtils.LoadPlugin<ILibraryService>(libService, args); 68 ServerUtils.LoadPlugin<ILibraryService>(libService, args);
69 69
70 WebFetchInvDescHandler webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService); 70 FetchInvDescHandler webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService, null);
71 IRequestHandler reqHandler 71 IRequestHandler reqHandler
72 = new RestStreamHandler( 72 = new RestStreamHandler(
73 "POST", 73 "POST",
74 "/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/, 74 "/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/,
75 webFetchHandler.FetchInventoryDescendentsRequest, 75 webFetchHandler.FetchInventoryDescendentsRequest,
76 "WebFetchInvDesc", 76 "FetchInvDescendents",
77 null); 77 null);
78 server.AddStreamHandler(reqHandler); 78 server.AddStreamHandler(reqHandler);
79 } 79 }
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs
index d1503ee..638e8bc 100644
--- a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs
@@ -25,39 +25,36 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection; 28using System.Reflection;
32using log4net;
33using Nini.Config;
34using OpenMetaverse; 29using OpenMetaverse;
35using OpenMetaverse.StructuredData; 30using OpenMetaverse.StructuredData;
36using OpenSim.Framework; 31using OpenSim.Framework;
37using OpenSim.Framework.Capabilities; 32using OpenSim.Framework.Capabilities;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Framework.Servers.HttpServer; 33using OpenSim.Framework.Servers.HttpServer;
40using OpenSim.Services.Interfaces; 34using OpenSim.Services.Interfaces;
41using Caps = OpenSim.Framework.Capabilities.Caps;
42using OSDArray = OpenMetaverse.StructuredData.OSDArray; 35using OSDArray = OpenMetaverse.StructuredData.OSDArray;
43using OSDMap = OpenMetaverse.StructuredData.OSDMap; 36using OSDMap = OpenMetaverse.StructuredData.OSDMap;
44 37
38using log4net;
39
45namespace OpenSim.Capabilities.Handlers 40namespace OpenSim.Capabilities.Handlers
46{ 41{
47 public class FetchInventory2Handler 42 public class FetchInventory2Handler
48 { 43 {
49// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 45
51 private IInventoryService m_inventoryService; 46 private IInventoryService m_inventoryService;
47 private UUID m_agentID;
52 48
53 public FetchInventory2Handler(IInventoryService invService) 49 public FetchInventory2Handler(IInventoryService invService, UUID agentId)
54 { 50 {
55 m_inventoryService = invService; 51 m_inventoryService = invService;
52 m_agentID = agentId;
56 } 53 }
57 54
58 public string FetchInventoryRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 55 public string FetchInventoryRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
59 { 56 {
60// m_log.DebugFormat("[FETCH INVENTORY HANDLER]: Received FetchInventory capabilty request"); 57 //m_log.DebugFormat("[FETCH INVENTORY HANDLER]: Received FetchInventory capability request {0}", request);
61 58
62 OSDMap requestmap = (OSDMap)OSDParser.DeserializeLLSDXml(Utils.StringToBytes(request)); 59 OSDMap requestmap = (OSDMap)OSDParser.DeserializeLLSDXml(Utils.StringToBytes(request));
63 OSDArray itemsRequested = (OSDArray)requestmap["items"]; 60 OSDArray itemsRequested = (OSDArray)requestmap["items"];
@@ -65,12 +62,32 @@ namespace OpenSim.Capabilities.Handlers
65 string reply; 62 string reply;
66 LLSDFetchInventory llsdReply = new LLSDFetchInventory(); 63 LLSDFetchInventory llsdReply = new LLSDFetchInventory();
67 64
65 UUID[] itemIDs = new UUID[itemsRequested.Count];
66 int i = 0;
68 foreach (OSDMap osdItemId in itemsRequested) 67 foreach (OSDMap osdItemId in itemsRequested)
69 { 68 {
70 UUID itemId = osdItemId["item_id"].AsUUID(); 69 itemIDs[i++] = osdItemId["item_id"].AsUUID();
70 }
71
72 InventoryItemBase[] items = m_inventoryService.GetMultipleItems(m_agentID, itemIDs);
71 73
72 InventoryItemBase item = m_inventoryService.GetItem(new InventoryItemBase(itemId)); 74 if (items == null)
75 {
76 // OMG!!! One by one!!! This is fallback code, in case the backend isn't updated
77 m_log.WarnFormat("[FETCH INVENTORY HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one.");
78 items = new InventoryItemBase[itemsRequested.Count];
79 i = 0;
80 InventoryItemBase item = new InventoryItemBase();
81 item.Owner = m_agentID;
82 foreach (UUID id in itemIDs)
83 {
84 item.ID = id;
85 items[i++] = m_inventoryService.GetItem(item);
86 }
87 }
73 88
89 foreach (InventoryItemBase item in items)
90 {
74 if (item != null) 91 if (item != null)
75 { 92 {
76 // We don't know the agent that this request belongs to so we'll use the agent id of the item 93 // We don't know the agent that this request belongs to so we'll use the agent id of the item
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventory2HandlerTests.cs b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventory2HandlerTests.cs
new file mode 100644
index 0000000..8af3c64
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventory2HandlerTests.cs
@@ -0,0 +1,170 @@
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.Linq;
31using System.Net;
32using System.Text.RegularExpressions;
33using log4net;
34using log4net.Config;
35using NUnit.Framework;
36using OpenMetaverse;
37using OpenSim.Capabilities.Handlers;
38using OpenSim.Framework;
39using OpenSim.Framework.Servers.HttpServer;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces;
42using OpenSim.Tests.Common;
43
44namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
45{
46 [TestFixture]
47 public class FetchInventory2HandlerTests : OpenSimTestCase
48 {
49 private UUID m_userID = UUID.Random();
50 private Scene m_scene;
51 private UUID m_rootFolderID;
52 private UUID m_notecardsFolder;
53 private UUID m_objectsFolder;
54
55 private void Init()
56 {
57 // Create an inventory that looks like this:
58 //
59 // /My Inventory
60 // <other system folders>
61 // /Objects
62 // Object 1
63 // Object 2
64 // Object 3
65 // /Notecards
66 // Notecard 1
67 // Notecard 2
68 // Notecard 3
69 // Notecard 4
70 // Notecard 5
71
72 m_scene = new SceneHelpers().SetupScene();
73
74 m_scene.InventoryService.CreateUserInventory(m_userID);
75
76 m_rootFolderID = m_scene.InventoryService.GetRootFolder(m_userID).ID;
77
78 InventoryFolderBase of = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Object);
79 m_objectsFolder = of.ID;
80
81 // Add 3 objects
82 InventoryItemBase item;
83 for (int i = 1; i <= 3; i++)
84 {
85 item = new InventoryItemBase(new UUID("b0000000-0000-0000-0000-0000000000b" + i), m_userID);
86 item.AssetID = UUID.Random();
87 item.AssetType = (int)AssetType.Object;
88 item.Folder = m_objectsFolder;
89 item.Name = "Object " + i;
90 m_scene.InventoryService.AddItem(item);
91 }
92
93 InventoryFolderBase ncf = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Notecard);
94 m_notecardsFolder = ncf.ID;
95
96 // Add 5 notecards
97 for (int i = 1; i <= 5; i++)
98 {
99 item = new InventoryItemBase(new UUID("10000000-0000-0000-0000-00000000000" + i), m_userID);
100 item.AssetID = UUID.Random();
101 item.AssetType = (int)AssetType.Notecard;
102 item.Folder = m_notecardsFolder;
103 item.Name = "Notecard " + i;
104 m_scene.InventoryService.AddItem(item);
105 }
106
107 }
108
109 [Test]
110 public void Test_001_RequestOne()
111 {
112 TestHelpers.InMethod();
113
114 Init();
115
116 FetchInventory2Handler handler = new FetchInventory2Handler(m_scene.InventoryService, m_userID);
117 TestOSHttpRequest req = new TestOSHttpRequest();
118 TestOSHttpResponse resp = new TestOSHttpResponse();
119
120 string request = "<llsd><map><key>items</key><array><map><key>item_id</key><uuid>";
121 request += "10000000-0000-0000-0000-000000000001"; // Notecard 1
122 request += "</uuid></map></array></map></llsd>";
123
124 string llsdresponse = handler.FetchInventoryRequest(request, "/FETCH", string.Empty, req, resp);
125
126 Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
127 Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");
128 Assert.That(llsdresponse.Contains(m_userID.ToString()), Is.True, "Response should contain userID");
129
130 Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Response does not contain item uuid");
131 Assert.That(llsdresponse.Contains("Notecard 1"), Is.True, "Response does not contain item Name");
132 Console.WriteLine(llsdresponse);
133 }
134
135 [Test]
136 public void Test_002_RequestMany()
137 {
138 TestHelpers.InMethod();
139
140 Init();
141
142 FetchInventory2Handler handler = new FetchInventory2Handler(m_scene.InventoryService, m_userID);
143 TestOSHttpRequest req = new TestOSHttpRequest();
144 TestOSHttpResponse resp = new TestOSHttpResponse();
145
146 string request = "<llsd><map><key>items</key><array>";
147 request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000001</uuid></map>"; // Notecard 1
148 request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000002</uuid></map>"; // Notecard 2
149 request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000003</uuid></map>"; // Notecard 3
150 request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000004</uuid></map>"; // Notecard 4
151 request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000005</uuid></map>"; // Notecard 5
152 request += "</array></map></llsd>";
153
154 string llsdresponse = handler.FetchInventoryRequest(request, "/FETCH", string.Empty, req, resp);
155
156 Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
157 Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");
158 Assert.That(llsdresponse.Contains(m_userID.ToString()), Is.True, "Response should contain userID");
159
160 Console.WriteLine(llsdresponse);
161 Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Response does not contain notecard 1");
162 Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000002"), Is.True, "Response does not contain notecard 2");
163 Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000003"), Is.True, "Response does not contain notecard 3");
164 Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000004"), Is.True, "Response does not contain notecard 4");
165 Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000005"), Is.True, "Response does not contain notecard 5");
166 }
167
168 }
169
170} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs
new file mode 100644
index 0000000..2d5531a
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs
@@ -0,0 +1,292 @@
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.Linq;
31using System.Net;
32using System.Text.RegularExpressions;
33using log4net;
34using log4net.Config;
35using NUnit.Framework;
36using OpenMetaverse;
37using OpenSim.Capabilities.Handlers;
38using OpenSim.Framework;
39using OpenSim.Framework.Servers.HttpServer;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces;
42using OpenSim.Tests.Common;
43
44namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
45{
46 [TestFixture]
47 public class FetchInventoryDescendents2HandlerTests : OpenSimTestCase
48 {
49 private UUID m_userID = UUID.Zero;
50 private Scene m_scene;
51 private UUID m_rootFolderID;
52 private int m_rootDescendents;
53 private UUID m_notecardsFolder;
54 private UUID m_objectsFolder;
55
56 private void Init()
57 {
58 // Create an inventory that looks like this:
59 //
60 // /My Inventory
61 // <other system folders>
62 // /Objects
63 // Some Object
64 // /Notecards
65 // Notecard 1
66 // Notecard 2
67 // /Test Folder
68 // Link to notecard -> /Notecards/Notecard 2
69 // Link to Objects folder -> /Objects
70
71 m_scene = new SceneHelpers().SetupScene();
72
73 m_scene.InventoryService.CreateUserInventory(m_userID);
74
75 m_rootFolderID = m_scene.InventoryService.GetRootFolder(m_userID).ID;
76
77 InventoryFolderBase of = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Object);
78 m_objectsFolder = of.ID;
79
80 // Add an object
81 InventoryItemBase item = new InventoryItemBase(new UUID("b0000000-0000-0000-0000-00000000000b"), m_userID);
82 item.AssetID = UUID.Random();
83 item.AssetType = (int)AssetType.Object;
84 item.Folder = m_objectsFolder;
85 item.Name = "Some Object";
86 m_scene.InventoryService.AddItem(item);
87
88 InventoryFolderBase ncf = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Notecard);
89 m_notecardsFolder = ncf.ID;
90
91 // Add a notecard
92 item = new InventoryItemBase(new UUID("10000000-0000-0000-0000-000000000001"), m_userID);
93 item.AssetID = UUID.Random();
94 item.AssetType = (int)AssetType.Notecard;
95 item.Folder = m_notecardsFolder;
96 item.Name = "Test Notecard 1";
97 m_scene.InventoryService.AddItem(item);
98 // Add another notecard
99 item.ID = new UUID("20000000-0000-0000-0000-000000000002");
100 item.AssetID = new UUID("a0000000-0000-0000-0000-00000000000a");
101 item.Name = "Test Notecard 2";
102 m_scene.InventoryService.AddItem(item);
103
104 // Add a folder
105 InventoryFolderBase folder = new InventoryFolderBase(new UUID("f0000000-0000-0000-0000-00000000000f"), "Test Folder", m_userID, m_rootFolderID);
106 m_scene.InventoryService.AddFolder(folder);
107
108 // Add a link to notecard 2 in Test Folder
109 item.AssetID = item.ID; // use item ID of notecard 2
110 item.ID = new UUID("40000000-0000-0000-0000-000000000004");
111 item.AssetType = (int)AssetType.Link;
112 item.Folder = folder.ID;
113 item.Name = "Link to notecard";
114 m_scene.InventoryService.AddItem(item);
115
116 // Add a link to the Objects folder in Test Folder
117 item.AssetID = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Object).ID; // use item ID of Objects folder
118 item.ID = new UUID("50000000-0000-0000-0000-000000000005");
119 item.AssetType = (int)AssetType.LinkFolder;
120 item.Folder = folder.ID;
121 item.Name = "Link to Objects folder";
122 m_scene.InventoryService.AddItem(item);
123
124 InventoryCollection coll = m_scene.InventoryService.GetFolderContent(m_userID, m_rootFolderID);
125 m_rootDescendents = coll.Items.Count + coll.Folders.Count;
126 Console.WriteLine("Number of descendents: " + m_rootDescendents);
127 }
128
129 [Test]
130 public void Test_001_SimpleFolder()
131 {
132 TestHelpers.InMethod();
133
134 Init();
135
136 FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
137 TestOSHttpRequest req = new TestOSHttpRequest();
138 TestOSHttpResponse resp = new TestOSHttpResponse();
139
140 string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
141 request += m_rootFolderID;
142 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
143
144 string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
145
146 Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
147 Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");
148 Assert.That(llsdresponse.Contains("00000000-0000-0000-0000-000000000000"), Is.True, "Response should contain userID");
149
150 string descendents = "descendents</key><integer>" + m_rootDescendents + "</integer>";
151 Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents");
152 Console.WriteLine(llsdresponse);
153 }
154
155 [Test]
156 public void Test_002_MultipleFolders()
157 {
158 TestHelpers.InMethod();
159
160 FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
161 TestOSHttpRequest req = new TestOSHttpRequest();
162 TestOSHttpResponse resp = new TestOSHttpResponse();
163
164 string request = "<llsd><map><key>folders</key><array>";
165 request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
166 request += m_rootFolderID;
167 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
168 request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
169 request += m_notecardsFolder;
170 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
171 request += "</array></map></llsd>";
172
173 string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
174 Console.WriteLine(llsdresponse);
175
176 string descendents = "descendents</key><integer>" + m_rootDescendents + "</integer>";
177 Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for root folder");
178 descendents = "descendents</key><integer>2</integer>";
179 Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for Notecard folder");
180
181 Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Notecard 1 is missing from response");
182 Assert.That(llsdresponse.Contains("20000000-0000-0000-0000-000000000002"), Is.True, "Notecard 2 is missing from response");
183 }
184
185 [Test]
186 public void Test_003_Links()
187 {
188 TestHelpers.InMethod();
189
190 FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
191 TestOSHttpRequest req = new TestOSHttpRequest();
192 TestOSHttpResponse resp = new TestOSHttpResponse();
193
194 string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
195 request += "f0000000-0000-0000-0000-00000000000f";
196 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
197
198 string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
199 Console.WriteLine(llsdresponse);
200
201 string descendents = "descendents</key><integer>2</integer>";
202 Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for Test Folder");
203
204 // Make sure that the note card link is included
205 Assert.That(llsdresponse.Contains("Link to notecard"), Is.True, "Link to notecard is missing");
206
207 //Make sure the notecard item itself is included
208 Assert.That(llsdresponse.Contains("Test Notecard 2"), Is.True, "Notecard 2 item (the source) is missing");
209
210 // Make sure that the source item is before the link item
211 int pos1 = llsdresponse.IndexOf("Test Notecard 2");
212 int pos2 = llsdresponse.IndexOf("Link to notecard");
213 Assert.Less(pos1, pos2, "Source of link is after link");
214
215 // Make sure the folder link is included
216 Assert.That(llsdresponse.Contains("Link to Objects folder"), Is.True, "Link to Objects folder is missing");
217
218 // Make sure the objects inside the Objects folder are included
219 // Note: I'm not entirely sure this is needed, but that's what I found in the implementation
220 Assert.That(llsdresponse.Contains("Some Object"), Is.True, "Some Object item (contents of the source) is missing");
221
222 // Make sure that the source item is before the link item
223 pos1 = llsdresponse.IndexOf("Some Object");
224 pos2 = llsdresponse.IndexOf("Link to Objects folder");
225 Assert.Less(pos1, pos2, "Contents of source of folder link is after folder link");
226 }
227
228 [Test]
229 public void Test_004_DuplicateFolders()
230 {
231 TestHelpers.InMethod();
232
233 FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
234 TestOSHttpRequest req = new TestOSHttpRequest();
235 TestOSHttpResponse resp = new TestOSHttpResponse();
236
237 string request = "<llsd><map><key>folders</key><array>";
238 request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
239 request += m_rootFolderID;
240 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
241 request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
242 request += m_notecardsFolder;
243 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
244 request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
245 request += m_rootFolderID;
246 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
247 request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
248 request += m_notecardsFolder;
249 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
250 request += "</array></map></llsd>";
251
252 string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
253 Console.WriteLine(llsdresponse);
254
255 string root_folder = "<key>folder_id</key><uuid>" + m_rootFolderID + "</uuid>";
256 string notecards_folder = "<key>folder_id</key><uuid>" + m_notecardsFolder + "</uuid>";
257
258 Assert.That(llsdresponse.Contains(root_folder), "Missing root folder");
259 Assert.That(llsdresponse.Contains(notecards_folder), "Missing notecards folder");
260 int count = Regex.Matches(llsdresponse, root_folder).Count;
261 Assert.AreEqual(1, count, "More than 1 root folder in response");
262 count = Regex.Matches(llsdresponse, notecards_folder).Count;
263 Assert.AreEqual(2, count, "More than 1 notecards folder in response"); // Notecards will also be under root, so 2
264 }
265
266 [Test]
267 public void Test_005_FolderZero()
268 {
269 TestHelpers.InMethod();
270
271 Init();
272
273 FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
274 TestOSHttpRequest req = new TestOSHttpRequest();
275 TestOSHttpResponse resp = new TestOSHttpResponse();
276
277 string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
278 request += UUID.Zero;
279 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
280
281 string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
282
283 Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
284 Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");
285 Assert.That(llsdresponse.Contains("bad_folders</key><array><uuid>00000000-0000-0000-0000-000000000000"), Is.True, "Folder Zero should be a bad folder");
286
287 Console.WriteLine(llsdresponse);
288 }
289
290 }
291
292} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs b/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs
new file mode 100644
index 0000000..589602d
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs
@@ -0,0 +1,120 @@
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.Collections.Specialized;
32using System.Drawing;
33using System.Drawing.Imaging;
34using System.Reflection;
35using System.IO;
36using System.Web;
37using log4net;
38using Nini.Config;
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41using OpenMetaverse.Imaging;
42using OpenSim.Framework;
43using OpenSim.Framework.Capabilities;
44using OpenSim.Framework.Servers;
45using OpenSim.Framework.Servers.HttpServer;
46using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Services.Interfaces;
48using Caps = OpenSim.Framework.Capabilities.Caps;
49using OSDMap = OpenMetaverse.StructuredData.OSDMap;
50using OSDArray = OpenMetaverse.StructuredData.OSDArray;
51
52namespace OpenSim.Capabilities.Handlers
53{
54 public class GetDisplayNamesHandler : BaseStreamHandler
55 {
56 private static readonly ILog m_log =
57 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
58 private IUserManagement m_UserManagement;
59
60 public GetDisplayNamesHandler(string path, IUserManagement umService, string name, string description)
61 : base("GET", path, name, description)
62 {
63 m_UserManagement = umService;
64 }
65
66 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
67 {
68 m_log.DebugFormat("[GET_DISPLAY_NAMES]: called {0}", httpRequest.Url.Query);
69
70 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
71 string[] ids = query.GetValues("ids");
72
73
74 if (m_UserManagement == null)
75 {
76 m_log.Error("[GET_DISPLAY_NAMES]: Cannot fetch display names without a user management component");
77 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
78 return new byte[0];
79 }
80
81 OSDMap osdReply = new OSDMap();
82 OSDArray agents = new OSDArray();
83
84 osdReply["agents"] = agents;
85 foreach (string id in ids)
86 {
87 UUID uuid = UUID.Zero;
88 if (UUID.TryParse(id, out uuid))
89 {
90 string name = m_UserManagement.GetUserName(uuid);
91 if (!string.IsNullOrEmpty(name))
92 {
93 string[] parts = name.Split(new char[] {' '});
94 OSDMap osdname = new OSDMap();
95 osdname["display_name_next_update"] = OSD.FromDate(DateTime.MinValue);
96 osdname["display_name_expires"] = OSD.FromDate(DateTime.Now.AddMonths(1));
97 osdname["display_name"] = OSD.FromString(name);
98 osdname["legacy_first_name"] = parts[0];
99 osdname["legacy_last_name"] = parts[1];
100 osdname["username"] = OSD.FromString(name);
101 osdname["id"] = OSD.FromUUID(uuid);
102 osdname["is_display_name_default"] = OSD.FromBoolean(true);
103
104 agents.Add(osdname);
105 }
106 }
107 }
108
109 // Full content request
110 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.OK;
111 //httpResponse.ContentLength = ??;
112 httpResponse.ContentType = "application/llsd+xml";
113
114 string reply = OSDParser.SerializeLLSDXmlString(osdReply);
115 return System.Text.Encoding.UTF8.GetBytes(reply);
116
117 }
118
119 }
120} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2ServerConnector.cs b/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesServerConnector.cs
index 5bab52f..d42de56 100644
--- a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2ServerConnector.cs
+++ b/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesServerConnector.cs
@@ -35,13 +35,13 @@ using OpenMetaverse;
35 35
36namespace OpenSim.Capabilities.Handlers 36namespace OpenSim.Capabilities.Handlers
37{ 37{
38 public class FetchInventory2ServerConnector : ServiceConnector 38 public class GetDisplayNamesServerConnector : ServiceConnector
39 { 39 {
40 private IInventoryService m_InventoryService; 40 private IUserManagement m_UserManagement;
41 private string m_ConfigName = "CapsService"; 41 private string m_ConfigName = "CapsService";
42 42
43 public FetchInventory2ServerConnector(IConfigSource config, IHttpServer server, string configName) 43 public GetDisplayNamesServerConnector(IConfigSource config, IHttpServer server, string configName) :
44 : base(config, server, configName) 44 base(config, server, configName)
45 { 45 {
46 if (configName != String.Empty) 46 if (configName != String.Empty)
47 m_ConfigName = configName; 47 m_ConfigName = configName;
@@ -50,22 +50,22 @@ namespace OpenSim.Capabilities.Handlers
50 if (serverConfig == null) 50 if (serverConfig == null)
51 throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName)); 51 throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
52 52
53 string invService = serverConfig.GetString("InventoryService", String.Empty); 53 string umService = serverConfig.GetString("AssetService", String.Empty);
54 54
55 if (invService == String.Empty) 55 if (umService == String.Empty)
56 throw new Exception("No InventoryService in config file"); 56 throw new Exception("No AssetService in config file");
57 57
58 Object[] args = new Object[] { config }; 58 Object[] args = new Object[] { config };
59 m_InventoryService = ServerUtils.LoadPlugin<IInventoryService>(invService, args); 59 m_UserManagement =
60 ServerUtils.LoadPlugin<IUserManagement>(umService, args);
60 61
61 if (m_InventoryService == null) 62 if (m_UserManagement == null)
62 throw new Exception(String.Format("Failed to load InventoryService from {0}; config is {1}", invService, m_ConfigName)); 63 throw new Exception(String.Format("Failed to load UserManagement from {0}; config is {1}", umService, m_ConfigName));
63 64
64 FetchInventory2Handler fiHandler = new FetchInventory2Handler(m_InventoryService); 65 string rurl = serverConfig.GetString("GetTextureRedirectURL");
65 IRequestHandler reqHandler 66
66 = new RestStreamHandler( 67 server.AddStreamHandler(
67 "POST", "/CAPS/FetchInventory/", fiHandler.FetchInventoryRequest, "FetchInventory", null); 68 new GetDisplayNamesHandler("/CAPS/agents/", m_UserManagement, "GetDisplayNames", null));
68 server.AddStreamHandler(reqHandler);
69 } 69 }
70 } 70 }
71} 71} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
index ec574a3..7fcc798 100644
--- a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
@@ -25,25 +25,23 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
29using System.Collections;
30using System.Collections.Specialized;
31using System.Reflection;
32using System.IO;
33using System.Web;
34using log4net; 28using log4net;
35using Nini.Config;
36using OpenMetaverse; 29using OpenMetaverse;
37using OpenMetaverse.StructuredData; 30using OpenMetaverse.Imaging;
38using OpenSim.Framework; 31using OpenSim.Framework;
39using OpenSim.Framework.Servers;
40using OpenSim.Framework.Servers.HttpServer; 32using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Services.Interfaces; 33using OpenSim.Services.Interfaces;
42using Caps = OpenSim.Framework.Capabilities.Caps; 34using System;
35using System.Collections.Specialized;
36using System.Drawing;
37using System.Drawing.Imaging;
38using System.IO;
39using System.Reflection;
40using System.Web;
43 41
44namespace OpenSim.Capabilities.Handlers 42namespace OpenSim.Capabilities.Handlers
45{ 43{
46 public class GetMeshHandler 44 public class GetMeshHandler : BaseStreamHandler
47 { 45 {
48 private static readonly ILog m_log = 46 private static readonly ILog m_log =
49 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -55,6 +53,9 @@ namespace OpenSim.Capabilities.Handlers
55 public GetMeshHandler(IAssetService assService) 53 public GetMeshHandler(IAssetService assService)
56 { 54 {
57 m_assetService = assService; 55 m_assetService = assService;
56 m_RedirectURL = redirectURL;
57 if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/"))
58 m_RedirectURL += "/";
58 } 59 }
59 public Hashtable Handle(Hashtable request) 60 public Hashtable Handle(Hashtable request)
60 { 61 {
@@ -95,38 +96,107 @@ namespace OpenSim.Capabilities.Handlers
95 } 96 }
96 public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap) 97 public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap)
97 { 98 {
98 Hashtable responsedata = new Hashtable(); 99 // Try to parse the texture ID from the request URL
99 responsedata["int_response_code"] = 400; //501; //410; //404; 100 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
100 responsedata["content_type"] = "text/plain"; 101 string textureStr = query.GetOne("mesh_id");
101 responsedata["keepalive"] = false;
102 responsedata["str_response_string"] = "Request wasn't what was expected";
103 responsedata["reusecontext"] = false; 102 responsedata["reusecontext"] = false;
104 responsedata["int_lod"] = 0; 103 responsedata["int_lod"] = 0;
105 responsedata["int_bytes"] = 0; 104 responsedata["int_bytes"] = 0;
106 105
107 string meshStr = string.Empty; 106 if (m_assetService == null)
108 107 {
109 if (request.ContainsKey("mesh_id")) 108 m_log.Error("[GETMESH]: Cannot fetch mesh " + textureStr + " without an asset service");
110 meshStr = request["mesh_id"].ToString(); 109 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
110 }
111 111
112 UUID meshID = UUID.Zero; 112 UUID meshID;
113 if (!String.IsNullOrEmpty(meshStr) && UUID.TryParse(meshStr, out meshID)) 113 if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out meshID))
114 { 114 {
115 if (m_assetService == null) 115 // OK, we have an array with preferred formats, possibly with only one entry
116
117 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
118 AssetBase mesh;
119
120 if (!String.IsNullOrEmpty(m_RedirectURL))
116 { 121 {
117 responsedata["int_response_code"] = 404; //501; //410; //404; 122 // Only try to fetch locally cached meshes. Misses are redirected
118 responsedata["content_type"] = "text/plain"; 123 mesh = m_assetService.GetCached(meshID.ToString());
119 responsedata["keepalive"] = false; 124
120 responsedata["str_response_string"] = "The asset service is unavailable. So is your mesh."; 125 if (mesh != null)
121 responsedata["reusecontext"] = false; 126 {
122 return responsedata; 127 if (mesh.Type != (sbyte)AssetType.Mesh)
128 {
129 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
130 }
131 WriteMeshData(httpRequest, httpResponse, mesh);
132 }
133 else
134 {
135 string textureUrl = m_RedirectURL + "?mesh_id="+ meshID.ToString();
136 m_log.Debug("[GETMESH]: Redirecting mesh request to " + textureUrl);
137 httpResponse.StatusCode = (int)OSHttpStatusCode.RedirectMovedPermanently;
138 httpResponse.RedirectLocation = textureUrl;
139 return null;
140 }
123 } 141 }
142 else // no redirect
143 {
144 // try the cache
145 mesh = m_assetService.GetCached(meshID.ToString());
124 146
125 AssetBase mesh = m_assetService.Get(meshID.ToString()); 147 if (mesh == null)
148 {
149 // Fetch locally or remotely. Misses return a 404
150 mesh = m_assetService.Get(meshID.ToString());
151
152 if (mesh != null)
153 {
154 if (mesh.Type != (sbyte)AssetType.Mesh)
155 {
156 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
157 return null;
158 }
159 WriteMeshData(httpRequest, httpResponse, mesh);
160 return null;
161 }
162 }
163 else // it was on the cache
164 {
165 if (mesh.Type != (sbyte)AssetType.Mesh)
166 {
167 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
168 return null;
169 }
170 WriteMeshData(httpRequest, httpResponse, mesh);
171 return null;
172 }
173 }
126 174
127 if (mesh != null) 175 // not found
176 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
177 return null;
178 }
179 else
180 {
181 m_log.Warn("[GETTEXTURE]: Failed to parse a mesh_id from GetMesh request: " + httpRequest.Url);
182 }
183
184 return null;
185 }
186
187 private void WriteMeshData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture)
188 {
189 string range = request.Headers.GetOne("Range");
190
191 if (!String.IsNullOrEmpty(range))
192 {
193 // Range request
194 int start, end;
195 if (TryParseRange(range, out start, out end))
128 { 196 {
129 if (mesh.Type == (SByte)AssetType.Mesh) 197 // Before clamping start make sure we can satisfy it in order to avoid
198 // sending back the last byte instead of an error status
199 if (start >= texture.Data.Length)
130 { 200 {
131 201
132 Hashtable headers = new Hashtable(); 202 Hashtable headers = new Hashtable();
@@ -223,7 +293,6 @@ namespace OpenSim.Capabilities.Handlers
223 responsedata["int_lod"] = 3; 293 responsedata["int_lod"] = 3;
224 } 294 }
225 } 295 }
226 // Optionally add additional mesh types here
227 else 296 else
228 { 297 {
229 responsedata["int_response_code"] = 404; //501; //410; //404; 298 responsedata["int_response_code"] = 404; //501; //410; //404;
@@ -246,8 +315,58 @@ namespace OpenSim.Capabilities.Handlers
246 return responsedata; 315 return responsedata;
247 } 316 }
248 } 317 }
318 else
319 {
320 // Full content request
321 response.StatusCode = (int)System.Net.HttpStatusCode.OK;
322 response.ContentLength = texture.Data.Length;
323 response.ContentType = "application/vnd.ll.mesh";
324 response.Body.Write(texture.Data, 0, texture.Data.Length);
325 }
326 }
249 327
250 return responsedata; 328 /// <summary>
329 /// Parse a range header.
330 /// </summary>
331 /// <remarks>
332 /// As per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html,
333 /// this obeys range headers with two values (e.g. 533-4165) and no second value (e.g. 533-).
334 /// Where there is no value, -1 is returned.
335 /// FIXME: Need to cover the case where only a second value is specified (e.g. -4165), probably by returning -1
336 /// for start.</remarks>
337 /// <returns></returns>
338 /// <param name='header'></param>
339 /// <param name='start'>Start of the range. Undefined if this was not a number.</param>
340 /// <param name='end'>End of the range. Will be -1 if no end specified. Undefined if there was a raw string but this was not a number.</param>
341 private bool TryParseRange(string header, out int start, out int end)
342 {
343 start = end = 0;
344
345 if (header.StartsWith("bytes="))
346 {
347 string[] rangeValues = header.Substring(6).Split('-');
348
349 if (rangeValues.Length == 2)
350 {
351 if (!Int32.TryParse(rangeValues[0], out start))
352 return false;
353
354 string rawEnd = rangeValues[1];
355
356 if (rawEnd == "")
357 {
358 end = -1;
359 return true;
360 }
361 else if (Int32.TryParse(rawEnd, out end))
362 {
363 return true;
364 }
365 }
366 }
367
368 start = end = 0;
369 return false;
251 } 370 }
252 private bool TryParseRange(string header, out int start, out int end) 371 private bool TryParseRange(string header, out int start, out int end)
253 { 372 {
diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs
index 8a275f3..19de3cf 100644
--- a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs
+++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs
@@ -25,16 +25,13 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
29using System.Collections;
30using Nini.Config; 28using Nini.Config;
31using OpenSim.Server.Base; 29using OpenMetaverse;
32using OpenSim.Services.Interfaces;
33using OpenSim.Framework.Servers.HttpServer; 30using OpenSim.Framework.Servers.HttpServer;
31using OpenSim.Server.Base;
34using OpenSim.Server.Handlers.Base; 32using OpenSim.Server.Handlers.Base;
35using OpenSim.Framework.Servers; 33using OpenSim.Services.Interfaces;
36 34using System;
37using OpenMetaverse;
38 35
39namespace OpenSim.Capabilities.Handlers 36namespace OpenSim.Capabilities.Handlers
40{ 37{
@@ -65,15 +62,15 @@ namespace OpenSim.Capabilities.Handlers
65 if (m_AssetService == null) 62 if (m_AssetService == null)
66 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName)); 63 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
67 64
68 GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService); 65 string rurl = serverConfig.GetString("GetMeshRedirectURL");
69 IRequestHandler reqHandler 66
70 = new RestHTTPHandler( 67 server.AddStreamHandler(
71 "GET", 68 new GetTextureHandler("/CAPS/GetMesh/" /*+ UUID.Random() */, m_AssetService, "GetMesh", null, rurl));
72 "/CAPS/" + UUID.Random(), 69
73 httpMethod => gmeshHandler.ProcessGetMesh(httpMethod, UUID.Zero, null), 70 rurl = serverConfig.GetString("GetMesh2RedirectURL");
74 "GetMesh", 71
75 null); 72 server.AddStreamHandler(
76 server.AddStreamHandler(reqHandler); 73 new GetTextureHandler("/CAPS/GetMesh2/" /*+ UUID.Random() */, m_AssetService, "GetMesh2", null, rurl));
77 } 74 }
78 } 75 }
79} \ No newline at end of file 76} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
index f3efb53..a8e0fb5 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -56,9 +56,16 @@ namespace OpenSim.Capabilities.Handlers
56 56
57 public const string DefaultFormat = "x-j2c"; 57 public const string DefaultFormat = "x-j2c";
58 58
59 // TODO: Change this to a config option
60 private string m_RedirectURL = null;
61
62
59 public GetTextureHandler(IAssetService assService) 63 public GetTextureHandler(IAssetService assService)
60 { 64 {
61 m_assetService = assService; 65 m_assetService = assService;
66 m_RedirectURL = redirectURL;
67 if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/"))
68 m_RedirectURL += "/";
62 } 69 }
63 70
64 public Hashtable Handle(Hashtable request) 71 public Hashtable Handle(Hashtable request)
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs
index bf66acb..d55e0ff 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs
@@ -63,8 +63,10 @@ namespace OpenSim.Capabilities.Handlers
63 if (m_AssetService == null) 63 if (m_AssetService == null)
64 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName)); 64 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
65 65
66 string rurl = serverConfig.GetString("GetTextureRedirectURL");
67 ;
66 server.AddStreamHandler( 68 server.AddStreamHandler(
67 new GetTextureHandler("/CAPS/GetTexture/", m_AssetService, "GetTexture", null)); 69 new GetTextureHandler("/CAPS/GetTexture/" /*+ UUID.Random() */, m_AssetService, "GetTexture", null, rurl));
68 } 70 }
69 } 71 }
70} 72}
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs b/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
index 217a265..61aa689 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
@@ -37,7 +37,6 @@ using OpenSim.Framework;
37using OpenSim.Framework.Servers.HttpServer; 37using OpenSim.Framework.Servers.HttpServer;
38using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Tests.Common; 39using OpenSim.Tests.Common;
40using OpenSim.Tests.Common.Mock;
41 40
42/* 41/*
43namespace OpenSim.Capabilities.Handlers.GetTexture.Tests 42namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
@@ -53,7 +52,7 @@ namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
53 // Overkill - we only really need the asset service, not a whole scene. 52 // Overkill - we only really need the asset service, not a whole scene.
54 Scene scene = new SceneHelpers().SetupScene(); 53 Scene scene = new SceneHelpers().SetupScene();
55 54
56 GetTextureHandler handler = new GetTextureHandler(null, scene.AssetService, "TestGetTexture", null); 55 GetTextureHandler handler = new GetTextureHandler("/gettexture", scene.AssetService, "TestGetTexture", null, null);
57 TestOSHttpRequest req = new TestOSHttpRequest(); 56 TestOSHttpRequest req = new TestOSHttpRequest();
58 TestOSHttpResponse resp = new TestOSHttpResponse(); 57 TestOSHttpResponse resp = new TestOSHttpResponse();
59 req.Url = new Uri("http://localhost/?texture_id=00000000-0000-1111-9999-000000000012"); 58 req.Url = new Uri("http://localhost/?texture_id=00000000-0000-1111-9999-000000000012");
diff --git a/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs b/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
index 0cf8bf4..3579649 100644
--- a/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
+++ b/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.8.0.*")] 32[assembly: AssemblyVersion("0.8.2.*")]
33 33
diff --git a/OpenSim/Capabilities/LLSD.cs b/OpenSim/Capabilities/LLSD.cs
index eec9e61..c59cede 100644
--- a/OpenSim/Capabilities/LLSD.cs
+++ b/OpenSim/Capabilities/LLSD.cs
@@ -68,7 +68,10 @@ namespace OpenSim.Framework.Capabilities
68 /// <returns></returns> 68 /// <returns></returns>
69 public static object LLSDDeserialize(byte[] b) 69 public static object LLSDDeserialize(byte[] b)
70 { 70 {
71 return LLSDDeserialize(new MemoryStream(b, false)); 71 using (MemoryStream ms = new MemoryStream(b, false))
72 {
73 return LLSDDeserialize(ms);
74 }
72 } 75 }
73 76
74 /// <summary> 77 /// <summary>
@@ -78,21 +81,23 @@ namespace OpenSim.Framework.Capabilities
78 /// <returns></returns> 81 /// <returns></returns>
79 public static object LLSDDeserialize(Stream st) 82 public static object LLSDDeserialize(Stream st)
80 { 83 {
81 XmlTextReader reader = new XmlTextReader(st); 84 using (XmlTextReader reader = new XmlTextReader(st))
82 reader.Read(); 85 {
83 SkipWS(reader); 86 reader.Read();
87 SkipWS(reader);
84 88
85 if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "llsd") 89 if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "llsd")
86 throw new LLSDParseException("Expected <llsd>"); 90 throw new LLSDParseException("Expected <llsd>");
87 91
88 reader.Read(); 92 reader.Read();
89 object ret = LLSDParseOne(reader); 93 object ret = LLSDParseOne(reader);
90 SkipWS(reader); 94 SkipWS(reader);
91 95
92 if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "llsd") 96 if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "llsd")
93 throw new LLSDParseException("Expected </llsd>"); 97 throw new LLSDParseException("Expected </llsd>");
94 98
95 return ret; 99 return ret;
100 }
96 } 101 }
97 102
98 /// <summary> 103 /// <summary>