Example #1
0
        private bool BadFolder(LLSDFetchInventoryDescendents freq, InventoryCollection contents, List <UUID> bad_folders)
        {
            bool bad = false;

            if (contents == null)
            {
                bad_folders.Add(freq.folder_id);
                bad = true;
            }

            // The inventory server isn't sending FolderID in the collection...
            // Must fetch it individually
            else if (contents.FolderID == UUID.Zero)
            {
                InventoryFolderBase containingFolder = m_InventoryService.GetFolder(freq.owner_id, freq.folder_id);

                if (containingFolder != null)
                {
                    contents.FolderID = containingFolder.ID;
                    contents.OwnerID  = containingFolder.Owner;
                    contents.Version  = containingFolder.Version;
                }
                else
                {
                    m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id);
                    bad_folders.Add(freq.folder_id);
                    bad = true;
                }
            }

            return(bad);
        }
        private bool BadFolder(LLSDFetchInventoryDescendents freq, InventoryCollection contents, List <UUID> bad_folders)
        {
            if (contents == null)
            {
                bad_folders.Add(freq.folder_id);
                return(true);
            }

            // The inventory server isn't sending FolderID in the collection...
            // Must fetch it individually
            if (contents.FolderID == UUID.Zero)
            {
                InventoryFolderBase containingFolder = m_InventoryService.GetFolder(freq.owner_id, freq.folder_id);
                if (containingFolder == null)
                {
                    bad_folders.Add(freq.folder_id);
                    return(true);
                }
                contents.FolderID = containingFolder.ID;
                contents.OwnerID  = containingFolder.Owner;
                contents.Version  = containingFolder.Version;
            }

            return(false);
        }
        private bool BadFolder(LLSDFetchInventoryDescendents freq, InventoryCollection contents, List <UUID> bad_folders)
        {
            bool bad = false;

            if (contents == null)
            {
                bad_folders.Add(freq.folder_id);
                bad = true;
            }

            // The inventory server isn't sending FolderID in the collection...
            // Must fetch it individually
            else if (contents.FolderID == UUID.Zero)
            {
                InventoryFolderBase containingFolder = m_InventoryService.GetFolder(freq.owner_id, freq.folder_id);

                if (containingFolder != null)
                {
                    contents.FolderID = containingFolder.ID;
                    contents.OwnerID  = containingFolder.Owner;
                    contents.Version  = containingFolder.Version;
                }
                else
                {
                    // Was it really a request for folder Zero?
                    // This is an overkill, but Firestorm really asks for folder Zero.
                    // I'm leaving the code here for the time being, but commented.
                    if (freq.folder_id == UUID.Zero)
                    {
                        //coll.Collection.OwnerID = freq.owner_id;
                        //coll.Collection.FolderID = contents.FolderID;
                        //containingFolder = m_InventoryService.GetRootFolder(freq.owner_id);
                        //if (containingFolder != null)
                        //{
                        //    m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Request for parent of folder {0}", containingFolder.ID);
                        //    coll.Collection.Folders.Clear();
                        //    coll.Collection.Folders.Add(containingFolder);
                        //    if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null)
                        //    {
                        //        InventoryFolderBase lib = new InventoryFolderBase(m_LibraryService.LibraryRootFolder.ID, m_LibraryService.LibraryRootFolder.Owner);
                        //        lib.Name = m_LibraryService.LibraryRootFolder.Name;
                        //        lib.Type = m_LibraryService.LibraryRootFolder.Type;
                        //        lib.Version = m_LibraryService.LibraryRootFolder.Version;
                        //        coll.Collection.Folders.Add(lib);
                        //    }
                        //    coll.Collection.Items.Clear();
                        //}
                    }
                    else
                    {
                        m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id);
                        bad_folders.Add(freq.folder_id);
                    }
                    bad = true;
                }
            }

            return(bad);
        }
        /// <summary>
        /// Construct an LLSD reply packet to a CAPS inventory request
        /// </summary>
        /// <param name="invFetch"></param>
        /// <returns></returns>
        private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch)
        {
            LLSDInventoryDescendents    reply    = new LLSDInventoryDescendents();
            LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();

            contents.agent_id  = invFetch.owner_id;
            contents.owner_id  = invFetch.owner_id;
            contents.folder_id = invFetch.folder_id;

            reply.folders.Array.Add(contents);
            InventoryCollection inv = new InventoryCollection();

            inv.Folders = new List <InventoryFolderBase>();
            inv.Items   = new List <InventoryItemBase>();
            int version     = 0;
            int descendents = 0;

#pragma warning disable 0612
            inv = Fetch(
                invFetch.owner_id, invFetch.folder_id, invFetch.owner_id,
                invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents);
#pragma warning restore 0612

            if (inv != null && inv.Folders != null)
            {
                foreach (InventoryFolderBase invFolder in inv.Folders)
                {
                    contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
                }

                descendents += inv.Folders.Count;
            }

            if (inv != null && inv.Items != null)
            {
                foreach (InventoryItemBase invItem in inv.Items)
                {
                    contents.items.Array.Add(ConvertInventoryItem(invItem));
                }
            }

            contents.descendents = descendents;
            contents.version     = version;

            //m_log.DebugFormat(
            //    "[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}",
            //    invFetch.folder_id,
            //    invFetch.fetch_items,
            //    invFetch.fetch_folders,
            //    contents.items.Array.Count,
            //    contents.categories.Array.Count,
            //    invFetch.owner_id);

            return(reply);
        }
        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 ProcessLinks(LLSDFetchInventoryDescendents freq, InventoryCollection contents)
        {
            if (contents.Items == null || contents.Items.Count == 0)
            {
                return;
            }

            // viewers are lasy and want a copy of the linked item sent before the link to it

            // 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)
                {
                    List <InventoryItemBase> linkedItems = new List <InventoryItemBase>(linked.Length);
                    // 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);
                    }
                }
            }
        }
