From 883f21dd026cbed55f2e12af491e2f9902b80d4a Mon Sep 17 00:00:00 2001
From: Diva Canto
Date: Mon, 2 May 2011 14:33:34 -0700
Subject: WebFetchInventoryDescendents working. Tested with robust.
---
.../WebFetchInvDescHandler.cs | 299 +++++++++++++++++++++
.../WebFetchInvDescServerConnector.cs | 76 ++++++
2 files changed, 375 insertions(+)
create mode 100644 OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs
create mode 100644 OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs
(limited to 'OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents')
diff --git a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs
new file mode 100644
index 0000000..6fd7946
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using log4net;
+using Nini.Config;
+using OpenMetaverse;
+using OpenMetaverse.StructuredData;
+using OpenSim.Framework;
+using OpenSim.Framework.Capabilities;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Framework.Servers.HttpServer;
+using OpenSim.Services.Interfaces;
+using Caps = OpenSim.Framework.Capabilities.Caps;
+
+namespace OpenSim.Capabilities.Handlers
+{
+
+ public class WebFetchInvDescHandler
+ {
+ private static readonly ILog m_log =
+ LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ private IInventoryService m_InventoryService;
+ private ILibraryService m_LibraryService;
+ private object m_fetchLock = new Object();
+
+ public WebFetchInvDescHandler(IInventoryService invService, ILibraryService libService)
+ {
+ m_InventoryService = invService;
+ m_LibraryService = libService;
+ }
+
+ public string FetchInventoryDescendentsRequest(string request, string path, string param, OSHttpRequest httpRequest, OSHttpResponse 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("00000000-0000-0000-0000-000000000000", "00000000-0000-0000-0000-000000000000");
+
+ // another hack 1 results in a
+ // System.ArgumentException: Object type System.Int32 cannot
+ // be converted to target type: System.Boolean
+ //
+ request = request.Replace("fetch_folders0", "fetch_folders0");
+ request = request.Replace("fetch_folders1", "fetch_folders1");
+
+ Hashtable hash = new Hashtable();
+ try
+ {
+ hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
+ }
+ catch (LLSD.LLSDParseException pe)
+ {
+ m_log.Error("[AGENT INVENTORY]: Fetch error: " + pe.Message);
+ m_log.Error("Request: " + request.ToString());
+ }
+
+ ArrayList foldersrequested = (ArrayList)hash["folders"];
+
+ string response = "";
+ lock (m_fetchLock)
+ {
+ 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("[CAPS]: caught exception doing OSD deserialize" + e);
+ }
+ LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
+
+ inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
+ inventoryitemstr = inventoryitemstr.Replace("", "");
+
+ 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 = "";
+ }
+ else
+ {
+ response = "";
+ }
+
+ //m_log.DebugFormat("[CAPS]: Replying to CAPS fetch inventory request with following xml");
+ //m_log.Debug("[CAPS] "+response);
+
+ }
+ return response;
+ }
+
+ ///
+ /// Construct an LLSD reply packet to a CAPS inventory request
+ ///
+ ///
+ ///
+ 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();
+ inv.Items = new List();
+ int version = 0;
+
+ inv = Fetch(invFetch.owner_id, invFetch.folder_id, invFetch.owner_id, invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version);
+
+ if (inv.Folders != null)
+ {
+ foreach (InventoryFolderBase invFolder in inv.Folders)
+ {
+ contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
+ }
+ }
+
+ if (inv.Items != null)
+ {
+ foreach (InventoryItemBase invItem in inv.Items)
+ {
+ contents.items.Array.Add(ConvertInventoryItem(invItem));
+ }
+ }
+
+ contents.descendents = contents.items.Array.Count + contents.categories.Array.Count;
+ contents.version = version;
+
+ return reply;
+ }
+
+ public InventoryCollection Fetch(UUID agentID, UUID folderID, UUID ownerID,
+ bool fetchFolders, bool fetchItems, int sortOrder, out int version)
+ {
+ m_log.DebugFormat(
+ "[WEBFETCHINVENTORYDESCENDANTS]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
+ fetchFolders, fetchItems, folderID, agentID);
+
+ version = 0;
+ InventoryFolderImpl fold;
+ if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
+ if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null)
+ {
+ InventoryCollection ret = new InventoryCollection();
+ ret.Folders = new List();
+ ret.Items = fold.RequestListOfItems();
+
+ return ret;
+ }
+
+ InventoryCollection contents = new InventoryCollection();
+
+ if (folderID != UUID.Zero)
+ {
+ contents = m_InventoryService.GetFolderContent(agentID, folderID);
+ InventoryFolderBase containingFolder = new InventoryFolderBase();
+ containingFolder.ID = folderID;
+ containingFolder.Owner = agentID;
+ containingFolder = m_InventoryService.GetFolder(containingFolder);
+ if (containingFolder != null)
+ version = containingFolder.Version;
+ }
+ else
+ {
+ // Lost itemsm don't really need a version
+ version = 1;
+ }
+
+ return contents;
+
+ }
+ ///
+ /// Convert an internal inventory folder object into an LLSD object.
+ ///
+ ///
+ ///
+ private LLSDInventoryFolder ConvertInventoryFolder(InventoryFolderBase invFolder)
+ {
+ LLSDInventoryFolder llsdFolder = new LLSDInventoryFolder();
+ llsdFolder.folder_id = invFolder.ID;
+ llsdFolder.parent_id = invFolder.ParentID;
+ llsdFolder.name = invFolder.Name;
+ if (invFolder.Type < 0 || invFolder.Type >= TaskInventoryItem.Types.Length)
+ llsdFolder.type = "-1";
+ else
+ llsdFolder.type = TaskInventoryItem.Types[invFolder.Type];
+ llsdFolder.preferred_type = "-1";
+
+ return llsdFolder;
+ }
+
+ ///
+ /// Convert an internal inventory item object into an LLSD object.
+ ///
+ ///
+ ///
+ private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem)
+ {
+ LLSDInventoryItem llsdItem = new LLSDInventoryItem();
+ llsdItem.asset_id = invItem.AssetID;
+ llsdItem.created_at = invItem.CreationDate;
+ llsdItem.desc = invItem.Description;
+ llsdItem.flags = (int)invItem.Flags;
+ llsdItem.item_id = invItem.ID;
+ llsdItem.name = invItem.Name;
+ llsdItem.parent_id = invItem.Folder;
+ try
+ {
+ // TODO reevaluate after upgrade to libomv >= r2566. Probably should use UtilsConversions.
+ llsdItem.type = TaskInventoryItem.Types[invItem.AssetType];
+ llsdItem.inv_type = TaskInventoryItem.InvTypes[invItem.InvType];
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat("[CAPS]: Problem setting asset {0} inventory {1} types while converting inventory item {2}: {3}", invItem.AssetType, invItem.InvType, invItem.Name, e.Message);
+ }
+ llsdItem.permissions = new LLSDPermissions();
+ llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
+ llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions;
+ llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions;
+ llsdItem.permissions.group_id = invItem.GroupID;
+ llsdItem.permissions.group_mask = (int)invItem.GroupPermissions;
+ llsdItem.permissions.is_owner_group = invItem.GroupOwned;
+ llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions;
+ llsdItem.permissions.owner_id = invItem.Owner;
+ llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
+ llsdItem.sale_info = new LLSDSaleInfo();
+ llsdItem.sale_info.sale_price = invItem.SalePrice;
+ switch (invItem.SaleType)
+ {
+ default:
+ llsdItem.sale_info.sale_type = "not";
+ break;
+ case 1:
+ llsdItem.sale_info.sale_type = "original";
+ break;
+ case 2:
+ llsdItem.sale_info.sale_type = "copy";
+ break;
+ case 3:
+ llsdItem.sale_info.sale_type = "contents";
+ break;
+ }
+
+ return llsdItem;
+ }
+
+ }
+}
diff --git a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs
new file mode 100644
index 0000000..92eeb14
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using Nini.Config;
+using OpenSim.Server.Base;
+using OpenSim.Services.Interfaces;
+using OpenSim.Framework.Servers.HttpServer;
+using OpenSim.Server.Handlers.Base;
+using OpenMetaverse;
+
+namespace OpenSim.Capabilities.Handlers
+{
+ public class WebFetchInvDescServerConnector : ServiceConnector
+ {
+ private IInventoryService m_InventoryService;
+ private ILibraryService m_LibraryService;
+ private string m_ConfigName = "CapsService";
+
+ public WebFetchInvDescServerConnector(IConfigSource config, IHttpServer server, string configName) :
+ base(config, server, configName)
+ {
+ if (configName != String.Empty)
+ m_ConfigName = configName;
+
+ IConfig serverConfig = config.Configs[m_ConfigName];
+ if (serverConfig == null)
+ throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
+
+ string invService = serverConfig.GetString("InventoryService", String.Empty);
+
+ if (invService == String.Empty)
+ throw new Exception("No InventoryService in config file");
+
+ Object[] args = new Object[] { config };
+ m_InventoryService =
+ ServerUtils.LoadPlugin(invService, args);
+
+ if (m_InventoryService == null)
+ throw new Exception(String.Format("Failed to load InventoryService from {0}; config is {1}", invService, m_ConfigName));
+
+ string libService = serverConfig.GetString("LibraryService", String.Empty);
+ m_LibraryService =
+ ServerUtils.LoadPlugin(libService, args);
+
+ WebFetchInvDescHandler webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
+ IRequestHandler reqHandler = new RestStreamHandler("POST", "/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/, webFetchHandler.FetchInventoryDescendentsRequest);
+ server.AddStreamHandler(reqHandler);
+ }
+
+ }
+}
--
cgit v1.1