diff options
Diffstat (limited to 'OpenSim/Capabilities/Handlers/FetchInventory')
-rw-r--r-- | OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs | 437 |
1 files changed, 150 insertions, 287 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; | |||
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Linq; | 31 | using System.Linq; |
32 | using System.Reflection; | 32 | using System.Reflection; |
33 | using System.Text; | ||
33 | using log4net; | 34 | using log4net; |
34 | using Nini.Config; | 35 | using Nini.Config; |
35 | using OpenMetaverse; | 36 | using 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. | ||
443 | from 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> |