Example #7
0
        public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
        {
//            lock (m_fetchLock)
//            {
//                m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request {0}", request);

            // nasty temporary hack here, the linden client falsely
            // identifies the uuid 00000000-0000-0000-0000-000000000000
            // as a string which breaks us
            //
            // correctly mark it as a uuid
            //
            request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");

            // another hack <integer>1</integer> results in a
            // System.ArgumentException: Object type System.Int32 cannot
            // be converted to target type: System.Boolean
            //
            request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
            request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");

            Hashtable hash = new Hashtable();

            try
            {
                hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
            }
            catch (LLSD.LLSDParseException e)
            {
                m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
                m_log.Error("Request: " + request);
            }

            ArrayList foldersrequested = (ArrayList)hash["folders"];

            string response = "";

            for (int i = 0; i < foldersrequested.Count; i++)
            {
                string    inventoryitemstr = "";
                Hashtable inventoryhash    = (Hashtable)foldersrequested[i];

                LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();

                try
                {
                    LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
                }
                catch (Exception e)
                {
                    m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
                }
                LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);

                inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
                inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
                inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");

                response += inventoryitemstr;
            }

            if (response.Length == 0)
            {
                // Ter-guess: If requests fail a lot, the client seems to stop requesting descendants.
                // Therefore, I'm concluding that the client only has so many threads available to do requests
                // and when a thread stalls..   is stays stalled.
                // Therefore we need to return something valid
                response = "<llsd><map><key>folders</key><array /></map></llsd>";
            }
            else
            {
                response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
            }

//                m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request");
            //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);

            return(response);

