diff --git a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs index 8b44f72421..d5c062b831 100644 --- a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs +++ b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs @@ -162,7 +162,7 @@ namespace OpenSim.Capabilities.Handlers invFetch.owner_id, invFetch.folder_id, invFetch.owner_id, invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version); - if (inv.Folders != null) + if (inv != null && inv.Folders != null) { foreach (InventoryFolderBase invFolder in inv.Folders) { @@ -170,7 +170,7 @@ namespace OpenSim.Capabilities.Handlers } } - if (inv.Items != null) + if (inv != null && inv.Items != null) { foreach (InventoryItemBase invItem in inv.Items) { diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index a8ece794cd..9d8561b69e 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -662,11 +662,11 @@ namespace OpenSim.Framework.Servers.HttpServer } catch (IOException e) { - m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw ", e); + m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw {0}", e); } catch (Exception e) { - m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw " + e.ToString()); + m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw {0}", e.StackTrace); SendHTML500(response); } finally diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 3470fa911b..9395233262 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1913,7 +1913,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP folderBlock.FolderID = folder.ID; folderBlock.ParentID = folder.ParentID; - folderBlock.Type = -1; + //folderBlock.Type = -1; + folderBlock.Type = (sbyte)folder.Type; folderBlock.Name = Util.StringToBytes256(folder.Name); return folderBlock; diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index ec260b4fec..0f422ae1ce 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -114,7 +114,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: ViaHGLogin"); if (m_RestrictInventoryAccessAbroad) { - RestoreRootFolderContents(client); + IUserManagement uMan = m_Scenes[0].RequestModuleInterface(); + if (uMan.IsLocalGridUser(client.AgentId)) + { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is local"); + RestoreRootFolderContents(client); + } + else + { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is foreign"); + RestoreSuitcaseFolderContents(client); + } } } } @@ -210,7 +220,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer logout = success; // flag for later logout from this grid; this is an HG TP if (success && m_RestrictInventoryAccessAbroad) - RemoveRootFolderContents(sp.ControllingClient); + { + IUserManagement uMan = m_aScene.RequestModuleInterface(); + if (uMan != null && uMan.IsLocalGridUser(sp.UUID)) + { + // local grid user + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is local"); + RemoveRootFolderContents(sp.ControllingClient); + } + else + { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is foreign"); + RemoveSuitcaseFolderContents(sp.ControllingClient); + } + } return success; } @@ -401,25 +424,40 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); if (root != null) { - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Removing root inventory for user {0}", client.AgentId); + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Removing root inventory for user {0}", client.Name); InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); - UUID[] ids = new UUID[content.Folders.Count]; - int i = 0; + List fids = new List(); + List iids = new List(); + List keep = new List(); + foreach (InventoryFolderBase f in content.Folders) - ids[i++] = f.ID; - inv.SendRemoveInventoryFolders(ids); - ids = new UUID[content.Items.Count]; - i = 0; + { + if (f.Name != "My Suitcase") + { + f.Name = f.Name + " (Unavailable)"; + keep.Add(f); + } + } + + // items directly under the root folder foreach (InventoryItemBase it in content.Items) - ids[i++] = it.ID; - inv.SendRemoveInventoryItems(ids); + it.Name = it.Name + " (Unavailable)"; ; + + // Send the new names + inv.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray()); + } } } } + private void RemoveSuitcaseFolderContents(IClientAPI client) + { + } + private void RestoreRootFolderContents(IClientAPI client) { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root folder"); if (client is IClientCore) { IClientCore core = (IClientCore)client; @@ -428,21 +466,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (core.TryGet(out inv)) { InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); - client.SendBulkUpdateInventory(root); - //if (root != null) - //{ - // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root inventory for user {0}", client.AgentId); - // InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); - // m_log.DebugFormat("[XXX]: Folder name {0}, id {1}, parent {2}", root.Name, root.ID, root.ParentID); - // foreach (InventoryItemBase i in content.Items) - // m_log.DebugFormat("[XXX]: Name={0}, folderID={1}", i.Name, i.Folder); + InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); - // inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); - //} + inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); } } } + private void RestoreSuitcaseFolderContents(IClientAPI client) + { + } + private GridRegion MakeRegion(AgentCircuitData aCircuit) { GridRegion region = new GridRegion(); diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs index 4be3804c1f..cf6d2f7905 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs @@ -297,14 +297,35 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory return m_LocalGridInventoryService.CreateUserInventory(userID); } - public List GetInventorySkeleton(UUID userId) + public List GetInventorySkeleton(UUID userID) { - return m_LocalGridInventoryService.GetInventorySkeleton(userId); + string invURL = GetInventoryServiceURL(userID); + + if (invURL == null) // not there, forward to local inventory connector to resolve + return m_LocalGridInventoryService.GetInventorySkeleton(userID); + + IInventoryService connector = GetConnector(invURL); + + return connector.GetInventorySkeleton(userID); } public InventoryCollection GetUserInventory(UUID userID) { - return null; + string invURL = GetInventoryServiceURL(userID); + m_log.DebugFormat("[HG INVENTORY CONNECTOR]: GetUserInventory for {0} {1}", userID, invURL); + + if (invURL == null) // not there, forward to local inventory connector to resolve + return m_LocalGridInventoryService.GetUserInventory(userID); + + InventoryCollection c = m_Cache.GetUserInventory(userID); + if (c != null) + return c; + + IInventoryService connector = GetConnector(invURL); + c = connector.GetUserInventory(userID); + + m_Cache.Cache(userID, c); + return c; } public void GetUserInventory(UUID userID, InventoryReceiptCallback callback) @@ -362,8 +383,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (invURL == null) // not there, forward to local inventory connector to resolve return m_LocalGridInventoryService.GetFolderContent(userID, folderID); - IInventoryService connector = GetConnector(invURL); + InventoryCollection c = m_Cache.GetFolderContent(userID, folderID); + if (c != null) + { + m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderContent found content in cache " + folderID); + return c; + } + IInventoryService connector = GetConnector(invURL); return connector.GetFolderContent(userID, folderID); } @@ -377,8 +404,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (invURL == null) // not there, forward to local inventory connector to resolve return m_LocalGridInventoryService.GetFolderItems(userID, folderID); - IInventoryService connector = GetConnector(invURL); + List items = m_Cache.GetFolderItems(userID, folderID); + if (items != null) + { + m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderItems found items in cache " + folderID); + return items; + } + IInventoryService connector = GetConnector(invURL); return connector.GetFolderItems(userID, folderID); } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs index 0fe778dfa6..1e434b9394 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs @@ -12,6 +12,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory private static ExpiringCache m_RootFolders = new ExpiringCache(); private static ExpiringCache> m_FolderTypes = new ExpiringCache>(); + private static ExpiringCache m_Inventories = new ExpiringCache(); public void Cache(UUID userID, InventoryFolderBase root) { @@ -55,5 +56,55 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory return null; } + + public void Cache(UUID userID, InventoryCollection inv) + { + lock (m_Inventories) + m_Inventories.AddOrUpdate(userID, inv, 120); + } + + public InventoryCollection GetUserInventory(UUID userID) + { + InventoryCollection inv = null; + if (m_Inventories.TryGetValue(userID, out inv)) + return inv; + return null; + } + + public InventoryCollection GetFolderContent(UUID userID, UUID folderID) + { + InventoryCollection inv = null; + InventoryCollection c; + if (m_Inventories.TryGetValue(userID, out inv)) + { + c = new InventoryCollection(); + c.UserID = userID; + + c.Folders = inv.Folders.FindAll(delegate(InventoryFolderBase f) + { + return f.ParentID == folderID; + }); + c.Items = inv.Items.FindAll(delegate(InventoryItemBase i) + { + return i.Folder == folderID; + }); + return c; + } + return null; + } + + public List GetFolderItems(UUID userID, UUID folderID) + { + InventoryCollection inv = null; + if (m_Inventories.TryGetValue(userID, out inv)) + { + List items = inv.Items.FindAll(delegate(InventoryItemBase i) + { + return i.Folder == folderID; + }); + return items; + } + return null; + } } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs index 77573c369b..990dffb61a 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs @@ -172,7 +172,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory public InventoryCollection GetUserInventory(UUID userID) { - return null; + return m_RemoteConnector.GetUserInventory(userID); } public void GetUserInventory(UUID userID, InventoryReceiptCallback callback) @@ -193,16 +193,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory { InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID); - if (UserManager != null) + if (invCol != null && UserManager != null) { // Protect ourselves against the caller subsequently modifying the items list List items = new List(invCol.Items); - Util.FireAndForget(delegate - { - foreach (InventoryItemBase item in items) - UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); - }); + if (items != null && items.Count > 0) + Util.FireAndForget(delegate + { + foreach (InventoryItemBase item in items) + UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); + }); } return invCol; diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index a0ed5a5274..ced7b523b2 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -56,6 +56,9 @@ namespace OpenSim.Region.CoreModules.World.Land protected List primsOverMe = new List(); protected Dictionary m_listTransactions = new Dictionary(); + protected ExpiringCache m_groupMemberCache = new ExpiringCache(); + protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds + public bool[,] LandBitmap { get { return m_landBitmap; } @@ -417,6 +420,45 @@ namespace OpenSim.Region.CoreModules.World.Land return false; } + public bool HasGroupAccess(UUID avatar) + { + if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) + { + ScenePresence sp; + if (!m_scene.TryGetScenePresence(avatar, out sp)) + { + bool isMember; + if (m_groupMemberCache.TryGetValue(avatar, out isMember)) + return isMember; + + IGroupsModule groupsModule = m_scene.RequestModuleInterface(); + if (groupsModule == null) + return false; + + GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar); + if (membership == null || membership.Length == 0) + { + m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + return false; + } + + foreach (GroupMembershipData d in membership) + { + if (d.GroupID == LandData.GroupID) + { + m_groupMemberCache.Add(avatar, true, m_groupMemberCacheTimeout); + return true; + } + } + m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + return false; + } + + return sp.ControllingClient.IsGroupMember(LandData.GroupID); + } + return false; + } + public bool IsBannedFromLand(UUID avatar) { ExpireAccessList(); @@ -448,6 +490,9 @@ namespace OpenSim.Region.CoreModules.World.Land public bool IsRestrictedFromLand(UUID avatar) { + if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) == 0) + return false; + if (m_scene.Permissions.IsAdministrator(avatar)) return false; @@ -457,10 +502,10 @@ namespace OpenSim.Region.CoreModules.World.Land if (avatar == LandData.OwnerID) return false; - if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) == 0) + if (HasGroupAccess(avatar)) return false; - return (!IsInLandAccessList(avatar)); + return !IsInLandAccessList(avatar); } public bool IsInLandAccessList(UUID avatar) diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/BMP.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/BMP.cs index 90f124bcbf..fb57c8275b 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/BMP.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/BMP.cs @@ -72,5 +72,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders { return "BMP"; } + + //Returns true if this extension is supported for terrain save-tile + public override bool SupportsTileSave() + { + return false; + } } } diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs index f331b562cd..79cc50b386 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs @@ -57,5 +57,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders { return "GIF"; } + + //Returns true if this extension is supported for terrain save-tile + public override bool SupportsTileSave() + { + return false; + } } } diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs index 58925fd624..da81dc16a9 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs @@ -177,6 +177,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders return "SYS.DRAWING"; } + //Returns true if this extension is supported for terrain save-tile + public virtual bool SupportsTileSave() + { + return false; + } + /// /// Protected method, generates a grayscale bitmap /// image from a specified terrain channel. diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs index 1a0d8ecf60..699d67a440 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs @@ -91,6 +91,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders return "JPEG"; } + //Returns true if this extension is supported for terrain save-tile + public bool SupportsTileSave() + { + return false; + } + private static Bitmap CreateBitmapFromMap(ITerrainChannel map) { Bitmap gradientmapLd = new Bitmap("defaultstripe.png"); diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs index fad7641e42..62d232e833 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs @@ -254,5 +254,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders { return "LL/SL RAW"; } + + //Returns true if this extension is supported for terrain save-tile + public bool SupportsTileSave() + { + return false; + } + } } diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs index e009ecf833..c5c12ae6cf 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs @@ -57,5 +57,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders { return "PNG"; } + + //Returns true if this extension is supported for terrain save-tile + public override bool SupportsTileSave() + { + return true; + } } } diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs index ba073cae5a..9fb7ef796e 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs @@ -173,5 +173,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders { return "RAW32"; } + + //Returns true if this extension is supported for terrain save-tile + public bool SupportsTileSave() + { + return false; + } } } diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs index fc1ad33baf..5d2f8937b4 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs @@ -57,5 +57,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders { return "TIFF"; } + + //Returns true if this extension is supported for terrain save-tile + public bool SupportsTileSave() + { + return false; + } } } diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs index 2f37d9d7e9..1ebf91654c 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs @@ -323,6 +323,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders return "Terragen"; } + //Returns true if this extension is supported for terrain save-tile + public bool SupportsTileSave() + { + return false; + } + /// /// terragen SCAL floats need to be written intel ordered regardless of /// big or little endian system diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs index d407617ec5..3ba36577fe 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs @@ -32,6 +32,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain { public interface ITerrainLoader { + // Returns true if that extension can be used for terrain save-tile + // (Look into each file in Region.CoreModules.World.Terrain.FileLoaders) + bool SupportsTileSave(); + string FileExtension { get; } ITerrainChannel LoadFile(string filename); ITerrainChannel LoadFile(string filename, int fileStartX, int fileStartY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight); diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index b3c2969057..8535a5aceb 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -93,6 +93,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain /// private string m_supportedFileExtensions = ""; + //For terrain save-tile file extensions + private string m_supportFileExtensionsForTileSave = ""; + #region ICommandableModule Members public ICommander CommandInterface @@ -148,11 +151,20 @@ namespace OpenSim.Region.CoreModules.World.Terrain // Generate user-readable extensions list string supportedFilesSeparator = ""; + string supportedFilesSeparatorForTileSave = ""; + m_supportFileExtensionsForTileSave = ""; foreach (KeyValuePair loader in m_loaders) { m_supportedFileExtensions += supportedFilesSeparator + loader.Key + " (" + loader.Value + ")"; supportedFilesSeparator = ", "; + + //For terrain save-tile file extensions + if (loader.Value.SupportsTileSave() == true) + { + m_supportFileExtensionsForTileSave += supportedFilesSeparatorForTileSave + loader.Key + " (" + loader.Value + ")"; + supportedFilesSeparatorForTileSave = ", "; + } } } @@ -589,7 +601,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain // this region is included in the tile request foreach (KeyValuePair loader in m_loaders) { - if (filename.EndsWith(loader.Key)) + if (filename.EndsWith(loader.Key) && loader.Value.SupportsTileSave()) { lock (m_scene) { @@ -610,7 +622,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain MainConsole.Instance.OutputFormat( "ERROR: Could not save terrain from {0} to {1}. Valid file extensions are {2}", - m_scene.RegionInfo.RegionName, filename, m_supportedFileExtensions); + m_scene.RegionInfo.RegionName, filename, m_supportFileExtensionsForTileSave); } /// @@ -1192,7 +1204,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain new Command("save-tile", CommandIntentions.COMMAND_HAZARDOUS, InterfaceSaveTileFile, "Saves the current heightmap to the larger file."); saveToTileCommand.AddArgument("filename", "The file you wish to save to, the file extension determines the loader to be used. Supported extensions include: " + - m_supportedFileExtensions, "String"); + m_supportFileExtensionsForTileSave, "String"); saveToTileCommand.AddArgument("file width", "The width of the file in tiles", "Integer"); saveToTileCommand.AddArgument("file height", "The height of the file in tiles", "Integer"); saveToTileCommand.AddArgument("minimum X tile", "The X region coordinate of the first section on the file", diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 5abd74ff96..10b25edac1 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -36,6 +36,7 @@ using OpenMetaverse.Packets; using log4net; using OpenSim.Framework; using OpenSim.Region.Framework; +using OpenSim.Framework.Client; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes.Serialization; @@ -117,31 +118,42 @@ namespace OpenSim.Region.Framework.Scenes /// public bool AddInventoryItem(InventoryItemBase item) { - if (UUID.Zero == item.Folder) + if (item.Folder != UUID.Zero && InventoryService.AddItem(item)) { - InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); + int userlevel = 0; + if (Permissions.IsGod(item.Owner)) + { + userlevel = 1; + } + EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); + + return true; + } + + // OK so either the viewer didn't send a folderID or AddItem failed + UUID originalFolder = item.Folder; + InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); + if (f != null) + { + m_log.DebugFormat( + "[AGENT INVENTORY]: Found folder {0} type {1} for item {2}", + f.Name, (AssetType)f.Type, item.Name); + + item.Folder = f.ID; + } + else + { + f = InventoryService.GetRootFolder(item.Owner); if (f != null) { -// m_log.DebugFormat( -// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}", -// f.Name, (AssetType)f.Type, item.Name); - item.Folder = f.ID; } else { - f = InventoryService.GetRootFolder(item.Owner); - if (f != null) - { - item.Folder = f.ID; - } - else - { - m_log.WarnFormat( - "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified", - item.Owner, item.Name); - return false; - } + m_log.WarnFormat( + "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified", + item.Owner, item.Name); + return false; } } @@ -153,7 +165,13 @@ namespace OpenSim.Region.Framework.Scenes userlevel = 1; } EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); - + + if (originalFolder != UUID.Zero) + { + // Tell the viewer that the item didn't go there + ChangePlacement(item, f); + } + return true; } else @@ -165,7 +183,32 @@ namespace OpenSim.Region.Framework.Scenes return false; } } - + + private void ChangePlacement(InventoryItemBase item, InventoryFolderBase f) + { + ScenePresence sp = GetScenePresence(item.Owner); + if (sp != null) + { + if (sp.ControllingClient is IClientCore) + { + IClientCore core = (IClientCore)sp.ControllingClient; + IClientInventory inv; + + if (core.TryGet(out inv)) + { + InventoryFolderBase parent = new InventoryFolderBase(f.ParentID, f.Owner); + parent = InventoryService.GetFolder(parent); + inv.SendRemoveInventoryItems(new UUID[] { item.ID }); + inv.SendBulkUpdateInventory(new InventoryFolderBase[0], new InventoryItemBase[] { item }); + string message = "The item was placed in folder " + f.Name; + if (parent != null) + message += " under " + parent.Name; + sp.ControllingClient.SendAgentAlertMessage(message, false); + } + } + } + } + /// /// Add the given inventory item to a user's inventory. /// diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 2a15e5d6f6..e669f4c74c 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -1294,7 +1294,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups OnAgentDataUpdateRequest(remoteClient, dataForAgentID, UUID.Zero); - // Need to send a group membership update to the client // UDP version doesn't seem to behave nicely. But we're going to send it out here // with an empty group membership to hopefully remove groups being displayed due @@ -1305,6 +1304,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups SendGroupMembershipInfoViaCaps(remoteClient, dataForAgentID, membershipArray); remoteClient.SendAvatarGroupsReply(dataForAgentID, membershipArray); + if (remoteClient.AgentId == dataForAgentID) + remoteClient.RefreshGroupMembership(); } /// diff --git a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs index 040c8405b3..cb9b65da77 100644 --- a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs +++ b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs @@ -114,6 +114,8 @@ namespace OpenSim.Server.Handlers.Asset return HandleCreateUserInventory(request); case "GETINVENTORYSKELETON": return HandleGetInventorySkeleton(request); + case "GETUSERINVENTORY": + return HandleGetUserInventory(request); case "GETROOTFOLDER": return HandleGetRootFolder(request); case "GETFOLDERFORTYPE": @@ -153,7 +155,7 @@ namespace OpenSim.Server.Handlers.Asset } catch (Exception e) { - m_log.DebugFormat("[XINVENTORY HANDLER]: Exception {0}", e); + m_log.DebugFormat("[XINVENTORY HANDLER]: Exception {0}", e.StackTrace); } return FailureResult(); @@ -248,6 +250,45 @@ namespace OpenSim.Server.Handlers.Asset return encoding.GetBytes(xmlString); } + byte[] HandleGetUserInventory(Dictionary request) + { + Dictionary result = new Dictionary(); + UUID principal = UUID.Zero; + UUID.TryParse(request["PRINCIPAL"].ToString(), out principal); + + InventoryCollection icoll = m_InventoryService.GetUserInventory(principal); + if (icoll != null) + { + Dictionary folders = new Dictionary(); + int i = 0; + if (icoll.Folders != null) + { + foreach (InventoryFolderBase f in icoll.Folders) + { + folders["folder_" + i.ToString()] = EncodeFolder(f); + i++; + } + result["FOLDERS"] = folders; + } + if (icoll.Items != null) + { + i = 0; + Dictionary items = new Dictionary(); + foreach (InventoryItemBase it in icoll.Items) + { + items["item_" + i.ToString()] = EncodeItem(it); + i++; + } + result["ITEMS"] = items; + } + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + UTF8Encoding encoding = new UTF8Encoding(); + return encoding.GetBytes(xmlString); + } + byte[] HandleGetRootFolder(Dictionary request) { Dictionary result = new Dictionary(); @@ -293,22 +334,27 @@ namespace OpenSim.Server.Handlers.Asset if (icoll != null) { Dictionary folders = new Dictionary(); - int i = 0; - foreach (InventoryFolderBase f in icoll.Folders) + int i = 0; + if (icoll.Folders != null) { - folders["folder_" + i.ToString()] = EncodeFolder(f); - i++; + foreach (InventoryFolderBase f in icoll.Folders) + { + folders["folder_" + i.ToString()] = EncodeFolder(f); + i++; + } + result["FOLDERS"] = folders; } - result["FOLDERS"] = folders; - - i = 0; - Dictionary items = new Dictionary(); - foreach (InventoryItemBase it in icoll.Items) + if (icoll.Items != null) { - items["item_" + i.ToString()] = EncodeItem(it); - i++; + i = 0; + Dictionary items = new Dictionary(); + foreach (InventoryItemBase it in icoll.Items) + { + items["item_" + i.ToString()] = EncodeItem(it); + i++; + } + result["ITEMS"] = items; } - result["ITEMS"] = items; } string xmlString = ServerUtils.BuildXmlResponse(result); diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs index 39e983bfd9..9d96703c1a 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs @@ -111,19 +111,21 @@ namespace OpenSim.Services.Connectors if (ret.Count == 0) return null; - List folders = new List(); + Dictionary folders = (Dictionary)ret["FOLDERS"]; + + List fldrs = new List(); try { - foreach (Object o in ret.Values) - folders.Add(BuildFolder((Dictionary)o)); + foreach (Object o in folders.Values) + fldrs.Add(BuildFolder((Dictionary)o)); } catch (Exception e) { m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception unwrapping folder list: {0}", e.Message); } - return folders; + return fldrs; } public InventoryFolderBase GetRootFolder(UUID principalID) @@ -492,12 +494,41 @@ namespace OpenSim.Services.Connectors return int.Parse(ret["RESULT"].ToString()); } - - // These are either obsolete or unused - // public InventoryCollection GetUserInventory(UUID principalID) { - return null; + InventoryCollection inventory = new InventoryCollection(); + inventory.Folders = new List(); + inventory.Items = new List(); + inventory.UserID = principalID; + + try + { + Dictionary ret = MakeRequest("GETUSERINVENTORY", + new Dictionary { + { "PRINCIPAL", principalID.ToString() } + }); + + if (ret == null) + return null; + if (ret.Count == 0) + return null; + + Dictionary folders = + (Dictionary)ret["FOLDERS"]; + Dictionary items = + (Dictionary)ret["ITEMS"]; + + foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i + inventory.Folders.Add(BuildFolder((Dictionary)o)); + foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i + inventory.Items.Add(BuildItem((Dictionary)o)); + } + catch (Exception e) + { + m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetUserInventory: {0}", e.Message); + } + + return inventory; } public void GetUserInventory(UUID principalID, InventoryReceiptCallback callback) diff --git a/OpenSim/Services/HypergridService/HGInventoryService.cs b/OpenSim/Services/HypergridService/HGInventoryService.cs index b29d803e90..2e9bd40cd2 100644 --- a/OpenSim/Services/HypergridService/HGInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGInventoryService.cs @@ -105,6 +105,12 @@ namespace OpenSim.Services.HypergridService return new List(); } + public override InventoryCollection GetUserInventory(UUID userID) + { + // NOGO for this inventory service + return null; + } + public override InventoryFolderBase GetRootFolder(UUID principalID) { //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetRootFolder for {0}", principalID); diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs index cb686e26e6..b6ec558b80 100644 --- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs @@ -59,7 +59,7 @@ namespace OpenSim.Services.HypergridService private UserAccountCache m_Cache; - private ExpiringCache> m_SuitcaseTrees = new ExpiringCache>(); + private ExpiringCache> m_SuitcaseTrees = new ExpiringCache>(); public HGSuitcaseInventoryService(IConfigSource config, string configName) : base(config, configName) @@ -104,11 +104,72 @@ namespace OpenSim.Services.HypergridService return false; } - public override List GetInventorySkeleton(UUID principalID) { - // NOGO for this inventory service - return new List(); + XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); + XInventoryFolder root = GetRootXFolder(principalID); + + List tree = GetFolderTree(suitcase.folderID); + if (tree == null || (tree != null && tree.Count == 0)) + return null; + + List folders = new List(); + foreach (XInventoryFolder x in tree) + { + folders.Add(ConvertToOpenSim(x)); + } + + SetAsRootFolder(suitcase, root); + folders.Add(ConvertToOpenSim(suitcase)); + + return folders; + } + + public override InventoryCollection GetUserInventory(UUID userID) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Get Suitcase inventory for user {0}", userID); + InventoryCollection userInventory = new InventoryCollection(); + userInventory.UserID = userID; + userInventory.Folders = new List(); + userInventory.Items = new List(); + + XInventoryFolder suitcase = GetSuitcaseXFolder(userID); + XInventoryFolder root = GetRootXFolder(userID); + + List tree = GetFolderTree(suitcase.folderID); + if (tree == null || (tree != null && tree.Count == 0)) + { + SetAsRootFolder(suitcase, root); + userInventory.Folders.Add(ConvertToOpenSim(suitcase)); + return userInventory; + } + + List items; + foreach (XInventoryFolder f in tree) + { + // Add the items of this subfolder + items = GetFolderItems(userID, f.folderID); + if (items != null && items.Count > 0) + { + userInventory.Items.AddRange(items); + } + + // Add the folder itself + userInventory.Folders.Add(ConvertToOpenSim(f)); + } + + items = GetFolderItems(userID, suitcase.folderID); + if (items != null && items.Count > 0) + { + userInventory.Items.AddRange(items); + } + + SetAsRootFolder(suitcase, root); + userInventory.Folders.Add(ConvertToOpenSim(suitcase)); + + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetUserInventory for user {0} returning {1} folders and {2} items", + userID, userInventory.Folders.Count, userInventory.Items.Count); + return userInventory; } public override InventoryFolderBase GetRootFolder(UUID principalID) @@ -131,51 +192,92 @@ namespace OpenSim.Services.HypergridService { m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: User {0} does not have a Suitcase folder. Creating it...", principalID); // make one, and let's add it to the user's inventory as a direct child of the root folder + // In the DB we tag it as type 100, but we use -1 (Unknown) outside suitcase = CreateFolder(principalID, root.folderID, 100, "My Suitcase"); if (suitcase == null) m_log.ErrorFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to create suitcase folder"); - m_Database.StoreFolder(suitcase); + + // Create System folders + CreateSystemFolders(principalID, suitcase.folderID); } - // Now let's change the folder ID to match that of the real root folder - SetAsRootFolder(suitcase, root.folderID); + SetAsRootFolder(suitcase, root); return ConvertToOpenSim(suitcase); } + protected void CreateSystemFolders(UUID principalID, UUID rootID) + { + m_log.Debug("[HG SUITCASE INVENTORY SERVICE]: Creating System folders under Suitcase..."); + XInventoryFolder[] sysFolders = GetSystemFolders(principalID, rootID); + + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Animation) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Animation, "Animations"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Bodypart) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Bodypart, "Body Parts"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.CallingCard) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.CallingCard, "Calling Cards"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Clothing) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Clothing, "Clothing"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Gesture) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Gesture, "Gestures"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Landmark) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Landmark, "Landmarks"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.LostAndFoundFolder) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.LostAndFoundFolder, "Lost And Found"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Notecard) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Notecard, "Notecards"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Object) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Object, "Objects"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.SnapshotFolder) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.SnapshotFolder, "Photo Album"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.LSLText) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.LSLText, "Scripts"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Sound) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Sound, "Sounds"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Texture) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Texture, "Textures"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.TrashFolder) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.TrashFolder, "Trash"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.FavoriteFolder) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.FavoriteFolder, "Favorites"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.CurrentOutfitFolder) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.CurrentOutfitFolder, "Current Outfit"); + + } + public override InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) { //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetFolderForType for {0} {0}", principalID, type); - return GetRootFolder(principalID); + XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "agentID", "type", "parentFolderID" }, + new string[] { principalID.ToString(), ((int)type).ToString(), suitcase.folderID.ToString() }); + + if (folders.Length == 0) + { + m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Found no folder for type {0} for user {1}", type, principalID); + return null; + } + + m_log.DebugFormat( + "[HG SUITCASE INVENTORY SERVICE]: Found folder {0} {1} for type {2} for user {3}", + folders[0].folderName, folders[0].folderID, type, principalID); + + return ConvertToOpenSim(folders[0]); } public override InventoryCollection GetFolderContent(UUID principalID, UUID folderID) { InventoryCollection coll = null; XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); - XInventoryFolder root = GetRootXFolder(principalID); - if (!IsWithinSuitcaseTree(folderID, root, suitcase)) + if (!IsWithinSuitcaseTree(folderID, suitcase)) return new InventoryCollection(); - if (folderID == root.folderID) // someone's asking for the root folder, we'll give them the suitcase - { - if (suitcase != null) - { - coll = base.GetFolderContent(principalID, suitcase.folderID); - foreach (InventoryFolderBase f in coll.Folders) - f.ParentID = root.folderID; - foreach (InventoryItemBase i in coll.Items) - i.Folder = root.folderID; - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetFolderContent for root folder returned content for suitcase folder"); - } - } - else - { - coll = base.GetFolderContent(principalID, folderID); - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetFolderContent for non-root folder {0}", folderID); - } + coll = base.GetFolderContent(principalID, folderID); + if (coll == null) { m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Something wrong with user {0}'s suitcase folder", principalID); @@ -188,10 +290,9 @@ namespace OpenSim.Services.HypergridService { // Let's do a bit of sanity checking, more than the base service does // make sure the given folder exists under the suitcase tree of this user - XInventoryFolder root = GetRootXFolder(principalID); XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); - if (!IsWithinSuitcaseTree(folderID, root, suitcase)) + if (!IsWithinSuitcaseTree(folderID, suitcase)) return new List(); return base.GetFolderItems(principalID, folderID); @@ -199,52 +300,40 @@ namespace OpenSim.Services.HypergridService public override bool AddFolder(InventoryFolderBase folder) { + m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder {0} {1}", folder.Name, folder.ParentID); // Let's do a bit of sanity checking, more than the base service does // make sure the given folder's parent folder exists under the suitcase tree of this user - XInventoryFolder root = GetRootXFolder(folder.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); - if (!IsWithinSuitcaseTree(folder.ParentID, root, suitcase)) + if (!IsWithinSuitcaseTree(folder.ParentID, suitcase)) return false; // OK, it's legit - // Check if it's under the Root folder directly - if (folder.ParentID == root.folderID) - { - // someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder for root folder for user {0}. Adding in suitcase instead", folder.Owner); - folder.ParentID = suitcase.folderID; - } - return base.AddFolder(folder); - } + } - public bool UpdateFolder(InventoryFolderBase folder) + public override bool UpdateFolder(InventoryFolderBase folder) { - XInventoryFolder root = GetRootXFolder(folder.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); - if (!IsWithinSuitcaseTree(folder.ID, root, suitcase)) + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version); + if (!IsWithinSuitcaseTree(folder.ID, suitcase)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name); return false; + } + // For all others return base.UpdateFolder(folder); } public override bool MoveFolder(InventoryFolderBase folder) { - XInventoryFolder root = GetRootXFolder(folder.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); - if (!IsWithinSuitcaseTree(folder.ID, root, suitcase) || !IsWithinSuitcaseTree(folder.ParentID, root, suitcase)) + if (!IsWithinSuitcaseTree(folder.ID, suitcase) || !IsWithinSuitcaseTree(folder.ParentID, suitcase)) return false; - if (folder.ParentID == root.folderID) - { - // someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveFolder to root folder for user {0}. Moving it to suitcase instead", folder.Owner); - folder.ParentID = suitcase.folderID; - } - return base.MoveFolder(folder); } @@ -264,31 +353,21 @@ namespace OpenSim.Services.HypergridService { // Let's do a bit of sanity checking, more than the base service does // make sure the given folder's parent folder exists under the suitcase tree of this user - XInventoryFolder root = GetRootXFolder(item.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(item.Owner); - if (!IsWithinSuitcaseTree(item.Folder, root, suitcase)) + if (!IsWithinSuitcaseTree(item.Folder, suitcase)) return false; // OK, it's legit - // Check if it's under the Root folder directly - if (item.Folder == root.folderID) - { - // someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: AddItem for root folder for user {0}. Adding in suitcase instead", item.Owner); - item.Folder = suitcase.folderID; - } - return base.AddItem(item); } public override bool UpdateItem(InventoryItemBase item) { - XInventoryFolder root = GetRootXFolder(item.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(item.Owner); - if (!IsWithinSuitcaseTree(item.Folder, root, suitcase)) + if (!IsWithinSuitcaseTree(item.Folder, suitcase)) return false; return base.UpdateItem(item); @@ -298,68 +377,64 @@ namespace OpenSim.Services.HypergridService { // Principal is b0rked. *sigh* - XInventoryFolder root = GetRootXFolder(items[0].Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(items[0].Owner); - if (!IsWithinSuitcaseTree(items[0].Folder, root, suitcase)) + if (!IsWithinSuitcaseTree(items[0].Folder, suitcase)) return false; - foreach (InventoryItemBase it in items) - if (it.Folder == root.folderID) - { - // someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveItem to root folder for user {0}. Moving it to suitcase instead", it.Owner); - it.Folder = suitcase.folderID; - } - return base.MoveItems(principalID, items); } - // Let these pass. Use inherited methods. public override bool DeleteItems(UUID principalID, List itemIDs) { return false; } - public override InventoryItemBase GetItem(InventoryItemBase item) + public new InventoryItemBase GetItem(InventoryItemBase item) { InventoryItemBase it = base.GetItem(item); - XInventoryFolder root = GetRootXFolder(it.Owner); - XInventoryFolder suitcase = GetSuitcaseXFolder(it.Owner); - - if (it != null) + if (it == null) { - if (!IsWithinSuitcaseTree(it.Folder, root, suitcase)) - return null; - - if (it.Folder == suitcase.folderID) - it.Folder = root.folderID; - - // UserAccount user = m_Cache.GetUser(it.CreatorId); - - // // Adjust the creator data - // if (user != null && it != null && (it.CreatorData == null || it.CreatorData == string.Empty)) - // it.CreatorData = m_HomeURL + ";" + user.FirstName + " " + user.LastName; - //} + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve item {0} ({1}) in folder {2}", + item.Name, item.ID, item.Folder); + return null; } + XInventoryFolder suitcase = GetSuitcaseXFolder(it.Owner); + if (suitcase == null) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Root or Suitcase are null for user {0}", + it.Owner); + return null; + } + + if (!IsWithinSuitcaseTree(it.Folder, suitcase)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Item {0} (folder {1}) is not within Suitcase", + it.Name, it.Folder); + return null; + } + + // UserAccount user = m_Cache.GetUser(it.CreatorId); + + // // Adjust the creator data + // if (user != null && it != null && (it.CreatorData == null || it.CreatorData == string.Empty)) + // it.CreatorData = m_HomeURL + ";" + user.FirstName + " " + user.LastName; + //} return it; } - public override InventoryFolderBase GetFolder(InventoryFolderBase folder) + public new InventoryFolderBase GetFolder(InventoryFolderBase folder) { InventoryFolderBase f = base.GetFolder(folder); - XInventoryFolder root = GetRootXFolder(f.Owner); - XInventoryFolder suitcase = GetSuitcaseXFolder(f.Owner); if (f != null) { - if (!IsWithinSuitcaseTree(f.ID, root, suitcase)) - return null; + XInventoryFolder suitcase = GetSuitcaseXFolder(f.Owner); - if (f.ParentID == suitcase.folderID) - f.ParentID = root.folderID; + if (!IsWithinSuitcaseTree(f.ID, suitcase)) + return null; } return f; @@ -409,20 +484,19 @@ namespace OpenSim.Services.HypergridService return null; } - private void SetAsRootFolder(XInventoryFolder suitcase, UUID rootID) + private void SetAsRootFolder(XInventoryFolder suitcase, XInventoryFolder root) { - suitcase.folderID = rootID; - suitcase.parentFolderID = UUID.Zero; + suitcase.type = (short)AssetType.Folder; } - private List GetFolderTree(UUID root) + private List GetFolderTree(UUID folder) { List t = null; - if (m_SuitcaseTrees.TryGetValue(root, out t)) + if (m_SuitcaseTrees.TryGetValue(folder, out t)) return t; - t = GetFolderTreeRecursive(root); - m_SuitcaseTrees.AddOrUpdate(root, t, 120); + t = GetFolderTreeRecursive(folder); + m_SuitcaseTrees.AddOrUpdate(folder, t, 120); return t; } @@ -447,10 +521,17 @@ namespace OpenSim.Services.HypergridService } - private bool IsWithinSuitcaseTree(UUID folderID, XInventoryFolder root, XInventoryFolder suitcase) + /// + /// Return true if the folderID is a subfolder of the Suitcase or the suitcase folder itself + /// + /// + /// + /// + /// + private bool IsWithinSuitcaseTree(UUID folderID, XInventoryFolder suitcase) { List tree = new List(); - tree.Add(root); // Warp! the tree is the real root folder plus the children of the suitcase folder + tree.Add(suitcase); // Warp! the tree is the real root folder plus the children of the suitcase folder tree.AddRange(GetFolderTree(suitcase.folderID)); XInventoryFolder f = tree.Find(delegate(XInventoryFolder fl) { @@ -463,4 +544,5 @@ namespace OpenSim.Services.HypergridService } #endregion } + } diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 7b2c3a6aff..0e7a3584e2 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -40,9 +40,9 @@ namespace OpenSim.Services.InventoryService { public class XInventoryService : ServiceBase, IInventoryService { -// private static readonly ILog m_log = -// LogManager.GetLogger( -// MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); protected IXInventoryData m_Database; protected bool m_AllowDelete = true; @@ -113,7 +113,7 @@ namespace OpenSim.Services.InventoryService result = true; } - XInventoryFolder[] sysFolders = GetSystemFolders(principalID); + XInventoryFolder[] sysFolders = GetSystemFolders(principalID, rootFolder.ID); if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Animation) return true; return false; })) CreateFolder(principalID, rootFolder.ID, (int)AssetType.Animation, "Animations"); @@ -163,13 +163,13 @@ namespace OpenSim.Services.InventoryService return newFolder; } - protected virtual XInventoryFolder[] GetSystemFolders(UUID principalID) + protected virtual XInventoryFolder[] GetSystemFolders(UUID principalID, UUID rootID) { // m_log.DebugFormat("[XINVENTORY SERVICE]: Getting system folders for {0}", principalID); XInventoryFolder[] allFolders = m_Database.GetFolders( - new string[] { "agentID" }, - new string[] { principalID.ToString() }); + new string[] { "agentID", "parentFolderID" }, + new string[] { principalID.ToString(), rootID.ToString() }); XInventoryFolder[] sysFolders = Array.FindAll( allFolders, @@ -301,16 +301,26 @@ namespace OpenSim.Services.InventoryService public virtual bool AddFolder(InventoryFolderBase folder) { + //m_log.DebugFormat("[XINVENTORY]: Add folder {0} type {1} in parent {2}", folder.Name, folder.Type, folder.ParentID); InventoryFolderBase check = GetFolder(folder); if (check != null) return false; - XInventoryFolder xFolder = ConvertFromOpenSim(folder); - return m_Database.StoreFolder(xFolder); + if (folder.Type == (short)AssetType.Folder || folder.Type == (short)AssetType.Unknown || + GetFolderForType(folder.Owner, (AssetType)(folder.Type)) == null) + { + XInventoryFolder xFolder = ConvertFromOpenSim(folder); + return m_Database.StoreFolder(xFolder); + } + else + m_log.DebugFormat("[XINVENTORY]: Folder {0} of type {1} already exists", folder.Name, folder.Type); + + return false; } public virtual bool UpdateFolder(InventoryFolderBase folder) { + //m_log.DebugFormat("[XINVENTORY]: Update folder {0} {1} ({2})", folder.Name, folder.Type, folder.ID); XInventoryFolder xFolder = ConvertFromOpenSim(folder); InventoryFolderBase check = GetFolder(folder); if (check == null) @@ -319,9 +329,13 @@ namespace OpenSim.Services.InventoryService if (check.Type != -1 || xFolder.type != -1) { if (xFolder.version < check.Version) + { + //m_log.DebugFormat("[XINVENTORY]: {0} < {1} can't do", xFolder.version, check.Version); return false; + } check.Version = (ushort)xFolder.version; xFolder = ConvertFromOpenSim(check); + //m_log.DebugFormat("[XINVENTORY]: Storing {0} {1} {2}", xFolder.folderName, xFolder.version, xFolder.type); return m_Database.StoreFolder(xFolder); } @@ -499,13 +513,30 @@ namespace OpenSim.Services.InventoryService return m_Database.GetAssetPermissions(principalID, assetID); } - // CM never needed those. Left unimplemented. - // Obsolete in core - // - public InventoryCollection GetUserInventory(UUID userID) + public virtual InventoryCollection GetUserInventory(UUID userID) { - return null; + InventoryCollection userInventory = new InventoryCollection(); + userInventory.UserID = userID; + userInventory.Folders = new List(); + userInventory.Items = new List(); + + List skel = GetInventorySkeleton(userID); + if (skel != null) + { + foreach (InventoryFolderBase f in skel) + { + InventoryCollection c = GetFolderContent(userID, f.ID); + if (c != null && c.Items != null && c.Items.Count > 0) + userInventory.Items.AddRange(c.Items); + if (c != null && c.Folders != null && c.Folders.Count > 0) + userInventory.Folders.AddRange(c.Folders); + } + } + m_log.DebugFormat("[XINVENTORY SERVICE]: GetUserInventory for user {0} returning {1} folders and {2} items", + userID, userInventory.Folders.Count, userInventory.Items.Count); + return userInventory; } + public void GetUserInventory(UUID userID, InventoryReceiptCallback callback) { } @@ -525,6 +556,9 @@ namespace OpenSim.Services.InventoryService newFolder.ParentID = folder.parentFolderID; newFolder.Type = (short)folder.type; + // Viewer can't understand anything that's not in it's LLFolderType enum + if (newFolder.Type == 100) + newFolder.Type = -1; newFolder.Version = (ushort)folder.version; newFolder.Name = folder.folderName; newFolder.Owner = folder.agentID;