From e3f804e1d816910c1f144cce82a51e9b7622fc3c Mon Sep 17 00:00:00 2001
From: UbitUmarov
Date: Fri, 26 Jan 2018 16:18:45 +0000
Subject: try fix IAR load inventory links and objects owner

---
 .../Archiver/InventoryArchiveReadRequest.cs        | 147 +++++++++++++--------
 .../Inventory/Archiver/InventoryArchiverModule.cs  |   4 +-
 .../Tests/InventoryArchiveLoadPathTests.cs         |   6 +-
 .../CoreModules/Framework/Library/LibraryModule.cs |   4 +-
 4 files changed, 100 insertions(+), 61 deletions(-)

diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index 3838316..1e21b74 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -109,7 +109,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
         /// <summary>
         /// Inventory nodes loaded from the iar.
         /// </summary>
-        protected HashSet<InventoryNodeBase> m_loadedNodes = new HashSet<InventoryNodeBase>();
+        protected Dictionary<UUID, InventoryNodeBase> m_loadedNodes = new Dictionary<UUID, InventoryNodeBase>();
 
         /// <summary>
         /// In order to load identically named folders, we need to keep track of the folders that we have already
@@ -122,6 +122,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
         /// after OSP resolution (since OSP creators are only stored in the item
         /// </summary>
         protected Dictionary<UUID, UUID> m_creatorIdForAssetId = new Dictionary<UUID, UUID>();
+        protected Dictionary<UUID, UUID> m_itemIDs = new Dictionary<UUID, UUID>();
+        protected List<InventoryItemBase> m_invLinks = new List<InventoryItemBase>();
+        protected Dictionary<UUID, InventoryNodeBase> m_invLinksFolders = new Dictionary<UUID, InventoryNodeBase>();
 
         public InventoryArchiveReadRequest(
             IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, string loadPath, bool merge)
@@ -181,7 +184,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
         /// returned
         /// </returns>
         /// <exception cref="System.Exception">Thrown if load fails.</exception>
-        public HashSet<InventoryNodeBase> Execute()
+        public Dictionary<UUID,InventoryNodeBase> Execute()
         {
             try
             {
@@ -223,6 +226,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
                 }
 
                 archive.Close();
+                LoadInventoryLinks();
 
                 m_log.DebugFormat(
                     "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures",
@@ -271,7 +275,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
             string iarPath,
             InventoryFolderBase rootDestFolder,
             Dictionary <string, InventoryFolderBase> resolvedFolders,
-            HashSet<InventoryNodeBase> loadedNodes)
+            Dictionary<UUID, InventoryNodeBase> loadedNodes)
         {
             string iarPathExisting = iarPath;
 
@@ -392,7 +396,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
             string iarPathExisting,
             string iarPathToReplicate,
             Dictionary <string, InventoryFolderBase> resolvedFolders,
-            HashSet<InventoryNodeBase> loadedNodes)
+            Dictionary<UUID, InventoryNodeBase> loadedNodes)
         {
             string[] rawDirsToCreate = iarPathToReplicate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
 
@@ -424,7 +428,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
                 resolvedFolders[iarPathExisting] = destFolder;
 
                 if (0 == i)
-                    loadedNodes.Add(destFolder);
+                    loadedNodes[destFolder.ID] = destFolder;
             }
         }
 
@@ -439,8 +443,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
         {
             InventoryItemBase item = UserInventoryItemSerializer.Deserialize(data);
 
+            UUID oldID = item.ID;
             // Don't use the item ID that's in the file
             item.ID = UUID.Random();
+            m_itemIDs[oldID] = item.ID;
 
             UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_UserAccountService);
             if (UUID.Zero != ospResolvedId) // The user exists in this grid
@@ -457,7 +463,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
             else if (string.IsNullOrEmpty(item.CreatorData))
             {
                 item.CreatorId = m_userInfo.PrincipalID.ToString();
-//                item.CreatorIdAsUuid = new UUID(item.CreatorId);
             }
 
             item.Owner = m_userInfo.PrincipalID;
@@ -470,10 +475,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
             // FIXME: This relies on the items coming before the assets in the TAR file.  Need to create stronger
             // checks for this, and maybe even an external tool for creating OARs which enforces this, rather than
             // relying on native tar tools.