//            }
        }
        public void FetchInventoryDescendentsRequest(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, ExpiringKey <UUID> BadRequests)
        {
            //m_log.DebugFormat("[XXX]: FetchInventoryDescendentsRequest in {0}, {1}", (m_Scene == null) ? "none" : m_Scene.Name, request);

            List <LLSDFetchInventoryDescendents> folders = null;
            List <UUID> bad_folders = new List <UUID>();

            try
            {
                OSDArray foldersrequested = null;
                OSD      tmp = OSDParser.DeserializeLLSDXml(httpRequest.InputStream);
                httpRequest.InputStream.Dispose();

                OSDMap map = (OSDMap)tmp;
                if (map.TryGetValue("folders", out tmp) && tmp is OSDArray)
                {
                    foldersrequested = tmp as OSDArray;
                }

                if (foldersrequested == null || foldersrequested.Count == 0)
                {
                    httpResponse.RawBuffer = EmptyResponse;
                    return;
                }

                folders = new List <LLSDFetchInventoryDescendents>(foldersrequested.Count);
                for (int i = 0; i < foldersrequested.Count; i++)
                {
                    OSDMap mfolder = foldersrequested[i] as OSDMap;
                    UUID   id      = mfolder["folder_id"].AsUUID();
                    if (BadRequests.ContainsKey(id))
                    {
                        bad_folders.Add(id);
                    }
                    else
                    {
                        LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
                        try
                        {
                            llsdRequest.folder_id     = id;
                            llsdRequest.owner_id      = mfolder["owner_id"].AsUUID();
                            llsdRequest.sort_order    = mfolder["sort_order"].AsInteger();
                            llsdRequest.fetch_folders = mfolder["fetch_folders"].AsBoolean();
                            llsdRequest.fetch_items   = mfolder["fetch_items"].AsBoolean();
                        }
                        catch (Exception e)
                        {
                            m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e.Message);
                            continue;
                        }
                        folders.Add(llsdRequest);
                    }
                }
                foldersrequested = null;
                map.Clear();
                map = null;
            }
            catch (Exception e)
            {
                m_log.ErrorFormat("[FETCH INV DESC]: fail parsing request: {0}", e.Message);
                httpResponse.RawBuffer = EmptyResponse;
                return;
            }

            if (folders == null || folders.Count == 0)
            {
                if (bad_folders.Count == 0)
                {
                    httpResponse.RawBuffer = EmptyResponse;
                    return;
                }

                StringBuilder sb = osStringBuilderCache.Acquire();
                sb.Append("[WEB FETCH INV DESC HANDLER]: Unable to fetch folders owned by ");
                sb.Append("Unknown");
                sb.Append(" :");
                int limit = 5;
                int count = 0;
                foreach (UUID bad in bad_folders)
                {
                    if (BadRequests.ContainsKey(bad))
                    {
                        continue;
                    }
                    sb.Append(" ");
                    sb.Append(bad.ToString());
                    ++count;
                    if (--limit < 0)
                    {
                        break;
                    }
                }

                if (count > 0)
                {
                    if (limit < 0)
                    {
                        sb.Append(" ...");
                    }
                    m_log.Warn(osStringBuilderCache.GetStringAndRelease(sb));
                }
                else
                {
                    osStringBuilderCache.Release(sb);
                }

                sb = osStringBuilderCache.Acquire();
                sb.Append("<llsd><map><key>folders</key><array /></map><map><key>bad_folders</key><array>");
                foreach (UUID bad in bad_folders)
                {
                    sb.Append("<map><key>folder_id</key><uuid>");
                    sb.Append(bad.ToString());
                    sb.Append("</uuid><key>error</key><string>Unknown</string></map>");
                }
                sb.Append("</array></map></llsd>");
                httpResponse.RawBuffer = Util.UTF8NBGetbytes(osStringBuilderCache.GetStringAndRelease(sb));
                return;
            }

            int total_folders = 0;
            int total_items   = 0;

            UUID requester = folders[0].owner_id;

            List <InventoryCollection> invcollSet = Fetch(folders, bad_folders, ref total_folders, ref total_items);
            //m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count);

            int invcollSetCount = 0;

            if (invcollSet != null)
            {
                invcollSetCount = invcollSet.Count;
            }

            int mem = 8192 + ((256 * invcollSetCount +
                               384 * total_folders +
                               1024 * total_items +
                               128 * bad_folders.Count) & 0x7ffff000);

            StringBuilder lastresponse = new StringBuilder(mem);

            lastresponse.Append("<llsd>");

            if (invcollSetCount > 0)
            {
                lastresponse.Append("<map><key>folders</key><array>");
                int i = 0;
                InventoryCollection thiscoll;
                for (i = 0; i < invcollSetCount; i++)
                {
                    thiscoll      = invcollSet[i];
                    invcollSet[i] = null;

                    LLSDxmlEncode.AddMap(lastresponse);
                    LLSDxmlEncode.AddElem("agent_id", thiscoll.OwnerID, lastresponse);
                    LLSDxmlEncode.AddElem("descendents", thiscoll.Descendents, lastresponse);
                    LLSDxmlEncode.AddElem("folder_id", thiscoll.FolderID, lastresponse);

                    if (thiscoll.Folders == null || thiscoll.Folders.Count == 0)
                    {
                        LLSDxmlEncode.AddEmptyArray("categories", lastresponse);
                    }
                    else
                    {
                        LLSDxmlEncode.AddArray("categories", lastresponse);
                        foreach (InventoryFolderBase invFolder in thiscoll.Folders)
                        {
                            LLSDxmlEncode.AddMap(lastresponse);

                            LLSDxmlEncode.AddElem("folder_id", invFolder.ID, lastresponse);
                            LLSDxmlEncode.AddElem("parent_id", invFolder.ParentID, lastresponse);
                            LLSDxmlEncode.AddElem("name", invFolder.Name, lastresponse);
                            LLSDxmlEncode.AddElem("type", invFolder.Type, lastresponse);
                            LLSDxmlEncode.AddElem("preferred_type", (int)-1, lastresponse);
                            LLSDxmlEncode.AddElem("version", invFolder.Version, lastresponse);

                            LLSDxmlEncode.AddEndMap(lastresponse);
                        }
                        LLSDxmlEncode.AddEndArray(lastresponse);
                    }

                    if (thiscoll.Items == null || thiscoll.Items.Count == 0)
                    {
                        LLSDxmlEncode.AddEmptyArray("items", lastresponse);
                    }
                    else
                    {
                        LLSDxmlEncode.AddArray("items", lastresponse);
                        foreach (InventoryItemBase invItem in thiscoll.Items)
                        {
                            invItem.ToLLSDxml(lastresponse);
                        }

                        LLSDxmlEncode.AddEndArray(lastresponse);
                    }

                    LLSDxmlEncode.AddElem("owner_id", thiscoll.OwnerID, lastresponse);
                    LLSDxmlEncode.AddElem("version", thiscoll.Version, lastresponse);

                    LLSDxmlEncode.AddEndMap(lastresponse);
                    invcollSet[i] = null;
                }
                lastresponse.Append("</array></map>");
                thiscoll = null;
            }
            else
            {
                lastresponse.Append("<map><key>folders</key><array /></map>");
            }

            if (bad_folders.Count > 0)
            {
                lastresponse.Append("<map><key>bad_folders</key><array>");
                foreach (UUID bad in bad_folders)
                {
                    BadRequests.Add(bad);
                    lastresponse.Append("<map><key>folder_id</key><uuid>");
                    lastresponse.Append(bad.ToString());
                    lastresponse.Append("</uuid><key>error</key><string>Unknown</string></map>");
                }
                lastresponse.Append("</array></map>");

                StringBuilder sb = osStringBuilderCache.Acquire();
                sb.Append("[WEB FETCH INV DESC HANDLER]: Unable to fetch folders owned by ");
                sb.Append(requester.ToString());
                sb.Append(" :");
                int limit = 9;
                foreach (UUID bad in bad_folders)
                {
                    sb.Append(" ");
                    sb.Append(bad.ToString());
                    if (--limit < 0)
                    {
                        break;
                    }
                }
                if (limit < 0)
                {
                    sb.Append(" ...");
                }
                m_log.Warn(osStringBuilderCache.GetStringAndRelease(sb));
            }
            lastresponse.Append("</llsd>");

            httpResponse.RawBuffer = Util.UTF8NBGetbytes(lastresponse.ToString());
        }
