private void AddLibraryFolders(List <LLSDFetchInventoryDescendents> fetchFolders, List <InventoryCollectionWithDescendents> result) { InventoryFolderImpl fold; if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null) { List <LLSDFetchInventoryDescendents> libfolders = fetchFolders.FindAll(f => f.owner_id == m_LibraryService.LibraryRootFolder.Owner); fetchFolders.RemoveAll(f => libfolders.Contains(f)); //m_log.DebugFormat("[XXX]: Found {0} library folders in request", libfolders.Count); foreach (LLSDFetchInventoryDescendents f in libfolders) { if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null) { InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents(); ret.Collection = new InventoryCollection(); ret.Collection.Folders = new List <InventoryFolderBase>(); ret.Collection.Items = fold.RequestListOfItems(); ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner; ret.Collection.FolderID = f.folder_id; ret.Collection.Version = fold.Version; ret.Descendents = ret.Collection.Items.Count; result.Add(ret); //m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID); } } } }
private List <InventoryCollectionWithDescendents> Fetch(List <LLSDFetchInventoryDescendents> fetchFolders, List <UUID> bad_folders) { //m_log.DebugFormat( // "[WEB FETCH INV DESC HANDLER]: Fetching {0} folders for owner {1}", fetchFolders.Count, fetchFolders[0].owner_id); // FIXME MAYBE: We're not handling sortOrder! List <InventoryCollectionWithDescendents> result = new List <InventoryCollectionWithDescendents>(); AddLibraryFolders(fetchFolders, result); if (fetchFolders.Count > 0) { UUID[] fids = new UUID[fetchFolders.Count]; int i = 0; foreach (LLSDFetchInventoryDescendents f in fetchFolders) { fids[i++] = f.folder_id; } //m_log.DebugFormat("[XXX]: {0}", string.Join(",", fids)); InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(fetchFolders[0].owner_id, fids); if (fetchedContents == null || (fetchedContents != null && fetchedContents.Length == 0)) { //m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of multiple folders for user {0}", fetchFolders[0].owner_id); return(null); } i = 0; // Do some post-processing. May need to fetch more from inv server for links foreach (InventoryCollection contents in fetchedContents) { // Find the original request LLSDFetchInventoryDescendents freq = fetchFolders[i++]; InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents(); coll.Collection = contents; if (BadFolder(freq, contents, bad_folders)) { continue; } // Next: link management ProcessLinks(freq, coll); result.Add(coll); } } return(result); }
private void AddLibraryFolders(List <LLSDFetchInventoryDescendents> libFolders, List <InventoryCollectionWithDescendents> result) { InventoryFolderImpl fold; foreach (LLSDFetchInventoryDescendents f in libFolders) { if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null) { InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents(); ret.Collection = new InventoryCollection(); // ret.Collection.Folders = new List<InventoryFolderBase>(); ret.Collection.Folders = fold.RequestListOfFolders(); ret.Collection.Items = fold.RequestListOfItems(); ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner; ret.Collection.FolderID = f.folder_id; ret.Collection.Version = fold.Version; ret.Descendents = ret.Collection.Items.Count + ret.Collection.Folders.Count; result.Add(ret); //m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID); } } }
private void ProcessLinks(LLSDFetchInventoryDescendents freq, InventoryCollectionWithDescendents coll) { InventoryCollection contents = coll.Collection; if (freq.fetch_items && contents.Items != null) { List <InventoryItemBase> itemsToReturn = contents.Items; // descendents must only include the links, not the linked items we add coll.Descendents = itemsToReturn.Count; // Add target items for links in this folder before the links themselves. List <UUID> itemIDs = new List <UUID>(); List <UUID> folderIDs = new List <UUID>(); foreach (InventoryItemBase item in itemsToReturn) { //m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType); if (item.AssetType == (int)AssetType.Link) { itemIDs.Add(item.AssetID); } else if (item.AssetType == (int)AssetType.LinkFolder) { folderIDs.Add(item.AssetID); } } //m_log.DebugFormat("[XXX]: folder {0} has {1} links and {2} linkfolders", contents.FolderID, itemIDs.Count, folderIDs.Count); // Scan for folder links and insert the items they target and those links at the head of the return data if (folderIDs.Count > 0) { InventoryCollection[] linkedFolders = m_InventoryService.GetMultipleFoldersContent(coll.Collection.OwnerID, folderIDs.ToArray()); foreach (InventoryCollection linkedFolderContents in linkedFolders) { if (linkedFolderContents == null) { continue; } List <InventoryItemBase> links = linkedFolderContents.Items; itemsToReturn.InsertRange(0, links); } } if (itemIDs.Count > 0) { InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray()); if (linked == null) { // OMG!!! One by one!!! This is fallback code, in case the backend isn't updated m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one."); linked = new InventoryItemBase[itemIDs.Count]; int i = 0; InventoryItemBase item = new InventoryItemBase(); item.Owner = freq.owner_id; foreach (UUID id in itemIDs) { item.ID = id; linked[i++] = m_InventoryService.GetItem(item); } } //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Processing folder {0}. Existing items:", freq.folder_id); //foreach (InventoryItemBase item in itemsToReturn) // m_log.DebugFormat("[XXX]: {0} {1} {2}", item.Name, item.AssetType, item.Folder); if (linked != null) { foreach (InventoryItemBase linkedItem in linked) { // Take care of genuinely broken links where the target doesn't exist // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles // rather than having to keep track of every folder requested in the recursion. if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) { itemsToReturn.Insert(0, linkedItem); //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder); } } } } } }
private void ProcessLinks(LLSDFetchInventoryDescendents freq, InventoryCollectionWithDescendents coll) { InventoryCollection contents = coll.Collection; if (freq.fetch_items && contents.Items != null) { // viewers are lasy and want a copy of the linked item sent before the link to it // descendents must only include the links, not the linked items we add coll.Descendents = contents.Items.Count + contents.Folders.Count; // look for item links List <UUID> itemIDs = new List <UUID>(); foreach (InventoryItemBase item in contents.Items) { //m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType); if (item.AssetType == (int)AssetType.Link) { itemIDs.Add(item.AssetID); } } // get the linked if any if (itemIDs.Count > 0) { InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray()); if (linked == null) { // OMG!!! One by one!!! This is fallback code, in case the backend isn't updated m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one."); linked = new InventoryItemBase[itemIDs.Count]; int i = 0; foreach (UUID id in itemIDs) { linked[i++] = m_InventoryService.GetItem(freq.owner_id, id); } } if (linked != null) { List <InventoryItemBase> linkedItems = new List <InventoryItemBase>(); // check for broken foreach (InventoryItemBase linkedItem in linked) { // Take care of genuinely broken links where the target doesn't exist // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles // rather than having to keep track of every folder requested in the recursion. if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) { linkedItems.Add(linkedItem); //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder); } } // insert them if (linkedItems.Count > 0) { contents.Items.InsertRange(0, linkedItems); } } } } }
private List <InventoryCollectionWithDescendents> Fetch(List <LLSDFetchInventoryDescendents> fetchFolders, List <UUID> bad_folders) { //m_log.DebugFormat( // "[WEB FETCH INV DESC HANDLER]: Fetching {0} folders for owner {1}", fetchFolders.Count, fetchFolders[0].owner_id); // FIXME MAYBE: We're not handling sortOrder! List <InventoryCollectionWithDescendents> result = new List <InventoryCollectionWithDescendents>(); List <LLSDFetchInventoryDescendents> libFolders = new List <LLSDFetchInventoryDescendents>(); List <LLSDFetchInventoryDescendents> otherFolders = new List <LLSDFetchInventoryDescendents>(); HashSet <UUID> libIDs = new HashSet <UUID>(); HashSet <UUID> otherIDs = new HashSet <UUID>(); bool dolib = (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null); UUID libOwner = UUID.Zero; if (dolib) { libOwner = m_LibraryService.LibraryRootFolder.Owner; } // Filter folder Zero right here. Some viewers (Firestorm) send request for folder Zero, which doesn't make sense // and can kill the sim (all root folders have parent_id Zero) // send something. bool doneZeroID = false; foreach (LLSDFetchInventoryDescendents f in fetchFolders) { if (f.folder_id == UUID.Zero) { if (doneZeroID) { continue; } doneZeroID = true; InventoryCollectionWithDescendents zeroColl = new InventoryCollectionWithDescendents(); zeroColl.Collection = new InventoryCollection(); zeroColl.Collection.OwnerID = f.owner_id; zeroColl.Collection.Version = 0; zeroColl.Collection.FolderID = f.folder_id; zeroColl.Descendents = 0; result.Add(zeroColl); continue; } if (dolib && f.owner_id == libOwner) { if (libIDs.Contains(f.folder_id)) { continue; } libIDs.Add(f.folder_id); libFolders.Add(f); continue; } if (otherIDs.Contains(f.folder_id)) { continue; } otherIDs.Add(f.folder_id); otherFolders.Add(f); } if (otherFolders.Count > 0) { int i = 0; //m_log.DebugFormat("[XXX]: {0}", string.Join(",", fids)); InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(otherFolders[0].owner_id, otherIDs.ToArray()); if (fetchedContents == null) { return(null); } if (fetchedContents.Length == 0) { foreach (LLSDFetchInventoryDescendents freq in otherFolders) { BadFolder(freq, null, bad_folders); } } else { i = 0; // Do some post-processing. May need to fetch more from inv server for links foreach (InventoryCollection contents in fetchedContents) { // Find the original request LLSDFetchInventoryDescendents freq = otherFolders[i++]; InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents(); coll.Collection = contents; if (BadFolder(freq, contents, bad_folders)) { continue; } // Next: link management ProcessLinks(freq, coll); result.Add(coll); } } } if (dolib && libFolders.Count > 0) { AddLibraryFolders(libFolders, result); } return(result); }
private void ProcessLinks(LLSDFetchInventoryDescendents freq, InventoryCollectionWithDescendents coll) { InventoryCollection contents = coll.Collection; if (freq.fetch_items && contents.Items != null) { List<InventoryItemBase> itemsToReturn = contents.Items; // descendents must only include the links, not the linked items we add coll.Descendents = itemsToReturn.Count; // Add target items for links in this folder before the links themselves. List<UUID> itemIDs = new List<UUID>(); List<UUID> folderIDs = new List<UUID>(); foreach (InventoryItemBase item in itemsToReturn) { //m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType); if (item.AssetType == (int)AssetType.Link) itemIDs.Add(item.AssetID); // else if (item.AssetType == (int)AssetType.LinkFolder) // folderIDs.Add(item.AssetID); } //m_log.DebugFormat("[XXX]: folder {0} has {1} links and {2} linkfolders", contents.FolderID, itemIDs.Count, folderIDs.Count); // Scan for folder links and insert the items they target and those links at the head of the return data if (folderIDs.Count > 0) { InventoryCollection[] linkedFolders = m_InventoryService.GetMultipleFoldersContent(coll.Collection.OwnerID, folderIDs.ToArray()); foreach (InventoryCollection linkedFolderContents in linkedFolders) { if (linkedFolderContents == null) continue; List<InventoryItemBase> links = linkedFolderContents.Items; itemsToReturn.InsertRange(0, links); } } if (itemIDs.Count > 0) { InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray()); if (linked == null) { // OMG!!! One by one!!! This is fallback code, in case the backend isn't updated m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one."); linked = new InventoryItemBase[itemIDs.Count]; int i = 0; InventoryItemBase item = new InventoryItemBase(); item.Owner = freq.owner_id; foreach (UUID id in itemIDs) { item.ID = id; linked[i++] = m_InventoryService.GetItem(item); } } //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Processing folder {0}. Existing items:", freq.folder_id); //foreach (InventoryItemBase item in itemsToReturn) // m_log.DebugFormat("[XXX]: {0} {1} {2}", item.Name, item.AssetType, item.Folder); if (linked != null) { foreach (InventoryItemBase linkedItem in linked) { // Take care of genuinely broken links where the target doesn't exist // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles // rather than having to keep track of every folder requested in the recursion. if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) { itemsToReturn.Insert(0, linkedItem); //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder); } } } } } }
private List<InventoryCollectionWithDescendents> Fetch(List<LLSDFetchInventoryDescendents> fetchFolders, List<UUID> bad_folders) { //m_log.DebugFormat( // "[WEB FETCH INV DESC HANDLER]: Fetching {0} folders for owner {1}", fetchFolders.Count, fetchFolders[0].owner_id); // FIXME MAYBE: We're not handling sortOrder! List<InventoryCollectionWithDescendents> result = new List<InventoryCollectionWithDescendents>(); AddLibraryFolders(fetchFolders, result); // Filter folder Zero right here. Some viewers (Firestorm) send request for folder Zero, which doesn't make sense // and can kill the sim (all root folders have parent_id Zero) LLSDFetchInventoryDescendents zero = fetchFolders.Find(f => f.folder_id == UUID.Zero); if (zero != null) { fetchFolders.Remove(zero); BadFolder(zero, null, bad_folders); } if (fetchFolders.Count > 0) { UUID[] fids = new UUID[fetchFolders.Count]; int i = 0; foreach (LLSDFetchInventoryDescendents f in fetchFolders) fids[i++] = f.folder_id; //m_log.DebugFormat("[XXX]: {0}", string.Join(",", fids)); InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(fetchFolders[0].owner_id, fids); if (fetchedContents == null || (fetchedContents != null && fetchedContents.Length == 0)) { m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of multiple folders for user {0}", fetchFolders[0].owner_id); foreach (LLSDFetchInventoryDescendents freq in fetchFolders) BadFolder(freq, null, bad_folders); return null; } i = 0; // Do some post-processing. May need to fetch more from inv server for links foreach (InventoryCollection contents in fetchedContents) { // Find the original request LLSDFetchInventoryDescendents freq = fetchFolders[i++]; InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents(); coll.Collection = contents; if (BadFolder(freq, contents, bad_folders)) continue; // Next: link management ProcessLinks(freq, coll); result.Add(coll); } } return result; }
private void AddLibraryFolders(List<LLSDFetchInventoryDescendents> fetchFolders, List<InventoryCollectionWithDescendents> result) { InventoryFolderImpl fold; if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null) { List<LLSDFetchInventoryDescendents> libfolders = fetchFolders.FindAll(f => f.owner_id == m_LibraryService.LibraryRootFolder.Owner); fetchFolders.RemoveAll(f => libfolders.Contains(f)); //m_log.DebugFormat("[XXX]: Found {0} library folders in request", libfolders.Count); foreach (LLSDFetchInventoryDescendents f in libfolders) { if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null) { InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents(); ret.Collection = new InventoryCollection(); ret.Collection.Folders = new List<InventoryFolderBase>(); ret.Collection.Items = fold.RequestListOfItems(); ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner; ret.Collection.FolderID = f.folder_id; ret.Collection.Version = fold.Version; ret.Descendents = ret.Collection.Items.Count; result.Add(ret); //m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID); } } } }