-            m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid;
-
-            if (!m_InventoryService.AddItem(item))
-                m_log.WarnFormat("[INVENTORY ARCHIVER]: Unable to save item {0} in folder {1}", item.Name, item.Folder);
+            if(item.AssetType == (int)AssetType.Link)
+            {
+                m_invLinks.Add(item);
+                if(!m_loadedNodes.ContainsKey(item.Folder) && !m_invLinksFolders.ContainsKey(item.Folder))
+                    m_invLinksFolders[item.Folder] = loadFolder;
+                return null;
+            }
+            else
+            {
+                m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid;
+                if (!m_InventoryService.AddItem(item))
+                    m_log.WarnFormat("[INVENTORY ARCHIVER]: Unable to save item {0} in folder {1}", item.Name, item.Folder);
+            }
 
             return item;
         }
@@ -504,56 +518,57 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
             string rawUuid = filename.Remove(filename.Length - extension.Length);
             UUID assetId = new UUID(rawUuid);
 
-            if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension))
+            if (!ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension))
+            {
+                m_log.ErrorFormat(
+                   "[INVENTORY ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}",
+                    assetPath, extension);
+                return false;
+            }
+
+            sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
+            if (assetType == (sbyte)AssetType.Unknown)
             {
-                sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
+                m_log.WarnFormat("[INVENTORY ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, assetId);
+                return false;
+            }
 
-                if (assetType == (sbyte)AssetType.Unknown)
-                {
-                    m_log.WarnFormat("[INVENTORY ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, assetId);
-                }
-                else if (assetType == (sbyte)AssetType.Object)
-                {
-                    if (m_creatorIdForAssetId.ContainsKey(assetId))
+            if(assetType == (sbyte)AssetType.Object)
+            {
+                UUID owner = m_userInfo.PrincipalID;
+                bool doCreatorID = m_creatorIdForAssetId.ContainsKey(assetId);
+
+                data = SceneObjectSerializer.ModifySerializedObject(assetId, data,
+                    sog =>
                     {
-                        data = SceneObjectSerializer.ModifySerializedObject(assetId, data,
-                            sog => {
-                                bool modified = false;
-
-                                foreach (SceneObjectPart sop in sog.Parts)
-                                {
-                                    if (string.IsNullOrEmpty(sop.CreatorData))
-                                    {
-                                        sop.CreatorID = m_creatorIdForAssetId[assetId];
-                                        modified = true;
-                                    }
-                                }
-
-                                return modified;
-                            });
-
-                        if (data == null)
-                            return false;
-                    }
-                }
+                        foreach(SceneObjectPart sop in sog.Parts)
+                        {
+                            sop.OwnerID = owner;
+                            if(doCreatorID && string.IsNullOrEmpty(sop.CreatorData))
+                                sop.CreatorID = m_creatorIdForAssetId[assetId];
+
+                            foreach(TaskInventoryItem it in sop.Inventory.GetInventoryItems())
+                            {
+                                it.OwnerID = owner;
+                                if(string.IsNullOrEmpty(it.CreatorData) && m_creatorIdForAssetId.ContainsKey(it.AssetID))
+                                    it.CreatorID = m_creatorIdForAssetId[it.AssetID];
+                            }
+                        }
+                        return true;
+                    });
 
-                //m_log.DebugFormat("[INVENTORY ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType);
+                if(data == null)
+                    return false;
+            }
 
-                AssetBase asset = new AssetBase(assetId, "From IAR", assetType, UUID.Zero.ToString());
-                asset.Data = data;
+            //m_log.DebugFormat("[INVENTORY ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType);
 
-                m_AssetService.Store(asset);
+            AssetBase asset = new AssetBase(assetId, "From IAR", assetType, UUID.Zero.ToString());
+            asset.Data = data;
 
-                return true;
-            }
-            else
-            {
-                m_log.ErrorFormat(
-                   "[INVENTORY ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}",
-                    assetPath, extension);
+            m_AssetService.Store(asset);
 
-                return false;
-            }
+            return true;
         }
 
         /// <summary>
@@ -621,14 +636,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 
                     // If we aren't loading the folder containing the item then well need to update the
                     // viewer separately for that item.