Example #9
0
        public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
        {
            //m_log.DebugFormat("[XXX]: FetchInventoryDescendentsRequest in {0}, {1}", (m_Scene == null) ? "none" : m_Scene.Name, request);

            ArrayList foldersrequested = null;

            try
            {
                Hashtable hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
                foldersrequested = (ArrayList)hash["folders"];
                hash             = null;
            }
            catch (Exception e)
            {
                m_log.ErrorFormat("[FETCH INV DESC]: fail parsing request: '{0}'; path: '{1}'; exception: '{2}'", request, path, e.Message);
                foldersrequested = null;
            }

            if (foldersrequested == null || foldersrequested.Count == 0)
            {
                return("<llsd><map><key>folders</key><array /></map></llsd>");
            }

            List <LLSDFetchInventoryDescendents> folders = new List <LLSDFetchInventoryDescendents>();

            for (int i = 0; i < foldersrequested.Count; i++)
            {
                Hashtable inventoryhash = (Hashtable)foldersrequested[i];
                LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();

                try
                {
                    LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
                }
                catch (Exception e)
                {
                    m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e.Message);
                    continue;
                }

                folders.Add(llsdRequest);
            }

            foldersrequested.Clear();

            if (folders.Count == 0)
            {
                return("<llsd><map><key>folders</key><array /></map></llsd>");
            }

            List <UUID> bad_folders = new List <UUID>();

            int total_folders = 0;
            int total_items   = 0;
            List <InventoryCollection> invcollSet = Fetch(folders, bad_folders, ref total_folders, ref total_items);
            //m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count);

            int invcollSetCount = 0;

            if (invcollSet != null)
            {
                invcollSetCount = invcollSet.Count;
            }

            int mem = 8192 + ((256 * invcollSetCount +
                               384 * total_folders +
                               1024 * total_items +
                               128 * bad_folders.Count) & 0x7ffff000);

            StringBuilder lastresponse = new StringBuilder(mem);

            lastresponse.Append("<llsd>");

            if (invcollSetCount > 0)
            {
                lastresponse.Append("<map><key>folders</key><array>");
                int i = 0;
                InventoryCollection thiscoll;
                for (i = 0; i < invcollSetCount; i++)
                {
                    thiscoll      = invcollSet[i];
                    invcollSet[i] = null;

                    LLSDxmlEncode.AddMap(lastresponse);
                    LLSDxmlEncode.AddElem("agent_id", thiscoll.OwnerID, lastresponse);
                    LLSDxmlEncode.AddElem("descendents", thiscoll.Descendents, lastresponse);
                    LLSDxmlEncode.AddElem("folder_id", thiscoll.FolderID, lastresponse);

                    if (thiscoll.Folders == null || thiscoll.Folders.Count == 0)
                    {
                        LLSDxmlEncode.AddEmptyArray("categories", lastresponse);
                    }
                    else
                    {
                        LLSDxmlEncode.AddArray("categories", lastresponse);
                        foreach (InventoryFolderBase invFolder in thiscoll.Folders)
                        {
                            LLSDxmlEncode.AddMap(lastresponse);

                            LLSDxmlEncode.AddElem("folder_id", invFolder.ID, lastresponse);
                            LLSDxmlEncode.AddElem("parent_id", invFolder.ParentID, lastresponse);
                            LLSDxmlEncode.AddElem("name", invFolder.Name, lastresponse);
                            LLSDxmlEncode.AddElem("type", invFolder.Type, lastresponse);
                            LLSDxmlEncode.AddElem("preferred_type", (int)-1, lastresponse);
                            LLSDxmlEncode.AddElem("version", invFolder.Version, lastresponse);

                            LLSDxmlEncode.AddEndMap(lastresponse);
                        }
                        LLSDxmlEncode.AddEndArray(lastresponse);
                    }

                    if (thiscoll.Items == null || thiscoll.Items.Count == 0)
                    {
                        LLSDxmlEncode.AddEmptyArray("items", lastresponse);
                    }
                    else
                    {
                        LLSDxmlEncode.AddArray("items", lastresponse);
                        foreach (InventoryItemBase invItem in thiscoll.Items)
                        {
                            invItem.ToLLSDxml(lastresponse);
                        }

                        LLSDxmlEncode.AddEndArray(lastresponse);
                    }

                    LLSDxmlEncode.AddElem("owner_id", thiscoll.OwnerID, lastresponse);
                    LLSDxmlEncode.AddElem("version", thiscoll.Version, lastresponse);

                    LLSDxmlEncode.AddEndMap(lastresponse);
                    invcollSet[i] = null;
                }
                lastresponse.Append("</array></map>");
                thiscoll = null;
            }
            else
            {
                lastresponse.Append("<map><key>folders</key><array /></map>");
            }

            //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders));
            if (bad_folders.Count > 0)
            {
                lastresponse.Append("<map><key>bad_folders</key><array>");
                foreach (UUID bad in bad_folders)
                {
                    lastresponse.Append("<map><key>folder_id</key><uuid>");
                    lastresponse.Append(bad.ToString());
                    lastresponse.Append("</uuid><key>error</key><string>Unknown</string></map>");
                }
                lastresponse.Append("</array></map>");
            }
            lastresponse.Append("</llsd>");

            return(lastresponse.ToString());
        }
        private List <InventoryCollection> Fetch(List <LLSDFetchInventoryDescendents> fetchFolders, List <UUID> bad_folders, ref int total_folders, ref int total_items)
        {
            //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 <InventoryCollection>           result       = new List <InventoryCollection>(32);
            List <LLSDFetchInventoryDescendents> libFolders   = new List <LLSDFetchInventoryDescendents>(32);
            List <LLSDFetchInventoryDescendents> otherFolders = new List <LLSDFetchInventoryDescendents>(32);
            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;
                    InventoryCollection Collection = new InventoryCollection();
                    Collection.OwnerID     = f.owner_id;
                    Collection.Version     = 0;
                    Collection.FolderID    = f.folder_id;
                    Collection.Descendents = 0;
                    result.Add(Collection);
                    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);
            }

            fetchFolders.Clear();

            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];
                        otherFolders[i] = null;
                        i++;

                        if (BadFolder(freq, contents, bad_folders))
                        {
                            continue;
                        }

                        if (!freq.fetch_folders)
                        {
                            contents.Folders.Clear();
                        }
                        if (!freq.fetch_items)
                        {
                            contents.Items.Clear();
                        }

                        contents.Descendents = contents.Items.Count + contents.Folders.Count;

                        // Next: link management
                        ProcessLinks(freq, contents);

                        total_folders += contents.Folders.Count;
                        total_items   += contents.Items.Count;
                        result.Add(contents);
                    }
                }
            }

            if (dolib && libFolders.Count > 0)
            {
                AddLibraryFolders(libFolders, result, ref total_folders, ref total_items);
            }

            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);
                            }
                        }
                    }
                }
            }
        }
        public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
        {
            //m_log.DebugFormat("[XXX]: FetchInventoryDescendentsRequest in {0}, {1}", (m_Scene == null) ? "none" : m_Scene.Name, request);

            // nasty temporary hack here, the linden client falsely
            // identifies the uuid 00000000-0000-0000-0000-000000000000
            // as a string which breaks us
            //
            // correctly mark it as a uuid
            //
            request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");

            // another hack <integer>1</integer> results in a
            // System.ArgumentException: Object type System.Int32 cannot
            // be converted to target type: System.Boolean
            //
            request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
            request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");

            Hashtable hash = new Hashtable();

            try
            {
                hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
            }
            catch (LLSD.LLSDParseException e)
            {
                m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
                m_log.Error("Request: " + request);
            }

            ArrayList foldersrequested = (ArrayList)hash["folders"];

            string response             = "";
            string bad_folders_response = "";

            List <LLSDFetchInventoryDescendents> folders = new List <LLSDFetchInventoryDescendents>();

            for (int i = 0; i < foldersrequested.Count; i++)
            {
                Hashtable inventoryhash = (Hashtable)foldersrequested[i];

                LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();

                try
                {
                    LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
                }
                catch (Exception e)
                {
                    m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
                    continue;
                }

                // Filter duplicate folder ids that bad viewers may send
                if (folders.Find(f => f.folder_id == llsdRequest.folder_id) == null)
                {
                    folders.Add(llsdRequest);
                }
            }

            if (folders.Count > 0)
            {
                List <UUID> bad_folders = new List <UUID>();
                List <InventoryCollectionWithDescendents> invcollSet = Fetch(folders, bad_folders);
                //m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count);

                if (invcollSet == null)
                {
                    m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Multiple folder fetch failed. Trying old protocol.");
#pragma warning disable 0612
                    return(FetchInventoryDescendentsRequest(foldersrequested, httpRequest, httpResponse));

#pragma warning restore 0612
                }

                string inventoryitemstr = string.Empty;
                foreach (InventoryCollectionWithDescendents icoll in invcollSet)
                {
                    LLSDInventoryDescendents reply = ToLLSD(icoll.Collection, icoll.Descendents);

                    inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
                    inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
                    inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");

                    response += inventoryitemstr;
                }

                //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders));
                foreach (UUID bad in bad_folders)
                {
                    bad_folders_response += "<uuid>" + bad + "</uuid>";
                }
            }

            if (response.Length == 0)
            {
                /* Viewers expect a bad_folders array when not available */
                if (bad_folders_response.Length != 0)
                {
                    response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
                }
                else
                {
                    response = "<llsd><map><key>folders</key><array /></map></llsd>";
                }
            }
            else
            {
                if (bad_folders_response.Length != 0)
                {
                    response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
                }
                else
                {
                    response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
                }
            }

            //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request for {0} folders. Item count {1}", folders.Count, item_count);
            //m_log.Debug("[WEB FETCH INV DESC HANDLER] " + response);

            return(response);
        }
        private string FetchInventoryDescendentsRequest(ArrayList foldersrequested, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
        {
            //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count);

            string response             = "";
            string bad_folders_response = "";

            for (int i = 0; i < foldersrequested.Count; i++)
            {
                string    inventoryitemstr = "";
                Hashtable inventoryhash    = (Hashtable)foldersrequested[i];

                LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();

                try
                {
                    LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
                }
                catch (Exception e)
                {
                    m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
                }

                LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);

                if (null == reply)
                {
                    bad_folders_response += "<uuid>" + llsdRequest.folder_id.ToString() + "</uuid>";
                }
                else
                {
                    inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
                    inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
                    inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
                }

                response += inventoryitemstr;
            }

            if (response.Length == 0)
            {
                /* Viewers expect a bad_folders array when not available */
                if (bad_folders_response.Length != 0)
                {
                    response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
                }
                else
                {
                    response = "<llsd><map><key>folders</key><array /></map></llsd>";
                }
            }
            else
            {
                if (bad_folders_response.Length != 0)
                {
                    response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
                }
                else
                {
                    response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
                }
            }

            //                m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request");
            //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);

            return(response);

            //            }
        }
