aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Capabilities
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Capabilities')
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs437
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs5
-rw-r--r--OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs41
3 files changed, 155 insertions, 328 deletions
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs
index 53ed115..0f3f48e 100644
--- a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs
@@ -30,6 +30,7 @@ using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Linq; 31using System.Linq;
32using System.Reflection; 32using System.Reflection;
33using System.Text;
33using log4net; 34using log4net;
34using Nini.Config; 35using Nini.Config;
35using OpenMetaverse; 36using OpenMetaverse;
@@ -60,7 +61,6 @@ namespace OpenSim.Capabilities.Handlers
60 m_Scene = s; 61 m_Scene = s;
61 } 62 }
62 63
63
64 public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 64 public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
65 { 65 {
66 //m_log.DebugFormat("[XXX]: FetchInventoryDescendentsRequest in {0}, {1}", (m_Scene == null) ? "none" : m_Scene.Name, request); 66 //m_log.DebugFormat("[XXX]: FetchInventoryDescendentsRequest in {0}, {1}", (m_Scene == null) ? "none" : m_Scene.Name, request);
@@ -93,8 +93,8 @@ namespace OpenSim.Capabilities.Handlers
93 93
94 ArrayList foldersrequested = (ArrayList)hash["folders"]; 94 ArrayList foldersrequested = (ArrayList)hash["folders"];
95 95
96 string response = ""; 96 StringBuilder tmpresponse = new StringBuilder(1024);
97 string bad_folders_response = ""; 97 StringBuilder tmpbadfolders = new StringBuilder(1024);
98 98
99 List<LLSDFetchInventoryDescendents> folders = new List<LLSDFetchInventoryDescendents>(); 99 List<LLSDFetchInventoryDescendents> folders = new List<LLSDFetchInventoryDescendents>();
100 for (int i = 0; i < foldersrequested.Count; i++) 100 for (int i = 0; i < foldersrequested.Count; i++)
@@ -113,10 +113,7 @@ namespace OpenSim.Capabilities.Handlers
113 continue; 113 continue;
114 } 114 }
115 115
116 // Filter duplicate folder ids that bad viewers may send 116 folders.Add(llsdRequest);
117 if (folders.Find(f => f.folder_id == llsdRequest.folder_id) == null)
118 folders.Add(llsdRequest);
119
120 } 117 }
121 118
122 if (folders.Count > 0) 119 if (folders.Count > 0)
@@ -136,49 +133,44 @@ namespace OpenSim.Capabilities.Handlers
136 string inventoryitemstr = string.Empty; 133 string inventoryitemstr = string.Empty;
137 foreach (InventoryCollectionWithDescendents icoll in invcollSet) 134 foreach (InventoryCollectionWithDescendents icoll in invcollSet)
138 { 135 {
139 LLSDInventoryDescendents reply = ToLLSD(icoll.Collection, icoll.Descendents); 136 LLSDInventoryFolderContents thiscontents = contentsToLLSD(icoll.Collection, icoll.Descendents);
140 137 inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(thiscontents);
141 inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply); 138// inventoryitemstr = inventoryitemstr.Replace("<llsd>", "");
142 inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", ""); 139// inventoryitemstr = inventoryitemstr.Replace("</llsd>", "");
143 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", ""); 140// inventoryitemstr = inventoryitemstr.Substring(6,inventoryitemstr.Length - 13);
144 141// tmpresponse.Append(inventoryitemstr);
145 response += inventoryitemstr; 142 tmpresponse.Append(inventoryitemstr.Substring(6,inventoryitemstr.Length - 13));
146 } 143 }
147 144
148 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders)); 145 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders));
149 foreach (UUID bad in bad_folders) 146 foreach (UUID bad in bad_folders)
150 bad_folders_response += "<uuid>" + bad + "</uuid>"; 147 {
148 tmpbadfolders.Append("<map><key>folder_id</key><uuid>");
149 tmpbadfolders.Append(bad.ToString());
150 tmpbadfolders.Append("</uuid><key>error</key><string>Unknown</string></map>");
151 }
151 } 152 }
152 153
153 if (response.Length == 0) 154 StringBuilder lastresponse = new StringBuilder(1024);
155 lastresponse.Append("<llsd>");
156 if(tmpresponse.Length > 0)
154 { 157 {
155 /* Viewers expect a bad_folders array when not available */ 158 lastresponse.Append("<map><key>folders</key><array>");
156 if (bad_folders_response.Length != 0) 159 lastresponse.Append(tmpresponse.ToString());
157 { 160 lastresponse.Append("</array></map>");
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 } 161 }
165 else 162 else
163 lastresponse.Append("<map><key>folders</key><array /></map>");
164
165 if(tmpbadfolders.Length > 0)
166 { 166 {
167 if (bad_folders_response.Length != 0) 167 lastresponse.Append("<map><key>bad_folders</key><array>");
168 { 168 lastresponse.Append(tmpbadfolders.ToString());
169 response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>"; 169 lastresponse.Append("</array></map>");
170 }
171 else
172 {
173 response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
174 }
175 } 170 }
171 lastresponse.Append("</llsd>");
176 172
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); 173 return lastresponse.ToString();
178 //m_log.Debug("[WEB FETCH INV DESC HANDLER] " + response);
179
180 return response;
181
182 } 174 }
183 175
184 /// <summary> 176 /// <summary>
@@ -240,24 +232,19 @@ namespace OpenSim.Capabilities.Handlers
240 return reply; 232 return reply;
241 } 233 }
242 234
243 private LLSDInventoryDescendents ToLLSD(InventoryCollection inv, int descendents) 235 private LLSDInventoryFolderContents contentsToLLSD(InventoryCollection inv, int descendents)
244 { 236 {
245 LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
246 LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents(); 237 LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
247 contents.agent_id = inv.OwnerID; 238 contents.agent_id = inv.OwnerID;
248 contents.owner_id = inv.OwnerID; 239 contents.owner_id = inv.OwnerID;
249 contents.folder_id = inv.FolderID; 240 contents.folder_id = inv.FolderID;
250 241
251 reply.folders.Array.Add(contents);
252
253 if (inv.Folders != null) 242 if (inv.Folders != null)
254 { 243 {
255 foreach (InventoryFolderBase invFolder in inv.Folders) 244 foreach (InventoryFolderBase invFolder in inv.Folders)
256 { 245 {
257 contents.categories.Array.Add(ConvertInventoryFolder(invFolder)); 246 contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
258 } 247 }
259
260 descendents += inv.Folders.Count;
261 } 248 }
262 249
263 if (inv.Items != null) 250 if (inv.Items != null)
@@ -271,7 +258,7 @@ namespace OpenSim.Capabilities.Handlers
271 contents.descendents = descendents; 258 contents.descendents = descendents;
272 contents.version = inv.Version; 259 contents.version = inv.Version;
273 260
274 return reply; 261 return contents;
275 } 262 }
276 /// <summary> 263 /// <summary>
277 /// Old style. Soon to be deprecated. 264 /// Old style. Soon to be deprecated.
@@ -285,8 +272,8 @@ namespace OpenSim.Capabilities.Handlers
285 { 272 {
286 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count); 273 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count);
287 274
288 string response = ""; 275 StringBuilder tmpresponse = new StringBuilder(1024);
289 string bad_folders_response = ""; 276 StringBuilder tmpbadfolders = new StringBuilder(1024);
290 277
291 for (int i = 0; i < foldersrequested.Count; i++) 278 for (int i = 0; i < foldersrequested.Count; i++)
292 { 279 {
@@ -308,7 +295,9 @@ namespace OpenSim.Capabilities.Handlers
308 295
309 if (null == reply) 296 if (null == reply)
310 { 297 {
311 bad_folders_response += "<uuid>" + llsdRequest.folder_id.ToString() + "</uuid>"; 298 tmpbadfolders.Append("<map><key>folder_id</key><uuid>");
299 tmpbadfolders.Append(llsdRequest.folder_id.ToString());
300 tmpbadfolders.Append("</uuid><key>error</key><string>Unknown</string></map>");
312 } 301 }
313 else 302 else
314 { 303 {
@@ -317,39 +306,29 @@ namespace OpenSim.Capabilities.Handlers
317 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", ""); 306 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
318 } 307 }
319 308
320 response += inventoryitemstr; 309 tmpresponse.Append(inventoryitemstr);
321 } 310 }
322 311
323 if (response.Length == 0) 312 StringBuilder lastresponse = new StringBuilder(1024);
313 lastresponse.Append("<llsd>");
314 if(tmpresponse.Length > 0)
324 { 315 {
325 /* Viewers expect a bad_folders array when not available */ 316 lastresponse.Append("<map><key>folders</key><array>");
326 if (bad_folders_response.Length != 0) 317 lastresponse.Append(tmpresponse.ToString());
327 { 318 lastresponse.Append("</array></map>");
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 } 319 }
335 else 320 else
321 lastresponse.Append("<map><key>folders</key><array /></map>");
322
323 if(tmpbadfolders.Length > 0)
336 { 324 {
337 if (bad_folders_response.Length != 0) 325 lastresponse.Append("<map><key>bad_folders</key><array>");
338 { 326 lastresponse.Append(tmpbadfolders.ToString());
339 response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>"; 327 lastresponse.Append("</array></map>");
340 }
341 else
342 {
343 response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
344 }
345 } 328 }
329 lastresponse.Append("</llsd>");
346 330
347 // m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request"); 331 return lastresponse.ToString();
348 //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);
349
350 return response;
351
352 // }
353 } 332 }
354 333
355 /// <summary> 334 /// <summary>
@@ -436,108 +415,7 @@ namespace OpenSim.Capabilities.Handlers
436 itemsToReturn.Insert(0, linkedItem); 415 itemsToReturn.Insert(0, linkedItem);
437 } 416 }
438 } 417 }
439
440 // Now scan for folder links and insert the items they target and those links at the head of the return data
441
442/* dont send contents of LinkFolders.
443from docs seems this was never a spec
444
445 foreach (InventoryItemBase item in originalItems)
446 {
447 if (item.AssetType == (int)AssetType.LinkFolder)
448 {
449 InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID);
450 List<InventoryItemBase> links = linkedFolderContents.Items;
451
452 itemsToReturn.InsertRange(0, links);
453
454 foreach (InventoryItemBase link in linkedFolderContents.Items)
455 {
456 // Take care of genuinely broken links where the target doesn't exist
457 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
458 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
459 // rather than having to keep track of every folder requested in the recursion.
460 if (link != null)
461 {
462// m_log.DebugFormat(
463// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}",
464// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name);
465
466 InventoryItemBase linkedItem
467 = m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
468
469 if (linkedItem != null)
470 itemsToReturn.Insert(0, linkedItem);
471 }
472 }
473 }
474 }
475*/
476 } 418 }
477
478// foreach (InventoryItemBase item in contents.Items)
479// {
480// m_log.DebugFormat(
481// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}",
482// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID);
483// }
484
485 // =====
486
487//
488// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
489// {
490// m_log.DebugFormat(
491// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}",
492// linkedItem.Name, folderID, agentID);
493//
494// contents.Items.Add(linkedItem);
495// }
496//
497// // If the folder requested contains links, then we need to send those folders first, otherwise the links
498// // will be broken in the viewer.
499// HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>();
500// foreach (InventoryItemBase item in contents.Items)
501// {
502// if (item.AssetType == (int)AssetType.Link)
503// {
504// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
505//
506// // Take care of genuinely broken links where the target doesn't exist
507// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
508// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
509// // rather than having to keep track of every folder requested in the recursion.
510// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
511// {
512// // We don't need to send the folder if source and destination of the link are in the same
513// // folder.
514// if (linkedItem.Folder != containingFolder.ID)
515// linkedItemFolderIdsToSend.Add(linkedItem.Folder);
516// }
517// }
518// }
519//
520// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend)
521// {
522// m_log.DebugFormat(
523// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}",
524// linkedItemFolderId, folderID, agentID);
525//
526// int dummyVersion;
527// InventoryCollection linkedCollection
528// = Fetch(
529// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion);
530//
531// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId);
532// linkedFolder.Owner = agentID;
533// linkedFolder = m_InventoryService.GetFolder(linkedFolder);
534//
535//// contents.Folders.AddRange(linkedCollection.Folders);
536//
537// contents.Folders.Add(linkedFolder);
538// contents.Items.AddRange(linkedCollection.Items);
539// }
540// }
541 } 419 }
542 } 420 }
543 else 421 else
@@ -550,33 +428,26 @@ from docs seems this was never a spec
550 428
551 } 429 }
552 430
553 private void AddLibraryFolders(List<LLSDFetchInventoryDescendents> fetchFolders, List<InventoryCollectionWithDescendents> result) 431 private void AddLibraryFolders(List<LLSDFetchInventoryDescendents> libFolders, List<InventoryCollectionWithDescendents> result)
554 { 432 {
555 InventoryFolderImpl fold; 433 InventoryFolderImpl fold;
556 if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null) 434 foreach (LLSDFetchInventoryDescendents f in libFolders)
557 { 435 {
558 List<LLSDFetchInventoryDescendents> libfolders = fetchFolders.FindAll(f => f.owner_id == m_LibraryService.LibraryRootFolder.Owner); 436 if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null)
559 fetchFolders.RemoveAll(f => libfolders.Contains(f));
560
561 //m_log.DebugFormat("[XXX]: Found {0} library folders in request", libfolders.Count);
562
563 foreach (LLSDFetchInventoryDescendents f in libfolders)
564 { 437 {
565 if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null) 438 InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents();
566 { 439 ret.Collection = new InventoryCollection();
567 InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents(); 440// ret.Collection.Folders = new List<InventoryFolderBase>();
568 ret.Collection = new InventoryCollection(); 441 ret.Collection.Folders = fold.RequestListOfFolders();
569 ret.Collection.Folders = new List<InventoryFolderBase>(); 442 ret.Collection.Items = fold.RequestListOfItems();
570 ret.Collection.Items = fold.RequestListOfItems(); 443 ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner;
571 ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner; 444 ret.Collection.FolderID = f.folder_id;
572 ret.Collection.FolderID = f.folder_id; 445 ret.Collection.Version = fold.Version;
573 ret.Collection.Version = fold.Version; 446
574 447 ret.Descendents = ret.Collection.Items.Count + ret.Collection.Folders.Count;
575 ret.Descendents = ret.Collection.Items.Count; 448 result.Add(ret);
576 result.Add(ret); 449
577 450 //m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID);
578 //m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID);
579 }
580 } 451 }
581 } 452 }
582 } 453 }
@@ -589,57 +460,97 @@ from docs seems this was never a spec
589 // FIXME MAYBE: We're not handling sortOrder! 460 // FIXME MAYBE: We're not handling sortOrder!
590 461
591 List<InventoryCollectionWithDescendents> result = new List<InventoryCollectionWithDescendents>(); 462 List<InventoryCollectionWithDescendents> result = new List<InventoryCollectionWithDescendents>();
463 if(fetchFolders.Count <= 0)
464 return result;
465
466 List<LLSDFetchInventoryDescendents> libFolders = new List<LLSDFetchInventoryDescendents>();
467 List<LLSDFetchInventoryDescendents> otherFolders = new List<LLSDFetchInventoryDescendents>();
468 HashSet<UUID> libIDs = new HashSet<UUID>();
469 HashSet<UUID> otherIDs = new HashSet<UUID>();
592 470
593 AddLibraryFolders(fetchFolders, result); 471 bool dolib = (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null);
472 UUID libOwner = UUID.Zero;
473 if(dolib)
474 libOwner = m_LibraryService.LibraryRootFolder.Owner;
594 475
595 // Filter folder Zero right here. Some viewers (Firestorm) send request for folder Zero, which doesn't make sense 476 // Filter folder Zero right here. Some viewers (Firestorm) send request for folder Zero, which doesn't make sense
596 // and can kill the sim (all root folders have parent_id Zero) 477 // and can kill the sim (all root folders have parent_id Zero)
597 LLSDFetchInventoryDescendents zero = fetchFolders.Find(f => f.folder_id == UUID.Zero); 478 // send something.
598 if (zero != null) 479 foreach(LLSDFetchInventoryDescendents f in fetchFolders)
599 { 480 {
600 fetchFolders.Remove(zero); 481 if (f.folder_id == UUID.Zero)
601 BadFolder(zero, null, bad_folders); 482 {
483 InventoryCollectionWithDescendents zeroColl = new InventoryCollectionWithDescendents();
484 zeroColl.Collection = new InventoryCollection();
485 zeroColl.Collection.OwnerID = f.owner_id;
486 zeroColl.Collection.Version = 0;
487 zeroColl.Collection.FolderID = f.folder_id;
488 zeroColl.Descendents = 0;
489 result.Add(zeroColl);
490 continue;
491 }
492 if(dolib && f.owner_id == libOwner)
493 {
494 if(libIDs.Contains(f.folder_id))
495 continue;
496 libIDs.Add(f.folder_id);
497 libFolders.Add(f);
498 continue;
499 }
500 if(otherIDs.Contains(f.folder_id))
501 continue;
502 otherIDs.Add(f.folder_id);
503 otherFolders.Add(f);
602 } 504 }
603 505
604 if (fetchFolders.Count > 0) 506
605 { 507 if(otherFolders.Count > 0)
606 UUID[] fids = new UUID[fetchFolders.Count]; 508 {
509 UUID[] fids = new UUID[otherFolders.Count];
607 int i = 0; 510 int i = 0;
608 foreach (LLSDFetchInventoryDescendents f in fetchFolders) 511 foreach (LLSDFetchInventoryDescendents f in otherFolders)
609 fids[i++] = f.folder_id; 512 fids[i++] = f.folder_id;
610 513
611 //m_log.DebugFormat("[XXX]: {0}", string.Join(",", fids)); 514 //m_log.DebugFormat("[XXX]: {0}", string.Join(",", fids));
612 515
613 InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(fetchFolders[0].owner_id, fids); 516 InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(otherFolders[0].owner_id, fids);
614 517
615 if (fetchedContents == null || (fetchedContents != null && fetchedContents.Length == 0)) 518 if (fetchedContents == null)
519 return null;
520
521 if (fetchedContents.Length == 0)
616 { 522 {
617 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of multiple folders for user {0}", fetchFolders[0].owner_id); 523 foreach (LLSDFetchInventoryDescendents freq in otherFolders)
618 foreach (LLSDFetchInventoryDescendents freq in fetchFolders)
619 BadFolder(freq, null, bad_folders); 524 BadFolder(freq, null, bad_folders);
620 return null;
621 } 525 }
622 526 else
623 i = 0;
624 // Do some post-processing. May need to fetch more from inv server for links
625 foreach (InventoryCollection contents in fetchedContents)
626 { 527 {
627 // Find the original request 528 i = 0;
628 LLSDFetchInventoryDescendents freq = fetchFolders[i++]; 529 // Do some post-processing. May need to fetch more from inv server for links
530 foreach (InventoryCollection contents in fetchedContents)
531 {
532 // Find the original request
533 LLSDFetchInventoryDescendents freq = otherFolders[i++];
629 534
630 InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents(); 535 InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents();
631 coll.Collection = contents; 536 coll.Collection = contents;
632 537
633 if (BadFolder(freq, contents, bad_folders)) 538 if (BadFolder(freq, contents, bad_folders))
634 continue; 539 continue;
635 540
636 // Next: link management 541 // Next: link management
637 ProcessLinks(freq, coll); 542 ProcessLinks(freq, coll);
638 543
639 result.Add(coll); 544 result.Add(coll);
545 }
640 } 546 }
641 } 547 }
642 548
549 if(dolib && libFolders.Count > 0)
550 {
551 AddLibraryFolders(libFolders, result);
552 }
553
643 return result; 554 return result;
644 } 555 }
645 556
@@ -666,35 +577,8 @@ from docs seems this was never a spec
666 } 577 }
667 else 578 else
668 { 579 {
669 // Was it really a request for folder Zero? 580 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id);
670 // This is an overkill, but Firestorm really asks for folder Zero. 581 bad_folders.Add(freq.folder_id);
671 // I'm leaving the code here for the time being, but commented.
672 if (freq.folder_id == UUID.Zero)
673 {
674 //coll.Collection.OwnerID = freq.owner_id;
675 //coll.Collection.FolderID = contents.FolderID;
676 //containingFolder = m_InventoryService.GetRootFolder(freq.owner_id);
677 //if (containingFolder != null)
678 //{
679 // m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Request for parent of folder {0}", containingFolder.ID);
680 // coll.Collection.Folders.Clear();
681 // coll.Collection.Folders.Add(containingFolder);
682 // if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null)
683 // {
684 // InventoryFolderBase lib = new InventoryFolderBase(m_LibraryService.LibraryRootFolder.ID, m_LibraryService.LibraryRootFolder.Owner);
685 // lib.Name = m_LibraryService.LibraryRootFolder.Name;
686 // lib.Type = m_LibraryService.LibraryRootFolder.Type;
687 // lib.Version = m_LibraryService.LibraryRootFolder.Version;
688 // coll.Collection.Folders.Add(lib);
689 // }
690 // coll.Collection.Items.Clear();
691 //}
692 }
693 else
694 {
695 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id);
696 bad_folders.Add(freq.folder_id);
697 }
698 bad = true; 582 bad = true;
699 } 583 }
700 } 584 }
@@ -708,42 +592,21 @@ from docs seems this was never a spec
708 592
709 if (freq.fetch_items && contents.Items != null) 593 if (freq.fetch_items && contents.Items != null)
710 { 594 {
711 List<InventoryItemBase> itemsToReturn = contents.Items; 595 // viewers are lasy and want a copy of the linked item sent before the link to it
712 596
713 // descendents must only include the links, not the linked items we add 597 // descendents must only include the links, not the linked items we add
714 coll.Descendents = itemsToReturn.Count; 598 coll.Descendents = contents.Items.Count + contents.Folders.Count;
715 599
716 // Add target items for links in this folder before the links themselves. 600 // look for item links
717 List<UUID> itemIDs = new List<UUID>(); 601 List<UUID> itemIDs = new List<UUID>();
718 List<UUID> folderIDs = new List<UUID>(); 602 foreach (InventoryItemBase item in contents.Items)
719 foreach (InventoryItemBase item in itemsToReturn)
720 { 603 {
721 //m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType); 604 //m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType);
722 if (item.AssetType == (int)AssetType.Link) 605 if (item.AssetType == (int)AssetType.Link)
723 itemIDs.Add(item.AssetID); 606 itemIDs.Add(item.AssetID);
724
725// else if (item.AssetType == (int)AssetType.LinkFolder)
726// folderIDs.Add(item.AssetID);
727 }
728
729 //m_log.DebugFormat("[XXX]: folder {0} has {1} links and {2} linkfolders", contents.FolderID, itemIDs.Count, folderIDs.Count);
730
731 // Scan for folder links and insert the items they target and those links at the head of the return data
732 if (folderIDs.Count > 0)
733 {
734 InventoryCollection[] linkedFolders = m_InventoryService.GetMultipleFoldersContent(coll.Collection.OwnerID, folderIDs.ToArray());
735 foreach (InventoryCollection linkedFolderContents in linkedFolders)
736 {
737 if (linkedFolderContents == null)
738 continue;
739
740 List<InventoryItemBase> links = linkedFolderContents.Items;
741
742 itemsToReturn.InsertRange(0, links);
743
744 }
745 } 607 }
746 608
609 // get the linked if any
747 if (itemIDs.Count > 0) 610 if (itemIDs.Count > 0)
748 { 611 {
749 InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray()); 612 InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray());
@@ -758,13 +621,11 @@ from docs seems this was never a spec
758 linked[i++] = m_InventoryService.GetItem(freq.owner_id, id); 621 linked[i++] = m_InventoryService.GetItem(freq.owner_id, id);
759 } 622 }
760 } 623 }
761 624
762 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Processing folder {0}. Existing items:", freq.folder_id);
763 //foreach (InventoryItemBase item in itemsToReturn)
764 // m_log.DebugFormat("[XXX]: {0} {1} {2}", item.Name, item.AssetType, item.Folder);
765
766 if (linked != null) 625 if (linked != null)
767 { 626 {
627 List<InventoryItemBase> linkedItems = new List<InventoryItemBase>();
628 // check for broken
768 foreach (InventoryItemBase linkedItem in linked) 629 foreach (InventoryItemBase linkedItem in linked)
769 { 630 {
770 // Take care of genuinely broken links where the target doesn't exist 631 // Take care of genuinely broken links where the target doesn't exist
@@ -773,14 +634,16 @@ from docs seems this was never a spec
773 // rather than having to keep track of every folder requested in the recursion. 634 // rather than having to keep track of every folder requested in the recursion.
774 if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) 635 if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
775 { 636 {
776 itemsToReturn.Insert(0, linkedItem); 637 linkedItems.Add(linkedItem);
777 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder); 638 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder);
778 } 639 }
779 } 640 }
641 // insert them
642 if(linkedItems.Count > 0)
643 contents.Items.InsertRange(0,linkedItems);
780 } 644 }
781 } 645 }
782 } 646 }
783
784 } 647 }
785 648
786 /// <summary> 649 /// <summary>
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs
index 4143aa3..1e9a993 100644
--- a/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs
@@ -267,6 +267,7 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
267 [Test] 267 [Test]
268 public void Test_005_FolderZero() 268 public void Test_005_FolderZero()
269 { 269 {
270
270 TestHelpers.InMethod(); 271 TestHelpers.InMethod();
271 272
272 Init(); 273 Init();
@@ -283,11 +284,11 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
283 284
284 Assert.That(llsdresponse != null, Is.True, "Incorrect null response"); 285 Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
285 Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response"); 286 Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");
286 Assert.That(llsdresponse.Contains("bad_folders</key><array><uuid>00000000-0000-0000-0000-000000000000"), Is.True, "Folder Zero should be a bad folder"); 287 // we do return a answer now
288 //Assert.That(llsdresponse.Contains("bad_folders</key><array><uuid>00000000-0000-0000-0000-000000000000"), Is.True, "Folder Zero should be a bad folder");
287 289
288 Console.WriteLine(llsdresponse); 290 Console.WriteLine(llsdresponse);
289 } 291 }
290
291 } 292 }
292 293
293} \ No newline at end of file 294} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
index a9b81f3..a0471bb 100644
--- a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
@@ -64,10 +64,7 @@ namespace OpenSim.Capabilities.Handlers
64 Hashtable ret = new Hashtable(); 64 Hashtable ret = new Hashtable();
65 ret["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound; 65 ret["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
66 ret["content_type"] = "text/plain"; 66 ret["content_type"] = "text/plain";
67 ret["keepalive"] = false;
68 ret["reusecontext"] = false;
69 ret["int_bytes"] = 0; 67 ret["int_bytes"] = 0;
70 ret["int_lod"] = 0;
71 string MeshStr = (string)request["mesh_id"]; 68 string MeshStr = (string)request["mesh_id"];
72 69
73 70
@@ -76,6 +73,8 @@ namespace OpenSim.Capabilities.Handlers
76 if (m_assetService == null) 73 if (m_assetService == null)
77 { 74 {
78 m_log.Error("[GETMESH]: Cannot fetch mesh " + MeshStr + " without an asset service"); 75 m_log.Error("[GETMESH]: Cannot fetch mesh " + MeshStr + " without an asset service");
76 ret["keepalive"] = false;
77 return ret;
79 } 78 }
80 79
81 UUID meshID; 80 UUID meshID;
@@ -101,10 +100,7 @@ namespace OpenSim.Capabilities.Handlers
101 Hashtable responsedata = new Hashtable(); 100 Hashtable responsedata = new Hashtable();
102 responsedata["int_response_code"] = 400; //501; //410; //404; 101 responsedata["int_response_code"] = 400; //501; //410; //404;
103 responsedata["content_type"] = "text/plain"; 102 responsedata["content_type"] = "text/plain";
104 responsedata["keepalive"] = false;
105 responsedata["str_response_string"] = "Request wasn't what was expected"; 103 responsedata["str_response_string"] = "Request wasn't what was expected";
106 responsedata["reusecontext"] = false;
107 responsedata["int_lod"] = 0;
108 responsedata["int_bytes"] = 0; 104 responsedata["int_bytes"] = 0;
109 105
110 string meshStr = string.Empty; 106 string meshStr = string.Empty;
@@ -118,10 +114,8 @@ namespace OpenSim.Capabilities.Handlers
118 if (m_assetService == null) 114 if (m_assetService == null)
119 { 115 {
120 responsedata["int_response_code"] = 404; //501; //410; //404; 116 responsedata["int_response_code"] = 404; //501; //410; //404;
121 responsedata["content_type"] = "text/plain";
122 responsedata["keepalive"] = false; 117 responsedata["keepalive"] = false;
123 responsedata["str_response_string"] = "The asset service is unavailable. So is your mesh."; 118 responsedata["str_response_string"] = "The asset service is unavailable. So is your mesh.";
124 responsedata["reusecontext"] = false;
125 return responsedata; 119 return responsedata;
126 } 120 }
127 121
@@ -155,10 +149,7 @@ namespace OpenSim.Capabilities.Handlers
155 { 149 {
156 responsedata["int_response_code"] = 404; //501; //410; //404; 150 responsedata["int_response_code"] = 404; //501; //410; //404;
157 responsedata["content_type"] = "text/plain"; 151 responsedata["content_type"] = "text/plain";
158 responsedata["keepalive"] = false;
159 responsedata["str_response_string"] = "This range doesnt exist."; 152 responsedata["str_response_string"] = "This range doesnt exist.";
160 responsedata["reusecontext"] = false;
161 responsedata["int_lod"] = 3;
162 return responsedata; 153 return responsedata;
163 } 154 }
164 else 155 else
@@ -169,28 +160,11 @@ namespace OpenSim.Capabilities.Handlers
169 160
170 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); 161 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
171 162
172 if (start > 20000)
173 {
174 responsedata["int_lod"] = 3;
175 }
176 else if (start < 4097)
177 {
178 responsedata["int_lod"] = 1;
179 }
180 else
181 {
182 responsedata["int_lod"] = 2;
183 }
184
185
186 if (start == 0 && len == mesh.Data.Length) // well redudante maybe 163 if (start == 0 && len == mesh.Data.Length) // well redudante maybe
187 { 164 {
188 responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.OK; 165 responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
189 responsedata["bin_response_data"] = mesh.Data; 166 responsedata["bin_response_data"] = mesh.Data;
190 responsedata["int_bytes"] = mesh.Data.Length; 167 responsedata["int_bytes"] = mesh.Data.Length;
191 responsedata["reusecontext"] = false;
192 responsedata["int_lod"] = 3;
193
194 } 168 }
195 else 169 else
196 { 170 {
@@ -203,7 +177,6 @@ namespace OpenSim.Capabilities.Handlers
203 Array.Copy(mesh.Data, start, d, 0, len); 177 Array.Copy(mesh.Data, start, d, 0, len);
204 responsedata["bin_response_data"] = d; 178 responsedata["bin_response_data"] = d;
205 responsedata["int_bytes"] = len; 179 responsedata["int_bytes"] = len;
206 responsedata["reusecontext"] = false;
207 } 180 }
208 } 181 }
209 } 182 }
@@ -213,8 +186,6 @@ namespace OpenSim.Capabilities.Handlers
213 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data); 186 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
214 responsedata["content_type"] = "application/vnd.ll.mesh"; 187 responsedata["content_type"] = "application/vnd.ll.mesh";
215 responsedata["int_response_code"] = 200; 188 responsedata["int_response_code"] = 200;
216 responsedata["reusecontext"] = false;
217 responsedata["int_lod"] = 3;
218 } 189 }
219 } 190 }
220 else 191 else
@@ -222,8 +193,6 @@ namespace OpenSim.Capabilities.Handlers
222 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data); 193 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
223 responsedata["content_type"] = "application/vnd.ll.mesh"; 194 responsedata["content_type"] = "application/vnd.ll.mesh";
224 responsedata["int_response_code"] = 200; 195 responsedata["int_response_code"] = 200;
225 responsedata["reusecontext"] = false;
226 responsedata["int_lod"] = 3;
227 } 196 }
228 } 197 }
229 // Optionally add additional mesh types here 198 // Optionally add additional mesh types here
@@ -231,10 +200,7 @@ namespace OpenSim.Capabilities.Handlers
231 { 200 {
232 responsedata["int_response_code"] = 404; //501; //410; //404; 201 responsedata["int_response_code"] = 404; //501; //410; //404;
233 responsedata["content_type"] = "text/plain"; 202 responsedata["content_type"] = "text/plain";
234 responsedata["keepalive"] = false;
235 responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh."; 203 responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh.";
236 responsedata["reusecontext"] = false;
237 responsedata["int_lod"] = 1;
238 return responsedata; 204 return responsedata;
239 } 205 }
240 } 206 }
@@ -242,10 +208,7 @@ namespace OpenSim.Capabilities.Handlers
242 { 208 {
243 responsedata["int_response_code"] = 404; //501; //410; //404; 209 responsedata["int_response_code"] = 404; //501; //410; //404;
244 responsedata["content_type"] = "text/plain"; 210 responsedata["content_type"] = "text/plain";
245 responsedata["keepalive"] = false;
246 responsedata["str_response_string"] = "Your Mesh wasn't found. Sorry!"; 211 responsedata["str_response_string"] = "Your Mesh wasn't found. Sorry!";
247 responsedata["reusecontext"] = false;
248 responsedata["int_lod"] = 0;
249 return responsedata; 212 return responsedata;
250 } 213 }
251 } 214 }