-                    if (!m_loadedNodes.Contains(foundFolder))
-                        m_loadedNodes.Add(item);
+                    if (!m_loadedNodes.ContainsKey(foundFolder.ID))
+                        m_loadedNodes[foundFolder.ID] = item;
                 }
             }
 
             m_inventoryNodesLoaded = true;
         }
 
+        private void LoadInventoryLinks()
+        {
+            foreach(InventoryItemBase it in m_invLinks)
+            {
+                UUID target = it.AssetID;
+                if(m_itemIDs.ContainsKey(target))
+                {
+                    it.AssetID = m_itemIDs[target];
+                    if(!m_InventoryService.AddItem(it))
+                        m_log.WarnFormat("[INVENTORY ARCHIVER]: Unable to save item {0} in folder {1}",it.Name,it.Folder);
+                    else
+                    {
+                        m_successfulItemRestores++;
+                        UUID fid = it.Folder;
+                        if (!m_loadedNodes.ContainsKey(fid) && m_invLinksFolders.ContainsKey(fid))
+                            m_loadedNodes[fid] = m_invLinksFolders[fid];
+                    }
+                }
+            }
+
+            m_itemIDs.Clear();
+            m_invLinks.Clear();
+            m_invLinksFolders.Clear();
+        }
         /// <summary>
         /// Load asset file
         /// </summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index 06aec7b..d50ebf5 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -593,7 +593,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
         /// Notify the client of loaded nodes if they are logged in
         /// </summary>
         /// <param name="loadedNodes">Can be empty.  In which case, nothing happens</param>
-        private void UpdateClientWithLoadedNodes(UserAccount userInfo, HashSet<InventoryNodeBase> loadedNodes)
+        private void UpdateClientWithLoadedNodes(UserAccount userInfo, Dictionary<UUID, InventoryNodeBase> loadedNodes)
         {
             if (loadedNodes.Count == 0)
                 return;
@@ -604,7 +604,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 
                 if (user != null && !user.IsChildAgent)
                 {
-                    foreach (InventoryNodeBase node in loadedNodes)
+                    foreach (InventoryNodeBase node in loadedNodes.Values)
                     {
 //                        m_log.DebugFormat(
 //                            "[INVENTORY ARCHIVER]: Notifying {0} of loaded inventory node {1}",
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
index f559c2e..86eca17 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
@@ -212,7 +212,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
             UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene);
 
             Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>();
-            HashSet<InventoryNodeBase> nodesLoaded = new HashSet<InventoryNodeBase>();
+            Dictionary<UUID, InventoryNodeBase> nodesLoaded = new Dictionary<UUID, InventoryNodeBase>();
 
             string folder1Name = "1";
             string folder2aName = "2a";
@@ -293,7 +293,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
             new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false)
                 .ReplicateArchivePathToUserInventory(
                     itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
-                    new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>());
+                    new Dictionary<string, InventoryFolderBase>(), new Dictionary<UUID, InventoryNodeBase>());
 
             List<InventoryFolderBase> folder1PostCandidates
                 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName);
@@ -344,7 +344,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
             new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, folder1ExistingName, (Stream)null, true)
                 .ReplicateArchivePathToUserInventory(
                     itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
-                    new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>());
+                    new Dictionary<string, InventoryFolderBase>(), new Dictionary<UUID, InventoryNodeBase>());
 
             List<InventoryFolderBase> folder1PostCandidates
                 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName);
diff --git a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
index df9d4f9..5d77201 100644
--- a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
@@ -178,7 +178,7 @@ namespace OpenSim.Region.CoreModules.Framework.Library
                 InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene.InventoryService, m_MockScene.AssetService, m_MockScene.UserAccountService, uinfo, simpleName, iarFileName, false);
                 try
                 {
-                    HashSet<InventoryNodeBase> nodes = archread.Execute();
+                    Dictionary<UUID, InventoryNodeBase> nodes = archread.Execute();
                     if (nodes != null && nodes.Count == 0)
                     {
                         // didn't find the subfolder with the given name; place it on the top
@@ -188,7 +188,7 @@ namespace OpenSim.Region.CoreModules.Framework.Library
                         archread.Execute();
                     }
 
-                    foreach (InventoryNodeBase node in nodes)
+                    foreach (InventoryNodeBase node in nodes.Values)
                         FixPerms(node);
                 }
                 catch (Exception e)
-- 
cgit v1.1