Example #14
0
        public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
        {
            // nasty temporary hack here, the linden client falsely
            // identifies the uuid 00000000-0000-0000-0000-000000000000
            // as a string which breaks us
            //
            // correctly mark it as a uuid
            //
            request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");

            // another hack <integer>1</integer> results in a
            // System.ArgumentException: Object type System.Int32 cannot
            // be converted to target type: System.Boolean
            //
            request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
            request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");

            Hashtable hash = new Hashtable();

            try
            {
                hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
            }
            catch (LLSD.LLSDParseException e)
            {
                m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
                m_log.Error("Request: " + request);
                throw;
            }

            ArrayList foldersrequested = (ArrayList)hash["folders"];

            string response             = "";
            string bad_folders_response = "";

            for (int i = 0; i < foldersrequested.Count; i++)
            {
                string    inventoryitemstr = "";
                Hashtable inventoryhash    = (Hashtable)foldersrequested[i];

                LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();

                try
                {
                    LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
                }
                catch (Exception e)
                {
                    m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
                }
                LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
                if (null == reply)
                {
                    bad_folders_response += "<uuid>" + llsdRequest.folder_id.ToString() + "</uuid>";
                }
                else
                {
                    inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
                    inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
                    inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");

                    response += inventoryitemstr;
                }
            }

            if (response.Length == 0)
            {
                /* Viewers expect a bad_folders array when not available */
                if (bad_folders_response.Length != 0)
                {
                    response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
                }
                else
                {
                    response = "<llsd><map><key>folders</key><array /></map></llsd>";
                }
            }
            else
            {
                if (bad_folders_response.Length != 0)
                {
                    response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
                }
                else
                {
                    response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
                }
            }

            return(response);
        }
