diff --git a/OpenSim/Data/IInventoryData.cs b/OpenSim/Data/IInventoryData.cs index 84a857c1e2..5724d91b97 100644 --- a/OpenSim/Data/IInventoryData.cs +++ b/OpenSim/Data/IInventoryData.cs @@ -114,6 +114,12 @@ namespace OpenSim.Data /// InventoryItemBase queryInventoryItem(UUID item); + /// + /// + /// + /// + InventoryFolderBase queryInventoryFolder(UUID folder); + /// /// Adds a new folder specified by folder /// diff --git a/OpenSim/Data/MSSQL/MSSQLInventoryData.cs b/OpenSim/Data/MSSQL/MSSQLInventoryData.cs index 3d25ed00d8..1349f295db 100644 --- a/OpenSim/Data/MSSQL/MSSQLInventoryData.cs +++ b/OpenSim/Data/MSSQL/MSSQLInventoryData.cs @@ -535,6 +535,11 @@ namespace OpenSim.Data.MSSQL return null; } + public InventoryFolderBase queryInventoryFolder(UUID folderID) + { + return null; + } + /// /// Returns all activated gesture-items in the inventory of the specified avatar. /// diff --git a/OpenSim/Data/MySQL/MySQLInventoryData.cs b/OpenSim/Data/MySQL/MySQLInventoryData.cs index 2f26cdf7ac..a5312b5dbb 100644 --- a/OpenSim/Data/MySQL/MySQLInventoryData.cs +++ b/OpenSim/Data/MySQL/MySQLInventoryData.cs @@ -553,6 +553,11 @@ namespace OpenSim.Data.MySQL return getInventoryItem(itemID); } + public InventoryFolderBase queryInventoryFolder(UUID folderID) + { + return getInventoryFolder(folderID); + } + /// /// Creates a new inventory folder /// diff --git a/OpenSim/Data/NHibernate/NHibernateInventoryData.cs b/OpenSim/Data/NHibernate/NHibernateInventoryData.cs index 74f6eae492..fd32f978fb 100644 --- a/OpenSim/Data/NHibernate/NHibernateInventoryData.cs +++ b/OpenSim/Data/NHibernate/NHibernateInventoryData.cs @@ -182,6 +182,11 @@ namespace OpenSim.Data.NHibernate return null; } + public InventoryFolderBase queryInventoryFolder(UUID folderID) + { + return null; + } + /// /// Returns an inventory folder by its UUID /// diff --git a/OpenSim/Data/SQLite/SQLiteInventoryStore.cs b/OpenSim/Data/SQLite/SQLiteInventoryStore.cs index 34a6364789..bd18c11e7b 100644 --- a/OpenSim/Data/SQLite/SQLiteInventoryStore.cs +++ b/OpenSim/Data/SQLite/SQLiteInventoryStore.cs @@ -631,6 +631,11 @@ namespace OpenSim.Data.SQLite return null; } + public InventoryFolderBase queryInventoryFolder(UUID folderID) + { + return null; + } + /// /// Delete all items in the specified folder /// diff --git a/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs b/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs index e590b9d285..8d36623877 100644 --- a/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs +++ b/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs @@ -37,6 +37,7 @@ namespace OpenSim.Framework.Communications.Cache internal delegate void UpdateItemDelegate(InventoryItemBase itemInfo); internal delegate void DeleteItemDelegate(UUID itemID); internal delegate void QueryItemDelegate(UUID itemID); + internal delegate void QueryFolderDelegate(UUID folderID); internal delegate void CreateFolderDelegate(string folderName, UUID folderID, ushort folderType, UUID parentID); internal delegate void MoveFolderDelegate(UUID folderID, UUID parentID); @@ -819,6 +820,56 @@ namespace OpenSim.Framework.Communications.Cache return false; } + public bool QueryFolder(InventoryFolderBase folder) + { + if (m_hasReceivedInventory) + { + InventoryFolderBase invFolder = RootFolder.FindFolder(folder.ID); + + if (invFolder != null) + { + // Folder is in local cache, just update client + // + return true; + } + + InventoryFolderBase folderInfo = null; + + if (m_commsManager.SecureInventoryService != null) + { + folderInfo = m_commsManager.SecureInventoryService.QueryFolder(folder, m_session_id); + } + else + { + folderInfo = m_commsManager.InventoryService.QueryFolder(folder); + } + + if (folderInfo != null) + { + InventoryFolderImpl createdFolder = RootFolder.CreateChildFolder(folderInfo.ID, folderInfo.Name, (ushort)folderInfo.Type); + + createdFolder.Version = folderInfo.Version; + createdFolder.Owner = folderInfo.Owner; + createdFolder.ParentID = folderInfo.ParentID; + + return true; + } + + return false; + } + else + { + AddRequest( + new InventoryRequest( + Delegate.CreateDelegate(typeof(QueryFolderDelegate), this, "QueryFolder"), + new object[] { folder.ID })); + + return true; + } + + return false; + } + } /// diff --git a/OpenSim/Framework/Communications/IInventoryServices.cs b/OpenSim/Framework/Communications/IInventoryServices.cs index fc9d8afa2f..e37b188282 100644 --- a/OpenSim/Framework/Communications/IInventoryServices.cs +++ b/OpenSim/Framework/Communications/IInventoryServices.cs @@ -112,6 +112,14 @@ namespace OpenSim.Framework.Communications /// true if the item was found in local cache InventoryItemBase QueryItem(InventoryItemBase item); + /// + /// Query the server for a folder that may have been added by + /// another region + /// + /// + /// true if the folder was found in local cache + InventoryFolderBase QueryFolder(InventoryFolderBase folder); + /// /// Does the given user have an inventory structure? /// diff --git a/OpenSim/Framework/Communications/ISecureInventoryService.cs b/OpenSim/Framework/Communications/ISecureInventoryService.cs index d70dd0b618..a405ee5bfa 100644 --- a/OpenSim/Framework/Communications/ISecureInventoryService.cs +++ b/OpenSim/Framework/Communications/ISecureInventoryService.cs @@ -98,6 +98,8 @@ namespace OpenSim.Framework.Communications InventoryItemBase QueryItem(InventoryItemBase item, UUID session_id); + InventoryFolderBase QueryFolder(InventoryFolderBase item, UUID session_id); + /// /// Does the given user have an inventory structure? /// diff --git a/OpenSim/Framework/Communications/InventoryServiceBase.cs b/OpenSim/Framework/Communications/InventoryServiceBase.cs index cad7989497..ff66250929 100644 --- a/OpenSim/Framework/Communications/InventoryServiceBase.cs +++ b/OpenSim/Framework/Communications/InventoryServiceBase.cs @@ -292,6 +292,20 @@ namespace OpenSim.Framework.Communications return null; } + public virtual InventoryFolderBase QueryFolder(InventoryFolderBase item) + { + foreach (IInventoryDataPlugin plugin in m_plugins) + { + InventoryFolderBase result = plugin.queryInventoryFolder(item.ID); + if (result != null) + { + return result; + } + } + + return null; + } + /// /// Purge a folder of all items items and subfolders. /// diff --git a/OpenSim/Grid/InventoryServer/Main.cs b/OpenSim/Grid/InventoryServer/Main.cs index 70bfe60d98..e4cd44687e 100644 --- a/OpenSim/Grid/InventoryServer/Main.cs +++ b/OpenSim/Grid/InventoryServer/Main.cs @@ -131,6 +131,10 @@ namespace OpenSim.Grid.InventoryServer new RestDeserialiseSecureHandler( "POST", "/QueryItem/", m_inventoryService.QueryItem, m_inventoryService.CheckAuthSession)); + m_httpServer.AddStreamHandler( + new RestDeserialiseSecureHandler( + "POST", "/QueryFolder/", m_inventoryService.QueryFolder, m_inventoryService.CheckAuthSession)); + // WARNING: Root folders no longer just delivers the root and immediate child folders (e.g // system folders such as Objects, Textures), but it now returns the entire inventory skeleton. // It would have been better to rename this request, but complexities in the BaseHttpServer diff --git a/OpenSim/Region/Communications/Hypergrid/HGInventoryService.cs b/OpenSim/Region/Communications/Hypergrid/HGInventoryService.cs index 9d70c4615f..a9e008ccb9 100644 --- a/OpenSim/Region/Communications/Hypergrid/HGInventoryService.cs +++ b/OpenSim/Region/Communications/Hypergrid/HGInventoryService.cs @@ -340,6 +340,29 @@ namespace OpenSim.Region.Communications.Hypergrid return null; } + + public InventoryFolderBase QueryFolder(InventoryFolderBase item, UUID session_id) + { + if (IsLocalStandaloneUser(item.Owner)) + { + return base.QueryFolder(item); + } + + try + { + string invServ = GetUserInventoryURI(item.Owner); + + return SynchronousRestSessionObjectPoster.BeginPostObject( + "POST", invServ + "/QueryFolder/", item, session_id.ToString(), item.Owner.ToString()); + } + catch (WebException e) + { + m_log.ErrorFormat("[HGrid INVENTORY SERVICE]: Query inventory item operation failed, {0} {1}", + e.Source, e.Message); + } + + return null; + } #endregion #region Methods common to ISecureInventoryService and IInventoryService diff --git a/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs b/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs index 56566a8b29..26e4a55f6d 100644 --- a/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs +++ b/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs @@ -312,6 +312,22 @@ namespace OpenSim.Region.Communications.OGS1 return null; } + public InventoryFolderBase QueryFolder(InventoryFolderBase item) + { + try + { + return SynchronousRestObjectPoster.BeginPostObject( + "POST", _inventoryServerUrl + "/QueryFolder/", item); + } + catch (WebException e) + { + m_log.ErrorFormat("[OGS1 INVENTORY SERVICE]: Query inventory item operation failed, {0} {1}", + e.Source, e.Message); + } + + return null; + } + public bool HasInventoryForUser(UUID userID) { return false; diff --git a/OpenSim/Region/Communications/OGS1/OGS1SecureInventoryService.cs b/OpenSim/Region/Communications/OGS1/OGS1SecureInventoryService.cs index 0f50b0158b..03fb0d5676 100644 --- a/OpenSim/Region/Communications/OGS1/OGS1SecureInventoryService.cs +++ b/OpenSim/Region/Communications/OGS1/OGS1SecureInventoryService.cs @@ -312,6 +312,22 @@ namespace OpenSim.Region.Communications.OGS1 return null; } + public InventoryFolderBase QueryFolder(InventoryFolderBase item, UUID session_id) + { + try + { + return SynchronousRestSessionObjectPoster.BeginPostObject( + "POST", _inventoryServerUrl + "/QueryFolder/", item, session_id.ToString(), item.Owner.ToString()); + } + catch (WebException e) + { + m_log.ErrorFormat("[OGS1 INVENTORY SERVICE]: Query inventory item operation failed, {0} {1}", + e.Source, e.Message); + } + + return null; + } + public bool HasInventoryForUser(UUID userID) { return false; diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index 465167a00e..19b9b224be 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -426,9 +426,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer if (AssetType.Folder == assetType) { - // Folders not implemented yet + UUID folderID = new UUID(msg.binaryBucket, 1); + InventoryFolderBase folder = new InventoryFolderBase(); + + folder.ID = folderID; + folder.Owner = user.ControllingClient.AgentId; + + // Fetch from database // - return; + if (!userInfo.QueryFolder(folder)) + { + m_log.Debug("[INVENTORY TRANSFER] Can't find folder to give"); + return; + } + + // Get folder info + // + InventoryFolderImpl folderInfo = userInfo.RootFolder.FindFolder(folder.ID); + if (folderInfo == null) + { + m_log.Debug("[INVENTORY TRANSFER] Can't retrieve folder to give"); + return; + } + + user.ControllingClient.SendBulkUpdateInventory(folderInfo); + + // Deliver message + // + user.ControllingClient.SendInstantMessage( + new UUID(msg.fromAgentID), msg.message, + new UUID(msg.toAgentID), + msg.fromAgentName, msg.dialog, msg.timestamp, + folderID, false, msg.binaryBucket); } else { diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 9528114d8e..d129b9367c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -618,6 +618,13 @@ namespace OpenSim.Region.Framework.Scenes return null; } + if (!recipientUserInfo.HasReceivedInventory) + { + recipientUserInfo.FetchInventory(); + if (!WaitForInventory(recipientUserInfo)) + return null; + } + if (recipientParentFolderId == UUID.Zero) recipientParentFolderId = recipientUserInfo.RootFolder.ID; diff --git a/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs index 69b0917ca1..efe0101636 100644 --- a/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs +++ b/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs @@ -120,6 +120,11 @@ namespace OpenSim.Tests.Common.Mock return null; } + public InventoryFolderBase queryInventoryFolder(UUID folderID) + { + return null; + } + public void addInventoryFolder(InventoryFolderBase folder) { m_folders[folder.ID] = folder;