From 9a9923405a956026b1b67b4f6f993a292b230f67 Mon Sep 17 00:00:00 2001 From: Garmin Kawaguichi Date: Tue, 3 Apr 2012 16:56:51 +0200 Subject: [PATCH 01/15] terrain save-tile extensions Signed-off-by: Garmin Kawaguichi Signed-off-by: Melanie --- .../World/Terrain/FileLoaders/BMP.cs | 6 ++++++ .../World/Terrain/FileLoaders/GIF.cs | 6 ++++++ .../FileLoaders/GenericSystemDrawing.cs | 6 ++++++ .../World/Terrain/FileLoaders/JPEG.cs | 6 ++++++ .../World/Terrain/FileLoaders/LLRAW.cs | 7 +++++++ .../World/Terrain/FileLoaders/PNG.cs | 6 ++++++ .../World/Terrain/FileLoaders/RAW32.cs | 6 ++++++ .../World/Terrain/FileLoaders/TIFF.cs | 6 ++++++ .../World/Terrain/FileLoaders/Terragen.cs | 6 ++++++ .../World/Terrain/ITerrainLoader.cs | 4 ++++ .../CoreModules/World/Terrain/TerrainModule.cs | 18 +++++++++++++++--- 11 files changed, 74 insertions(+), 3 deletions(-) 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", From 36c8fa16c012dd18012f0c8921fa93c4fbd53b5c Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Thu, 5 Apr 2012 00:53:40 +0200 Subject: [PATCH 02/15] Implements group based access restrictions for parcels of land. Because of caching there can be a delay of up to 30 seconds until the access rights are effectively changed for a user. --- .../CoreModules/World/Land/LandObject.cs | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index a0ed5a5274..9808ebf95a 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -56,6 +56,12 @@ namespace OpenSim.Region.CoreModules.World.Land protected List primsOverMe = new List(); protected Dictionary m_listTransactions = new Dictionary(); + protected IGroupsModule m_groupsModule; + protected const uint PARCEL_FLAG_USE_ACCESS_GROUP = 0x100; // parcel limits access to a group + protected Dictionary m_isGroupMemberCache = new Dictionary(); + protected Dictionary m_notGroupMemberCache = new Dictionary(); + protected const long m_groupMemberCacheTimeout = 30; // cache invalidation after 30 seconds + public bool[,] LandBitmap { get { return m_landBitmap; } @@ -132,6 +138,8 @@ namespace OpenSim.Region.CoreModules.World.Land else LandData.GroupID = UUID.Zero; LandData.IsGroupOwned = is_group_owned; + + m_groupsModule = scene.RequestModuleInterface(); } #endregion @@ -460,7 +468,55 @@ namespace OpenSim.Region.CoreModules.World.Land if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) == 0) return false; - return (!IsInLandAccessList(avatar)); + if (IsInLandAccessList(avatar)) + return false; + + UUID groupID = LandData.GroupID; + + if ((m_groupsModule != null) && (groupID != UUID.Zero) && ((LandData.Flags & PARCEL_FLAG_USE_ACCESS_GROUP) == PARCEL_FLAG_USE_ACCESS_GROUP)) + { + long now = Util.UnixTimeSinceEpoch(); + + if (m_isGroupMemberCache.ContainsKey(avatar)) + { + if (now - m_isGroupMemberCache[avatar] <= m_groupMemberCacheTimeout) // invalid? + { + m_isGroupMemberCache[avatar] = now; + return false; + } + else + m_isGroupMemberCache.Remove(avatar); + } + + if (m_notGroupMemberCache.ContainsKey(avatar)) + { + if (now - m_notGroupMemberCache[avatar] <= m_groupMemberCacheTimeout) // invalid? + { + // m_notGroupMemberCache[avatar] = now; + return true; + } + else + m_notGroupMemberCache.Remove(avatar); + } + + GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(avatar); + + if (GroupMembership != null) + { + for (int i = 0; i < GroupMembership.Length; i++) + { + if (groupID == GroupMembership[i].GroupID) + { + m_isGroupMemberCache[avatar] = now; + return false; + } + } + } + + m_notGroupMemberCache[avatar] = now; + } + + return true; } public bool IsInLandAccessList(UUID avatar) From a5d6b624f6e2abf8dd3e66b2f1f6924f5f1125d1 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 5 Apr 2012 00:45:58 +0100 Subject: [PATCH 03/15] Simplify group access checks and break them out into a separate method. Use existing cache if the avatar is within the region and use an ExpiringCache to cache status if the avatar is not in the region. The 30 second delay now applies to scripted objects ony and only when the owner is not present. --- .../CoreModules/World/Land/LandObject.cs | 106 ++++++++---------- 1 file changed, 49 insertions(+), 57 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 9808ebf95a..c532d0d645 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -56,11 +56,8 @@ namespace OpenSim.Region.CoreModules.World.Land protected List primsOverMe = new List(); protected Dictionary m_listTransactions = new Dictionary(); - protected IGroupsModule m_groupsModule; - protected const uint PARCEL_FLAG_USE_ACCESS_GROUP = 0x100; // parcel limits access to a group - protected Dictionary m_isGroupMemberCache = new Dictionary(); - protected Dictionary m_notGroupMemberCache = new Dictionary(); - protected const long m_groupMemberCacheTimeout = 30; // cache invalidation after 30 seconds + protected ExpiringCache m_groupMemberCache = new ExpiringCache(); + protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds public bool[,] LandBitmap { @@ -138,8 +135,6 @@ namespace OpenSim.Region.CoreModules.World.Land else LandData.GroupID = UUID.Zero; LandData.IsGroupOwned = is_group_owned; - - m_groupsModule = scene.RequestModuleInterface(); } #endregion @@ -425,6 +420,48 @@ 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, false, m_groupMemberCacheTimeout); + return true; + } + } + m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + return false; + } + + if (!sp.ControllingClient.IsGroupMember(LandData.GroupID)) + return false; + + return true; + } + return false; + } + public bool IsBannedFromLand(UUID avatar) { ExpireAccessList(); @@ -456,6 +493,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; @@ -465,58 +505,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; - if (IsInLandAccessList(avatar)) - return false; - - UUID groupID = LandData.GroupID; - - if ((m_groupsModule != null) && (groupID != UUID.Zero) && ((LandData.Flags & PARCEL_FLAG_USE_ACCESS_GROUP) == PARCEL_FLAG_USE_ACCESS_GROUP)) - { - long now = Util.UnixTimeSinceEpoch(); - - if (m_isGroupMemberCache.ContainsKey(avatar)) - { - if (now - m_isGroupMemberCache[avatar] <= m_groupMemberCacheTimeout) // invalid? - { - m_isGroupMemberCache[avatar] = now; - return false; - } - else - m_isGroupMemberCache.Remove(avatar); - } - - if (m_notGroupMemberCache.ContainsKey(avatar)) - { - if (now - m_notGroupMemberCache[avatar] <= m_groupMemberCacheTimeout) // invalid? - { - // m_notGroupMemberCache[avatar] = now; - return true; - } - else - m_notGroupMemberCache.Remove(avatar); - } - - GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(avatar); - - if (GroupMembership != null) - { - for (int i = 0; i < GroupMembership.Length; i++) - { - if (groupID == GroupMembership[i].GroupID) - { - m_isGroupMemberCache[avatar] = now; - return false; - } - } - } - - m_notGroupMemberCache[avatar] = now; - } - - return true; + return !IsInLandAccessList(avatar); } public bool IsInLandAccessList(UUID avatar) From 600a86bcaeb78089165f7d778661edbfdface047 Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Thu, 5 Apr 2012 10:02:18 +0200 Subject: [PATCH 04/15] Little bug fix in HasGroupAccess, to properly store the case "true" in the cache. --- OpenSim/Region/CoreModules/World/Land/LandObject.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index c532d0d645..ced7b523b2 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -446,7 +446,7 @@ namespace OpenSim.Region.CoreModules.World.Land { if (d.GroupID == LandData.GroupID) { - m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + m_groupMemberCache.Add(avatar, true, m_groupMemberCacheTimeout); return true; } } @@ -454,10 +454,7 @@ namespace OpenSim.Region.CoreModules.World.Land return false; } - if (!sp.ControllingClient.IsGroupMember(LandData.GroupID)) - return false; - - return true; + return sp.ControllingClient.IsGroupMember(LandData.GroupID); } return false; } From e4406c846d74212493890a46922292cd7fec2ea5 Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Thu, 5 Apr 2012 10:25:54 +0200 Subject: [PATCH 05/15] Group based access restrictions to parcels require group membership, but not that this group is active for that user. --- .../CoreModules/World/Land/LandObject.cs | 49 +++++++++---------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index ced7b523b2..a7c7cc5234 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -424,37 +424,34 @@ namespace OpenSim.Region.CoreModules.World.Land { 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) { - 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); + 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 false; } From 8f45eb913c6fad38735f00db818e03c4123904aa Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Thu, 5 Apr 2012 11:10:05 +0200 Subject: [PATCH 06/15] Revert last commit --- .../CoreModules/World/Land/LandObject.cs | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index a7c7cc5234..ced7b523b2 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -424,34 +424,37 @@ namespace OpenSim.Region.CoreModules.World.Land { if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) { - bool isMember; - if (m_groupMemberCache.TryGetValue(avatar, out isMember)) - return isMember; - - IGroupsModule groupsModule = m_scene.RequestModuleInterface(); - if (groupsModule == null) + ScenePresence sp; + if (!m_scene.TryGetScenePresence(avatar, out sp)) { - m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); - return false; - } + bool isMember; + if (m_groupMemberCache.TryGetValue(avatar, out isMember)) + return isMember; - GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar); - if (membership == null || membership.Length == 0) - { - m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); - return false; - } + IGroupsModule groupsModule = m_scene.RequestModuleInterface(); + if (groupsModule == null) + return false; - foreach (GroupMembershipData d in membership) - { - if (d.GroupID == LandData.GroupID) + GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar); + if (membership == null || membership.Length == 0) { - m_groupMemberCache.Add(avatar, true, m_groupMemberCacheTimeout); - return true; + 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; } - m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); - return false; + + return sp.ControllingClient.IsGroupMember(LandData.GroupID); } return false; } From 67537f359688bfa592312baf808e9d399fc164fa Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Thu, 5 Apr 2012 13:03:57 +0200 Subject: [PATCH 07/15] Added missing refresh of group membership client side cache to the groups module. Before memberships of non active groups often were not stored in the cache (n_groupPowers). --- .../Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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(); } /// From cdbe34716f78072168189e30ac5d6b8e7bcc91ef Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 11:21:27 -0700 Subject: [PATCH 08/15] Thank you, BaseHttpServer, for telling me where things go wrong. --- OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From e324fb241505c92ea845421280c4a8ca372e3ded Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 11:22:30 -0700 Subject: [PATCH 09/15] Guard against null inventory contents. --- .../WebFetchInventoryDescendents/WebFetchInvDescHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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) { From 8fd86c91561ade716a9179653e9ffb75ff1df438 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 11:24:34 -0700 Subject: [PATCH 10/15] Packing of folder in SendBulkUpdateInventory always set the folder type to -1. Not sure if there's a reason for it, but I'm changing it to the given folder type. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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; From 6eaff18961668ba6141a7dd26a3df873489f64b5 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 11:38:47 -0700 Subject: [PATCH 11/15] Finish the implementation of GetUserInventory, even though it's still not used. --- .../Inventory/HGInventoryBroker.cs | 43 +++++++++-- .../Inventory/InventoryCache.cs | 51 +++++++++++++ .../RemoteXInventoryServiceConnector.cs | 15 ++-- .../Inventory/XInventoryInConnector.cs | 72 +++++++++++++++---- .../Inventory/XInventoryConnector.cs | 47 +++++++++--- .../HypergridService/HGInventoryService.cs | 6 ++ 6 files changed, 201 insertions(+), 33 deletions(-) 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/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); From 953fe46811d4c35378526bc58d950c72da64aa70 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 11:48:41 -0700 Subject: [PATCH 12/15] A few minor tweaks here and there in XInventoryService. --- .../InventoryService/XInventoryService.cs | 62 ++++++++++++++----- 1 file changed, 48 insertions(+), 14 deletions(-) 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; From 25b3edc21c4d5deb7563410a4e0a5364153b1002 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 11:51:12 -0700 Subject: [PATCH 13/15] WARNING: LOTS OF COMMENTED AND UNUSED CODE IN THIS COMMIT. This is on purpose; it's an historical record of what works and what doesn't wrt manipulating inventory at the viewer. I'll remove the unused code in a subsequent commit, but wanted to place it in history. The uncommented code works. --- .../EntityTransfer/HGEntityTransferModule.cs | 318 +++++++- .../HGSuitcaseInventoryService.cs | 752 +++++++++++++++++- 2 files changed, 1010 insertions(+), 60 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index ec260b4fec..d85a996c5f 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; } @@ -388,6 +411,36 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #endregion + // COMPLETE FAIL + //private void RemoveRootFolderContents(IClientAPI client) + //{ + // InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); + // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Removing root inventory for user {0}, version {1}", client.AgentId, root.Version); + // InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); + + // List keep = new List(); + // foreach (InventoryFolderBase f in content.Folders) + // { + // if (f.Type == (short)AssetType.TrashFolder || f.Type == (short)AssetType.Landmark || + // f.Type == (short)AssetType.FavoriteFolder || f.Type == (short)AssetType.CurrentOutfitFolder) + // { + // // Don't remove these because the viewer refuses to exist without them + // // and immediately sends a request to create them again, which makes things + // // very confusing in the viewer. + // // Just change their names + // f.Name = "Home " + f.Name + " (Unavailable)"; + // keep.Add(f); + // } + // else + // { + // m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); + // } + // } + + + // client.SendInventoryFolderDetails(client.AgentId, root.ID, new List(), keep, root.Version + 1, true, true); + //} + private void RemoveRootFolderContents(IClientAPI client) { // TODO tell the viewer to remove the root folder's content @@ -401,25 +454,60 @@ 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)"; ; + + // next, add the subfolders and items of the keep folders + //foreach (InventoryFolderBase f in keep) + //{ + // InventoryCollection c = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, f.ID); + // foreach (InventoryFolderBase sf in c.Folders) + // { + // m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); + // fids.Add(sf.ID); + // } + // foreach (InventoryItemBase it in c.Items) + // iids.Add(it.ID); + //} + + //inv.SendRemoveInventoryFolders(fids.ToArray()); + + // Increase the version number + //root.Version += 1; + //m_Scenes[0].InventoryService.UpdateFolder(root); + //foreach (InventoryFolderBase f in keep) + //{ + // f.Version += 1; + // m_Scenes[0].InventoryService.UpdateFolder(f); + //} + + // Send the new names and versions + inv.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray()); + } } } } - private void RestoreRootFolderContents(IClientAPI client) + private void RemoveRootFolderContents2(IClientAPI client) { + // TODO tell the viewer to remove the root folder's content if (client is IClientCore) { IClientCore core = (IClientCore)client; @@ -428,21 +516,207 @@ 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); + if (root != null) + { + 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); + List fids = new List(); + List iids = new List(); + List keep = new List(); - // inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); - //} + foreach (InventoryFolderBase f in content.Folders) + { + if (f.Type == (short)AssetType.TrashFolder || f.Type == (short)AssetType.Landmark || + f.Type == (short)AssetType.FavoriteFolder || f.Type == (short)AssetType.CurrentOutfitFolder) + { + // Don't remove these because the viewer refuses to exist without them + // and immediately sends a request to create them again, which makes things + // very confusing in the viewer. + // Just change their names + f.Name = "Home " + f.Name + " (Unavailable)"; + keep.Add(f); + } + else + { + m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); + fids.Add(f.ID); + } + } + + foreach (InventoryItemBase it in content.Items) + iids.Add(it.ID); + + // next, add the subfolders and items of the keep folders + foreach (InventoryFolderBase f in keep) + { + InventoryCollection c = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, f.ID); + foreach (InventoryFolderBase sf in c.Folders) + { + m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); + fids.Add(sf.ID); + } + foreach (InventoryItemBase it in c.Items) + iids.Add(it.ID); + } + + inv.SendRemoveInventoryFolders(fids.ToArray()); + inv.SendRemoveInventoryItems(iids.ToArray()); + + // Increase the version number + root.Version += 1; + m_Scenes[0].InventoryService.UpdateFolder(root); + //foreach (InventoryFolderBase f in keep) + //{ + // f.Version += 1; + // m_Scenes[0].InventoryService.UpdateFolder(f); + //} + + // Send the new names and versions + inv.SendBulkUpdateInventory(keep.ToArray(), new InventoryItemBase[0]); + + } } } } + private void RemoveSuitcaseFolderContents(IClientAPI client) + { + return; + + //// TODO tell the viewer to remove the suitcase folder's content + //if (client is IClientCore) + //{ + // IClientCore core = (IClientCore)client; + // IClientInventory inv; + + // if (core.TryGet(out inv)) + // { + // InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); + // if (root != null) + // { + // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Removing suitcase inventory for user {0}", client.Name); + // InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); + // List fids = new List(); + // List iids = new List(); + + // if (content.Folders.Count == 0) + // m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: no subfolders???"); + // foreach (InventoryFolderBase f in content.Folders) + // { + // m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); + // fids.Add(f.ID); + // } + + // foreach (InventoryItemBase it in content.Items) + // iids.Add(it.ID); + + // inv.SendRemoveInventoryFolders(fids.ToArray()); + // inv.SendRemoveInventoryItems(iids.ToArray()); + + // // Increase the version number + // root.Version += 1; + // m_Scenes[0].InventoryService.UpdateFolder(root); + // } + // } + //} + } + + private void RestoreRootFolderContents(IClientAPI client) + { + // This works! + //InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); + //client.SendBulkUpdateInventory(root); + + // SORTA KINDA some items are missing... + //InventoryCollection userInventory = m_Scenes[0].InventoryService.GetUserInventory(client.AgentId); + //InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); + //client.SendBulkUpdateInventory(root); + + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root folder"); + if (client is IClientCore) + { + IClientCore core = (IClientCore)client; + IClientInventory inv; + + if (core.TryGet(out inv)) + { + InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); + InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); + + inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); + } + } + + // ATTEMPT # 3 -- STILL DOESN'T WORK! + //if (client is IClientCore) + //{ + // IClientCore core = (IClientCore)client; + // IClientInventory inv; + + // if (core.TryGet(out inv)) + // { + // InventoryCollection userInventory = m_Scenes[0].InventoryService.GetUserInventory(client.AgentId); + // if (userInventory != null) + // { + // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root inventory for user {0}", client.AgentId); + // foreach (InventoryFolderBase f in userInventory.Folders) + // m_log.DebugFormat("[AAA]: FOLDER {0} {1} {2} {3} {4}", f.Name, f.Type, f.Version, f.ID, f.ParentID); + // foreach (InventoryItemBase f in userInventory.Items) + // m_log.DebugFormat("[AAA]: ITEM {0} {1} {2}", f.Name, f.ID, f.Folder); + // inv.SendBulkUpdateInventory(userInventory.Folders.ToArray(), userInventory.Items.ToArray()); + // } + // else + // m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve inventory for user {0}", client.AgentId); + // } + //} + + + // ATTEMPT #2 -- BETTER THAN 1, BUT STILL DOES NOT WORK WELL + //if (client is IClientCore) + //{ + // IClientCore core = (IClientCore)client; + // IClientInventory inv; + + // if (core.TryGet(out inv)) + // { + // List skel = m_Scenes[0].InventoryService.GetInventorySkeleton(client.AgentId); + // if (skel != null) + // { + // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root inventory for user {0}", client.AgentId); + // foreach (InventoryFolderBase f in skel) + // m_log.DebugFormat("[AAA]: {0} {1} {2} {3} {4}", f.Name, f.Type, f.Version, f.ID, f.ParentID); + // inv.SendBulkUpdateInventory(skel.ToArray(), new InventoryItemBase[0]); + // } + // else + // m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve skeleton for user {0}", client.AgentId); + + // ATTEMPT #1 -- DOES NOT WORK + //InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); + //if (root != null) + //{ + //InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); + //InventoryFolderBase[] folders = new InventoryFolderBase[content.Folders.Count + 1]; + //m_log.DebugFormat("[AAA]: Folder name {0}, id {1}, version {2}, parent {3}", root.Name, root.ID, root.Version, root.ParentID); + //folders[0] = root; + //for (int count = 1; count < content.Folders.Count + 1; count++) + //{ + // folders[count] = content.Folders[count - 1]; + // m_log.DebugFormat("[AAA]: Name={0}, Id={1}, Version={2}, type={3}, folderID={4}", + // folders[count].Name, folders[count].ID, folders[count].Version, folders[count].Type, folders[count].ParentID); + //} + //foreach (InventoryItemBase i in content.Items) + // m_log.DebugFormat("[AAA]: Name={0}, folderID={1}", i.Name, i.Folder); + //inv.SendBulkUpdateInventory(/*content.Folders.ToArray()*/ folders, content.Items.ToArray()); + //} + //} + //} + } + + private void RestoreSuitcaseFolderContents(IClientAPI client) + { + + } + private GridRegion MakeRegion(AgentCircuitData aCircuit) { GridRegion region = new GridRegion(); diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs index cb686e26e6..e65ad17ae6 100644 --- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs @@ -48,7 +48,7 @@ namespace OpenSim.Services.HypergridService /// and it responds to GetRootFolder requests with the ID of the /// Suitcase folder, not the actual "My Inventory" folder. /// - public class HGSuitcaseInventoryService : XInventoryService, IInventoryService + public class HGSuitcaseInventoryService1 : XInventoryService, IInventoryService { private static readonly ILog m_log = LogManager.GetLogger( @@ -61,7 +61,7 @@ namespace OpenSim.Services.HypergridService private ExpiringCache> m_SuitcaseTrees = new ExpiringCache>(); - public HGSuitcaseInventoryService(IConfigSource config, string configName) + public HGSuitcaseInventoryService1(IConfigSource config, string configName) : base(config, configName) { m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Starting with config name {0}", configName); @@ -104,11 +104,79 @@ 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) + { + if (x.parentFolderID == suitcase.folderID) + x.parentFolderID = root.folderID; + + 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 + if (f.parentFolderID == suitcase.folderID) + f.parentFolderID = root.folderID; + userInventory.Folders.Add(ConvertToOpenSim(f)); + } + + items = GetFolderItems(userID, suitcase.folderID); + if (items != null && items.Count > 0) + { + foreach (InventoryItemBase i in items) + i.Folder = root.folderID; + 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,23 +199,87 @@ 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"); + suitcase.version = root.version; + m_Database.StoreFolder(suitcase); + // Create System folders + CreateSystemFolders(principalID, suitcase.folderID); + } + else if (suitcase.version < root.version) + { + suitcase.version = root.version; m_Database.StoreFolder(suitcase); } // 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) @@ -199,6 +331,7 @@ 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); @@ -219,14 +352,37 @@ namespace OpenSim.Services.HypergridService 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); + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version); if (!IsWithinSuitcaseTree(folder.ID, root, suitcase)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name); return false; + } + if (folder.ID == root.folderID) + { + if (folder.Version <= suitcase.version) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: version {0} <= suitcase version {1}. Ignoring.", folder.Version, suitcase.version); + return false; + } + if (folder.Version <= root.version) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: version {0} <= root version {1}. Ignoring.", folder.Version, suitcase.version); + return false; + } + suitcase.version = root.version = folder.Version; + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Storing {0} type {1} version {2}", suitcase.folderName, suitcase.type, suitcase.version); + m_Database.StoreFolder(suitcase); + m_Database.StoreFolder(root); + } + + // For all others return base.UpdateFolder(folder); } @@ -301,9 +457,6 @@ namespace OpenSim.Services.HypergridService XInventoryFolder root = GetRootXFolder(items[0].Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(items[0].Owner); - if (!IsWithinSuitcaseTree(items[0].Folder, root, suitcase)) - return false; - foreach (InventoryItemBase it in items) if (it.Folder == root.folderID) { @@ -312,6 +465,9 @@ namespace OpenSim.Services.HypergridService it.Folder = suitcase.folderID; } + if (!IsWithinSuitcaseTree(items[0].Folder, root, suitcase)) + return false; + return base.MoveItems(principalID, items); } @@ -322,44 +478,57 @@ namespace OpenSim.Services.HypergridService return false; } - public override InventoryItemBase GetItem(InventoryItemBase item) + public new InventoryItemBase GetItem(InventoryItemBase item) { InventoryItemBase it = base.GetItem(item); + if (it == null) + { + 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 root = GetRootXFolder(it.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(it.Owner); - - if (it != null) + if (root == null || suitcase == 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]: Root or Suitcase are null for user {0}", + it.Owner); + return null; } + if (it.Folder == suitcase.folderID) + it.Folder = root.folderID; + + if (!IsWithinSuitcaseTree(it.Folder, root, 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 root = GetRootXFolder(f.Owner); + XInventoryFolder suitcase = GetSuitcaseXFolder(f.Owner); if (f.ParentID == suitcase.folderID) f.ParentID = root.folderID; + + if (!IsWithinSuitcaseTree(f.ID, root, suitcase)) + return null; } return f; @@ -409,20 +578,22 @@ namespace OpenSim.Services.HypergridService return null; } - private void SetAsRootFolder(XInventoryFolder suitcase, UUID rootID) + private void SetAsRootFolder(XInventoryFolder suitcase, XInventoryFolder root) { - suitcase.folderID = rootID; + suitcase.version = root.version; + suitcase.folderID = root.folderID; 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,6 +618,13 @@ namespace OpenSim.Services.HypergridService } + /// + /// Return true if the folderID is a subfolder of the Suitcase or the root folder ID itself + /// + /// + /// + /// + /// private bool IsWithinSuitcaseTree(UUID folderID, XInventoryFolder root, XInventoryFolder suitcase) { List tree = new List(); @@ -463,4 +641,502 @@ namespace OpenSim.Services.HypergridService } #endregion } + + public class HGSuitcaseInventoryService : XInventoryService, IInventoryService + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_HomeURL; + private IUserAccountService m_UserAccountService; + + private UserAccountCache m_Cache; + + private ExpiringCache> m_SuitcaseTrees = new ExpiringCache>(); + + public HGSuitcaseInventoryService(IConfigSource config, string configName) + : base(config, configName) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Starting with config name {0}", configName); + if (configName != string.Empty) + m_ConfigName = configName; + + if (m_Database == null) + m_log.WarnFormat("[XXX]: m_Database is null!"); + + // + // Try reading the [InventoryService] section, if it exists + // + IConfig invConfig = config.Configs[m_ConfigName]; + if (invConfig != null) + { + // realm = authConfig.GetString("Realm", realm); + string userAccountsDll = invConfig.GetString("UserAccountsService", string.Empty); + if (userAccountsDll == string.Empty) + throw new Exception("Please specify UserAccountsService in HGInventoryService configuration"); + + Object[] args = new Object[] { config }; + m_UserAccountService = ServerUtils.LoadPlugin(userAccountsDll, args); + if (m_UserAccountService == null) + throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll)); + + // legacy configuration [obsolete] + m_HomeURL = invConfig.GetString("ProfileServerURI", string.Empty); + // Preferred + m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL); + + m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); + } + + m_log.Debug("[HG SUITCASE INVENTORY SERVICE]: Starting..."); + } + + public override bool CreateUserInventory(UUID principalID) + { + // NOGO + return false; + } + + public override List GetInventorySkeleton(UUID principalID) + { + 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) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetRootFolder for {0}", principalID); + if (m_Database == null) + m_log.ErrorFormat("[XXX]: m_Database is NULL!"); + + // Let's find out the local root folder + XInventoryFolder root = GetRootXFolder(principalID); ; + if (root == null) + { + m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve local root folder for user {0}", principalID); + } + + // Warp! Root folder for travelers is the suitcase folder + XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); + + if (suitcase == null) + { + 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); + } + + 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); + 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); + + if (!IsWithinSuitcaseTree(folderID, suitcase)) + return new InventoryCollection(); + + coll = base.GetFolderContent(principalID, folderID); + + if (coll == null) + { + m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Something wrong with user {0}'s suitcase folder", principalID); + coll = new InventoryCollection(); + } + return coll; + } + + public override List GetFolderItems(UUID principalID, UUID folderID) + { + // 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 suitcase = GetSuitcaseXFolder(principalID); + + if (!IsWithinSuitcaseTree(folderID, suitcase)) + return new List(); + + return base.GetFolderItems(principalID, folderID); + } + + 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 suitcase = GetSuitcaseXFolder(folder.Owner); + + if (!IsWithinSuitcaseTree(folder.ParentID, suitcase)) + return false; + + // OK, it's legit + return base.AddFolder(folder); + } + + public override bool UpdateFolder(InventoryFolderBase folder) + { + XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); + + 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 suitcase = GetSuitcaseXFolder(folder.Owner); + + if (!IsWithinSuitcaseTree(folder.ID, suitcase) || !IsWithinSuitcaseTree(folder.ParentID, suitcase)) + return false; + + return base.MoveFolder(folder); + } + + public override bool DeleteFolders(UUID principalID, List folderIDs) + { + // NOGO + return false; + } + + public override bool PurgeFolder(InventoryFolderBase folder) + { + // NOGO + return false; + } + + public override bool AddItem(InventoryItemBase item) + { + // 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 suitcase = GetSuitcaseXFolder(item.Owner); + + if (!IsWithinSuitcaseTree(item.Folder, suitcase)) + return false; + + // OK, it's legit + return base.AddItem(item); + + } + + public override bool UpdateItem(InventoryItemBase item) + { + XInventoryFolder suitcase = GetSuitcaseXFolder(item.Owner); + + if (!IsWithinSuitcaseTree(item.Folder, suitcase)) + return false; + + return base.UpdateItem(item); + } + + public override bool MoveItems(UUID principalID, List items) + { + // Principal is b0rked. *sigh* + + XInventoryFolder suitcase = GetSuitcaseXFolder(items[0].Owner); + + if (!IsWithinSuitcaseTree(items[0].Folder, suitcase)) + return false; + + return base.MoveItems(principalID, items); + + } + + public override bool DeleteItems(UUID principalID, List itemIDs) + { + return false; + } + + public new InventoryItemBase GetItem(InventoryItemBase item) + { + InventoryItemBase it = base.GetItem(item); + if (it == null) + { + 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 new InventoryFolderBase GetFolder(InventoryFolderBase folder) + { + InventoryFolderBase f = base.GetFolder(folder); + + if (f != null) + { + XInventoryFolder suitcase = GetSuitcaseXFolder(f.Owner); + + if (!IsWithinSuitcaseTree(f.ID, suitcase)) + return null; + } + + return f; + } + + //public List GetActiveGestures(UUID principalID) + //{ + //} + + //public int GetAssetPermissions(UUID principalID, UUID assetID) + //{ + //} + + #region Auxiliary functions + private XInventoryFolder GetXFolder(UUID userID, UUID folderID) + { + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "agentID", "folderID" }, + new string[] { userID.ToString(), folderID.ToString() }); + + if (folders.Length == 0) + return null; + + return folders[0]; + } + + private XInventoryFolder GetRootXFolder(UUID principalID) + { + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "agentID", "folderName", "type" }, + new string[] { principalID.ToString(), "My Inventory", ((int)AssetType.RootFolder).ToString() }); + + if (folders != null && folders.Length > 0) + return folders[0]; + return null; + } + + private XInventoryFolder GetSuitcaseXFolder(UUID principalID) + { + // Warp! Root folder for travelers + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "agentID", "type" }, + new string[] { principalID.ToString(), "100" }); // This is a special folder type... + + if (folders != null && folders.Length > 0) + return folders[0]; + return null; + } + + private void SetAsRootFolder(XInventoryFolder suitcase, XInventoryFolder root) + { + suitcase.type = (short)AssetType.Folder; + } + + private List GetFolderTree(UUID folder) + { + List t = null; + if (m_SuitcaseTrees.TryGetValue(folder, out t)) + return t; + + t = GetFolderTreeRecursive(folder); + m_SuitcaseTrees.AddOrUpdate(folder, t, 120); + return t; + } + + private List GetFolderTreeRecursive(UUID root) + { + List tree = new List(); + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "parentFolderID" }, + new string[] { root.ToString() }); + + if (folders == null || (folders != null && folders.Length == 0)) + return tree; // empty tree + else + { + foreach (XInventoryFolder f in folders) + { + tree.Add(f); + tree.AddRange(GetFolderTreeRecursive(f.folderID)); + } + return tree; + } + + } + + /// + /// 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(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) + { + if (fl.folderID == folderID) return true; + else return false; + }); + + if (f == null) return false; + else return true; + } + #endregion + } + } From 7435582b7040d46675adc3795aa0e39f28c6718b Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 11:52:05 -0700 Subject: [PATCH 14/15] If an AddItem fails, try adding it to the right folder type. --- .../Framework/Scenes/Scene.Inventory.cs | 83 ++++++++++++++----- 1 file changed, 63 insertions(+), 20 deletions(-) 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. /// From 6a9f36788df8c07b76d779236b66e48cab6ae316 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 12:28:15 -0700 Subject: [PATCH 15/15] Deleted the unused and commented code from 2 commits ago. --- .../EntityTransfer/HGEntityTransferModule.cs | 242 +------ .../HGSuitcaseInventoryService.cs | 594 ------------------ 2 files changed, 1 insertion(+), 835 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index d85a996c5f..0f422ae1ce 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -411,36 +411,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #endregion - // COMPLETE FAIL - //private void RemoveRootFolderContents(IClientAPI client) - //{ - // InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); - // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Removing root inventory for user {0}, version {1}", client.AgentId, root.Version); - // InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); - - // List keep = new List(); - // foreach (InventoryFolderBase f in content.Folders) - // { - // if (f.Type == (short)AssetType.TrashFolder || f.Type == (short)AssetType.Landmark || - // f.Type == (short)AssetType.FavoriteFolder || f.Type == (short)AssetType.CurrentOutfitFolder) - // { - // // Don't remove these because the viewer refuses to exist without them - // // and immediately sends a request to create them again, which makes things - // // very confusing in the viewer. - // // Just change their names - // f.Name = "Home " + f.Name + " (Unavailable)"; - // keep.Add(f); - // } - // else - // { - // m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); - // } - // } - - - // client.SendInventoryFolderDetails(client.AgentId, root.ID, new List(), keep, root.Version + 1, true, true); - //} - private void RemoveRootFolderContents(IClientAPI client) { // TODO tell the viewer to remove the root folder's content @@ -473,31 +443,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer foreach (InventoryItemBase it in content.Items) it.Name = it.Name + " (Unavailable)"; ; - // next, add the subfolders and items of the keep folders - //foreach (InventoryFolderBase f in keep) - //{ - // InventoryCollection c = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, f.ID); - // foreach (InventoryFolderBase sf in c.Folders) - // { - // m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); - // fids.Add(sf.ID); - // } - // foreach (InventoryItemBase it in c.Items) - // iids.Add(it.ID); - //} - - //inv.SendRemoveInventoryFolders(fids.ToArray()); - - // Increase the version number - //root.Version += 1; - //m_Scenes[0].InventoryService.UpdateFolder(root); - //foreach (InventoryFolderBase f in keep) - //{ - // f.Version += 1; - // m_Scenes[0].InventoryService.UpdateFolder(f); - //} - - // Send the new names and versions + // Send the new names inv.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray()); } @@ -505,133 +451,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } } - private void RemoveRootFolderContents2(IClientAPI client) - { - // TODO tell the viewer to remove the root folder's content - if (client is IClientCore) - { - IClientCore core = (IClientCore)client; - IClientInventory inv; - - if (core.TryGet(out inv)) - { - 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.Name); - InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); - List fids = new List(); - List iids = new List(); - List keep = new List(); - - foreach (InventoryFolderBase f in content.Folders) - { - if (f.Type == (short)AssetType.TrashFolder || f.Type == (short)AssetType.Landmark || - f.Type == (short)AssetType.FavoriteFolder || f.Type == (short)AssetType.CurrentOutfitFolder) - { - // Don't remove these because the viewer refuses to exist without them - // and immediately sends a request to create them again, which makes things - // very confusing in the viewer. - // Just change their names - f.Name = "Home " + f.Name + " (Unavailable)"; - keep.Add(f); - } - else - { - m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); - fids.Add(f.ID); - } - } - - foreach (InventoryItemBase it in content.Items) - iids.Add(it.ID); - - // next, add the subfolders and items of the keep folders - foreach (InventoryFolderBase f in keep) - { - InventoryCollection c = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, f.ID); - foreach (InventoryFolderBase sf in c.Folders) - { - m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); - fids.Add(sf.ID); - } - foreach (InventoryItemBase it in c.Items) - iids.Add(it.ID); - } - - inv.SendRemoveInventoryFolders(fids.ToArray()); - inv.SendRemoveInventoryItems(iids.ToArray()); - - // Increase the version number - root.Version += 1; - m_Scenes[0].InventoryService.UpdateFolder(root); - //foreach (InventoryFolderBase f in keep) - //{ - // f.Version += 1; - // m_Scenes[0].InventoryService.UpdateFolder(f); - //} - - // Send the new names and versions - inv.SendBulkUpdateInventory(keep.ToArray(), new InventoryItemBase[0]); - - } - } - } - } - private void RemoveSuitcaseFolderContents(IClientAPI client) { - return; - - //// TODO tell the viewer to remove the suitcase folder's content - //if (client is IClientCore) - //{ - // IClientCore core = (IClientCore)client; - // IClientInventory inv; - - // if (core.TryGet(out inv)) - // { - // InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); - // if (root != null) - // { - // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Removing suitcase inventory for user {0}", client.Name); - // InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); - // List fids = new List(); - // List iids = new List(); - - // if (content.Folders.Count == 0) - // m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: no subfolders???"); - // foreach (InventoryFolderBase f in content.Folders) - // { - // m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); - // fids.Add(f.ID); - // } - - // foreach (InventoryItemBase it in content.Items) - // iids.Add(it.ID); - - // inv.SendRemoveInventoryFolders(fids.ToArray()); - // inv.SendRemoveInventoryItems(iids.ToArray()); - - // // Increase the version number - // root.Version += 1; - // m_Scenes[0].InventoryService.UpdateFolder(root); - // } - // } - //} } private void RestoreRootFolderContents(IClientAPI client) { - // This works! - //InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); - //client.SendBulkUpdateInventory(root); - - // SORTA KINDA some items are missing... - //InventoryCollection userInventory = m_Scenes[0].InventoryService.GetUserInventory(client.AgentId); - //InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); - //client.SendBulkUpdateInventory(root); - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root folder"); if (client is IClientCore) { @@ -646,75 +471,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); } } - - // ATTEMPT # 3 -- STILL DOESN'T WORK! - //if (client is IClientCore) - //{ - // IClientCore core = (IClientCore)client; - // IClientInventory inv; - - // if (core.TryGet(out inv)) - // { - // InventoryCollection userInventory = m_Scenes[0].InventoryService.GetUserInventory(client.AgentId); - // if (userInventory != null) - // { - // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root inventory for user {0}", client.AgentId); - // foreach (InventoryFolderBase f in userInventory.Folders) - // m_log.DebugFormat("[AAA]: FOLDER {0} {1} {2} {3} {4}", f.Name, f.Type, f.Version, f.ID, f.ParentID); - // foreach (InventoryItemBase f in userInventory.Items) - // m_log.DebugFormat("[AAA]: ITEM {0} {1} {2}", f.Name, f.ID, f.Folder); - // inv.SendBulkUpdateInventory(userInventory.Folders.ToArray(), userInventory.Items.ToArray()); - // } - // else - // m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve inventory for user {0}", client.AgentId); - // } - //} - - - // ATTEMPT #2 -- BETTER THAN 1, BUT STILL DOES NOT WORK WELL - //if (client is IClientCore) - //{ - // IClientCore core = (IClientCore)client; - // IClientInventory inv; - - // if (core.TryGet(out inv)) - // { - // List skel = m_Scenes[0].InventoryService.GetInventorySkeleton(client.AgentId); - // if (skel != null) - // { - // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root inventory for user {0}", client.AgentId); - // foreach (InventoryFolderBase f in skel) - // m_log.DebugFormat("[AAA]: {0} {1} {2} {3} {4}", f.Name, f.Type, f.Version, f.ID, f.ParentID); - // inv.SendBulkUpdateInventory(skel.ToArray(), new InventoryItemBase[0]); - // } - // else - // m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve skeleton for user {0}", client.AgentId); - - // ATTEMPT #1 -- DOES NOT WORK - //InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); - //if (root != null) - //{ - //InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); - //InventoryFolderBase[] folders = new InventoryFolderBase[content.Folders.Count + 1]; - //m_log.DebugFormat("[AAA]: Folder name {0}, id {1}, version {2}, parent {3}", root.Name, root.ID, root.Version, root.ParentID); - //folders[0] = root; - //for (int count = 1; count < content.Folders.Count + 1; count++) - //{ - // folders[count] = content.Folders[count - 1]; - // m_log.DebugFormat("[AAA]: Name={0}, Id={1}, Version={2}, type={3}, folderID={4}", - // folders[count].Name, folders[count].ID, folders[count].Version, folders[count].Type, folders[count].ParentID); - //} - //foreach (InventoryItemBase i in content.Items) - // m_log.DebugFormat("[AAA]: Name={0}, folderID={1}", i.Name, i.Folder); - //inv.SendBulkUpdateInventory(/*content.Folders.ToArray()*/ folders, content.Items.ToArray()); - //} - //} - //} } private void RestoreSuitcaseFolderContents(IClientAPI client) { - } private GridRegion MakeRegion(AgentCircuitData aCircuit) diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs index e65ad17ae6..b6ec558b80 100644 --- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs @@ -48,600 +48,6 @@ namespace OpenSim.Services.HypergridService /// and it responds to GetRootFolder requests with the ID of the /// Suitcase folder, not the actual "My Inventory" folder. /// - public class HGSuitcaseInventoryService1 : XInventoryService, IInventoryService - { - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); - - private string m_HomeURL; - private IUserAccountService m_UserAccountService; - - private UserAccountCache m_Cache; - - private ExpiringCache> m_SuitcaseTrees = new ExpiringCache>(); - - public HGSuitcaseInventoryService1(IConfigSource config, string configName) - : base(config, configName) - { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Starting with config name {0}", configName); - if (configName != string.Empty) - m_ConfigName = configName; - - if (m_Database == null) - m_log.WarnFormat("[XXX]: m_Database is null!"); - - // - // Try reading the [InventoryService] section, if it exists - // - IConfig invConfig = config.Configs[m_ConfigName]; - if (invConfig != null) - { - // realm = authConfig.GetString("Realm", realm); - string userAccountsDll = invConfig.GetString("UserAccountsService", string.Empty); - if (userAccountsDll == string.Empty) - throw new Exception("Please specify UserAccountsService in HGInventoryService configuration"); - - Object[] args = new Object[] { config }; - m_UserAccountService = ServerUtils.LoadPlugin(userAccountsDll, args); - if (m_UserAccountService == null) - throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll)); - - // legacy configuration [obsolete] - m_HomeURL = invConfig.GetString("ProfileServerURI", string.Empty); - // Preferred - m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL); - - m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); - } - - m_log.Debug("[HG SUITCASE INVENTORY SERVICE]: Starting..."); - } - - public override bool CreateUserInventory(UUID principalID) - { - // NOGO - return false; - } - - public override List GetInventorySkeleton(UUID principalID) - { - 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) - { - if (x.parentFolderID == suitcase.folderID) - x.parentFolderID = root.folderID; - - 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 - if (f.parentFolderID == suitcase.folderID) - f.parentFolderID = root.folderID; - userInventory.Folders.Add(ConvertToOpenSim(f)); - } - - items = GetFolderItems(userID, suitcase.folderID); - if (items != null && items.Count > 0) - { - foreach (InventoryItemBase i in items) - i.Folder = root.folderID; - 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) - { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetRootFolder for {0}", principalID); - if (m_Database == null) - m_log.ErrorFormat("[XXX]: m_Database is NULL!"); - - // Let's find out the local root folder - XInventoryFolder root = GetRootXFolder(principalID); ; - if (root == null) - { - m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve local root folder for user {0}", principalID); - } - - // Warp! Root folder for travelers is the suitcase folder - XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); - - if (suitcase == null) - { - 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"); - suitcase.version = root.version; - m_Database.StoreFolder(suitcase); - - // Create System folders - CreateSystemFolders(principalID, suitcase.folderID); - } - else if (suitcase.version < root.version) - { - suitcase.version = root.version; - m_Database.StoreFolder(suitcase); - } - - // Now let's change the folder ID to match that of the real root folder - 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); - 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)) - 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); - } - if (coll == null) - { - m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Something wrong with user {0}'s suitcase folder", principalID); - coll = new InventoryCollection(); - } - return coll; - } - - public override List GetFolderItems(UUID principalID, UUID folderID) - { - // 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)) - return new List(); - - return base.GetFolderItems(principalID, folderID); - } - - 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)) - 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 override bool UpdateFolder(InventoryFolderBase folder) - { - XInventoryFolder root = GetRootXFolder(folder.Owner); - XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); - - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version); - if (!IsWithinSuitcaseTree(folder.ID, root, suitcase)) - { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name); - return false; - } - - if (folder.ID == root.folderID) - { - if (folder.Version <= suitcase.version) - { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: version {0} <= suitcase version {1}. Ignoring.", folder.Version, suitcase.version); - return false; - } - if (folder.Version <= root.version) - { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: version {0} <= root version {1}. Ignoring.", folder.Version, suitcase.version); - return false; - } - suitcase.version = root.version = folder.Version; - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Storing {0} type {1} version {2}", suitcase.folderName, suitcase.type, suitcase.version); - m_Database.StoreFolder(suitcase); - m_Database.StoreFolder(root); - } - - // 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)) - 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); - } - - public override bool DeleteFolders(UUID principalID, List folderIDs) - { - // NOGO - return false; - } - - public override bool PurgeFolder(InventoryFolderBase folder) - { - // NOGO - return false; - } - - public override bool AddItem(InventoryItemBase item) - { - // 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)) - 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)) - return false; - - return base.UpdateItem(item); - } - - public override bool MoveItems(UUID principalID, List items) - { - // Principal is b0rked. *sigh* - - XInventoryFolder root = GetRootXFolder(items[0].Owner); - XInventoryFolder suitcase = GetSuitcaseXFolder(items[0].Owner); - - 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; - } - - if (!IsWithinSuitcaseTree(items[0].Folder, root, suitcase)) - return false; - - return base.MoveItems(principalID, items); - - } - - // Let these pass. Use inherited methods. - public override bool DeleteItems(UUID principalID, List itemIDs) - { - return false; - } - - public new InventoryItemBase GetItem(InventoryItemBase item) - { - InventoryItemBase it = base.GetItem(item); - if (it == null) - { - 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 root = GetRootXFolder(it.Owner); - XInventoryFolder suitcase = GetSuitcaseXFolder(it.Owner); - if (root == null || suitcase == null) - { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Root or Suitcase are null for user {0}", - it.Owner); - return null; - } - - if (it.Folder == suitcase.folderID) - it.Folder = root.folderID; - - if (!IsWithinSuitcaseTree(it.Folder, root, 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 new InventoryFolderBase GetFolder(InventoryFolderBase folder) - { - InventoryFolderBase f = base.GetFolder(folder); - - if (f != null) - { - XInventoryFolder root = GetRootXFolder(f.Owner); - XInventoryFolder suitcase = GetSuitcaseXFolder(f.Owner); - if (f.ParentID == suitcase.folderID) - f.ParentID = root.folderID; - - if (!IsWithinSuitcaseTree(f.ID, root, suitcase)) - return null; - } - - return f; - } - - //public List GetActiveGestures(UUID principalID) - //{ - //} - - //public int GetAssetPermissions(UUID principalID, UUID assetID) - //{ - //} - - #region Auxiliary functions - private XInventoryFolder GetXFolder(UUID userID, UUID folderID) - { - XInventoryFolder[] folders = m_Database.GetFolders( - new string[] { "agentID", "folderID" }, - new string[] { userID.ToString(), folderID.ToString() }); - - if (folders.Length == 0) - return null; - - return folders[0]; - } - - private XInventoryFolder GetRootXFolder(UUID principalID) - { - XInventoryFolder[] folders = m_Database.GetFolders( - new string[] { "agentID", "folderName", "type" }, - new string[] { principalID.ToString(), "My Inventory", ((int)AssetType.RootFolder).ToString() }); - - if (folders != null && folders.Length > 0) - return folders[0]; - return null; - } - - private XInventoryFolder GetSuitcaseXFolder(UUID principalID) - { - // Warp! Root folder for travelers - XInventoryFolder[] folders = m_Database.GetFolders( - new string[] { "agentID", "type" }, - new string[] { principalID.ToString(), "100" }); // This is a special folder type... - - if (folders != null && folders.Length > 0) - return folders[0]; - return null; - } - - private void SetAsRootFolder(XInventoryFolder suitcase, XInventoryFolder root) - { - suitcase.version = root.version; - suitcase.folderID = root.folderID; - suitcase.parentFolderID = UUID.Zero; - suitcase.type = (short)AssetType.Folder; - } - - private List GetFolderTree(UUID folder) - { - List t = null; - if (m_SuitcaseTrees.TryGetValue(folder, out t)) - return t; - - t = GetFolderTreeRecursive(folder); - m_SuitcaseTrees.AddOrUpdate(folder, t, 120); - return t; - } - - private List GetFolderTreeRecursive(UUID root) - { - List tree = new List(); - XInventoryFolder[] folders = m_Database.GetFolders( - new string[] { "parentFolderID" }, - new string[] { root.ToString() }); - - if (folders == null || (folders != null && folders.Length == 0)) - return tree; // empty tree - else - { - foreach (XInventoryFolder f in folders) - { - tree.Add(f); - tree.AddRange(GetFolderTreeRecursive(f.folderID)); - } - return tree; - } - - } - - /// - /// Return true if the folderID is a subfolder of the Suitcase or the root folder ID itself - /// - /// - /// - /// - /// - private bool IsWithinSuitcaseTree(UUID folderID, XInventoryFolder root, 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.AddRange(GetFolderTree(suitcase.folderID)); - XInventoryFolder f = tree.Find(delegate(XInventoryFolder fl) - { - if (fl.folderID == folderID) return true; - else return false; - }); - - if (f == null) return false; - else return true; - } - #endregion - } - public class HGSuitcaseInventoryService : XInventoryService, IInventoryService { private static readonly ILog m_log =