Example #15
0
        public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
        {
            //m_log.DebugFormat("[XXX]: FetchInventoryDescendentsRequest in {0}, {1}", (m_Scene == null) ? "none" : m_Scene.Name, request);

            Hashtable hash = new Hashtable();

            try
            {
                hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
            }
            catch (LLSD.LLSDParseException e)
            {
                m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
                m_log.Error("Request: " + request);
            }

            ArrayList foldersrequested = (ArrayList)hash["folders"];

            List <LLSDFetchInventoryDescendents> folders = new List <LLSDFetchInventoryDescendents>();

            for (int i = 0; i < foldersrequested.Count; i++)
            {
                Hashtable inventoryhash = (Hashtable)foldersrequested[i];

                LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();

                try
                {
                    LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
                }
                catch (Exception e)
                {
                    m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
                    continue;
                }

                folders.Add(llsdRequest);
            }

            if (folders.Count == 0)
            {
                return("<llsd><map><key>folders</key><array /></map></llsd>");
            }

            List <UUID> bad_folders = new List <UUID>();

            List <InventoryCollectionWithDescendents> invcollSet = Fetch(folders, bad_folders);

            //m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count);

            if (invcollSet == null)
            {
                m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Multiple folder fetch failed. Trying old protocol.");
#pragma warning disable 0612
                return(FetchInventoryDescendentsRequest(foldersrequested, httpRequest, httpResponse));

#pragma warning restore 0612
            }

            StringBuilder lastresponse = new StringBuilder(1024);
            lastresponse.Append("<llsd>");

            if (invcollSet.Count > 0)
            {
                lastresponse.Append("<map><key>folders</key><array>");
                foreach (InventoryCollectionWithDescendents icoll in invcollSet)
                {
                    LLSDInventoryFolderContents thiscontents = contentsToLLSD(icoll.Collection, icoll.Descendents);
                    lastresponse.Append(LLSDHelpers.SerialiseLLSDReplyNoHeader(thiscontents));
                }
                lastresponse.Append("</array></map>");
            }
            else
            {
                lastresponse.Append("<map><key>folders</key><array /></map>");
            }

            //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders));
            if (bad_folders.Count > 0)
            {
                lastresponse.Append("<map><key>bad_folders</key><array>");
                foreach (UUID bad in bad_folders)
                {
                    lastresponse.Append("<map><key>folder_id</key><uuid>");
                    lastresponse.Append(bad.ToString());
                    lastresponse.Append("</uuid><key>error</key><string>Unknown</string></map>");
                }
                lastresponse.Append("</array></map>");
            }
            lastresponse.Append("</llsd>");

            return(lastresponse.ToString());;
        }
Example #16
0
        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);
                        }
                    }
                }
            }
        }
Example #17
0
        private string FetchInventoryDescendentsRequest(ArrayList foldersrequested, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
        {
            //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count);

            StringBuilder tmpresponse   = new StringBuilder(1024);
            StringBuilder tmpbadfolders = new StringBuilder(1024);

            for (int i = 0; i < foldersrequested.Count; i++)
            {
                string    inventoryitemstr = "";
                Hashtable inventoryhash    = (Hashtable)foldersrequested[i];

                LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();

                try
                {
                    LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
                }
                catch (Exception e)
                {
                    m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
                }

                LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);

                if (null == reply)
                {
                    tmpbadfolders.Append("<map><key>folder_id</key><uuid>");
                    tmpbadfolders.Append(llsdRequest.folder_id.ToString());
                    tmpbadfolders.Append("</uuid><key>error</key><string>Unknown</string></map>");
                }
                else
                {
                    inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
                    inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
                    inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
                }

                tmpresponse.Append(inventoryitemstr);
            }

            StringBuilder lastresponse = new StringBuilder(1024);

            lastresponse.Append("<llsd>");
            if (tmpresponse.Length > 0)
            {
                lastresponse.Append("<map><key>folders</key><array>");
                lastresponse.Append(tmpresponse.ToString());
                lastresponse.Append("</array></map>");
            }
            else
            {
                lastresponse.Append("<map><key>folders</key><array /></map>");
            }

            if (tmpbadfolders.Length > 0)
            {
                lastresponse.Append("<map><key>bad_folders</key><array>");
                lastresponse.Append(tmpbadfolders.ToString());
                lastresponse.Append("</array></map>");
            }
            lastresponse.Append("</llsd>");

            return(lastresponse.ToString());
        }
Example #18
0
        public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
        {
            //m_log.DebugFormat("[XXX]: FetchInventoryDescendentsRequest in {0}, {1}", (m_Scene == null) ? "none" : m_Scene.Name, request);

            // nasty temporary hack here, the linden client falsely
            // identifies the uuid 00000000-0000-0000-0000-000000000000
            // as a string which breaks us
            //
            // correctly mark it as a uuid
            //
            request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");

            // another hack <integer>1</integer> results in a
            // System.ArgumentException: Object type System.Int32 cannot
            // be converted to target type: System.Boolean
            //
            request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
            request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");

            Hashtable hash = new Hashtable();

            try
            {
                hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
            }
            catch (LLSD.LLSDParseException e)
            {
                m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
                m_log.Error("Request: " + request);
            }

            ArrayList foldersrequested = (ArrayList)hash["folders"];

            StringBuilder tmpresponse   = new StringBuilder(1024);
            StringBuilder tmpbadfolders = new StringBuilder(1024);

            List <LLSDFetchInventoryDescendents> folders = new List <LLSDFetchInventoryDescendents>();

            for (int i = 0; i < foldersrequested.Count; i++)
            {
                Hashtable inventoryhash = (Hashtable)foldersrequested[i];

                LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();

                try
                {
                    LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
                }
                catch (Exception e)
                {
                    m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
                    continue;
                }

                folders.Add(llsdRequest);
            }

            if (folders.Count > 0)
            {
                List <UUID> bad_folders = new List <UUID>();
                List <InventoryCollectionWithDescendents> invcollSet = Fetch(folders, bad_folders);
                //m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count);

                if (invcollSet == null)
                {
                    m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Multiple folder fetch failed. Trying old protocol.");
#pragma warning disable 0612
                    return(FetchInventoryDescendentsRequest(foldersrequested, httpRequest, httpResponse));

#pragma warning restore 0612
                }

                string inventoryitemstr = string.Empty;
                foreach (InventoryCollectionWithDescendents icoll in invcollSet)
                {
                    LLSDInventoryFolderContents thiscontents = contentsToLLSD(icoll.Collection, icoll.Descendents);
                    inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(thiscontents);
//                    inventoryitemstr = inventoryitemstr.Replace("<llsd>", "");
//                    inventoryitemstr = inventoryitemstr.Replace("</llsd>", "");
//                    inventoryitemstr = inventoryitemstr.Substring(6,inventoryitemstr.Length - 13);
//                    tmpresponse.Append(inventoryitemstr);
                    tmpresponse.Append(inventoryitemstr.Substring(6, inventoryitemstr.Length - 13));
                }

                //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders));
                foreach (UUID bad in bad_folders)
                {
                    tmpbadfolders.Append("<map><key>folder_id</key><uuid>");
                    tmpbadfolders.Append(bad.ToString());
                    tmpbadfolders.Append("</uuid><key>error</key><string>Unknown</string></map>");
                }
            }

            StringBuilder lastresponse = new StringBuilder(1024);
            lastresponse.Append("<llsd>");
            if (tmpresponse.Length > 0)
            {
                lastresponse.Append("<map><key>folders</key><array>");
                lastresponse.Append(tmpresponse.ToString());
                lastresponse.Append("</array></map>");
            }
            else
            {
                lastresponse.Append("<map><key>folders</key><array /></map>");
            }

            if (tmpbadfolders.Length > 0)
            {
                lastresponse.Append("<map><key>bad_folders</key><array>");
                lastresponse.Append(tmpbadfolders.ToString());
                lastresponse.Append("</array></map>");
            }
            lastresponse.Append("</llsd>");

            return(lastresponse.ToString());
        }