// Constructors
 public InventoryFolderImpl(InventoryFolderBase folderbase)
 {
     Owner = folderbase.Owner;
     ID = folderbase.ID;
     Name = folderbase.Name;
     ParentID = folderbase.ParentID;
     Type = folderbase.Type;
     Version = folderbase.Version;
 }
        public virtual bool AddFolder(InventoryFolderBase folder)
        {
            object remoteValue = DoRemoteByURL("InventoryServerURI", folder);
            if (remoteValue != null || m_doRemoteOnly)
                return remoteValue == null ? false : (bool) remoteValue;

            InventoryFolderBase check = GetFolder(folder);
            if (check != null)
                return false;

            return m_Database.StoreFolder(folder);
        }
 public override void FromOSD(OSDMap map)
 {
     OSDArray items = (OSDArray) map["Items"];
     Items = items.ConvertAll<InventoryItemBase>((osd) =>
                                                     {
                                                         InventoryItemBase item = new InventoryItemBase();
                                                         item.FromOSD((OSDMap) osd);
                                                         return item;
                                                     }
         );
     OSDArray folders = (OSDArray) map["Folders"];
     Folders = folders.ConvertAll<InventoryFolderBase>((osd) =>
                                                           {
                                                               InventoryFolderBase folder =
                                                                   new InventoryFolderBase();
                                                               folder.FromOSD((OSDMap) osd);
                                                               return folder;
                                                           }
         );
     UserID = map["UserID"];
     FolderID = map["FolderID"];
 }
        public virtual InventoryFolderBase GetFolder(InventoryFolderBase folder)
        {
            object remoteValue = DoRemoteByURL("InventoryServerURI", folder);
            if (remoteValue != null || m_doRemoteOnly)
                return (InventoryFolderBase) remoteValue;

            List<InventoryFolderBase> folders = m_Database.GetFolders(
                new[] {"folderID"},
                new[] {folder.ID.ToString()});

            if (folders.Count == 0)
                return null;

            return folders[0];
        }
        /// <summary>
        ///     Delete a scene object from a scene and place in the given avatar's inventory.
        ///     Returns the UUID of the newly created asset.
        /// </summary>
        /// <param name="action"></param>
        /// <param name="folderID"></param>
        /// <param name="objectGroups"></param>
        /// <param name="agentId"></param>
        /// <param name="itemID"></param>
        public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID,
                                              List<ISceneEntity> objectGroups, UUID agentId, out UUID itemID)
        {
            itemID = UUID.Zero;
            if (objectGroups.Count == 0)
                return UUID.Zero;

            // Get the user info of the item destination
            //
            IScenePresence SP = m_scene.GetScenePresence(agentId);
            UUID userID = UUID.Zero;

            if (action == DeRezAction.Take || action == DeRezAction.AcquireToUserInventory ||
                action == DeRezAction.SaveToExistingUserInventoryItem)
            {
                // Take or take copy require a taker
                // Saving changes requires a local user
                //
                if (SP == null || SP.ControllingClient == null)
                    return UUID.Zero;

                userID = agentId;
            }
            else
            {
                // All returns / deletes go to the object owner
                //

                userID = objectGroups[0].OwnerID;
            }

            if (userID == UUID.Zero) // Can't proceed
            {
                return UUID.Zero;
            }

            // If we're returning someone's item, it goes back to the
            // owner's Lost And Found folder.
            // Delete is treated like return in this case
            // Deleting your own items makes them go to trash
            //

            InventoryFolderBase folder = null;
            InventoryItemBase item = null;

            if (DeRezAction.SaveToExistingUserInventoryItem == action)
            {
                item = m_scene.InventoryService.GetItem(userID, objectGroups[0].RootChild.FromUserInventoryItemID);

                //item = userInfo.RootFolder.FindItem(
                //        objectGroup.RootPart.FromUserInventoryItemID);

                if (null == item)
                {
                    MainConsole.Instance.DebugFormat(
                        "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.",
                        objectGroups[0].Name, objectGroups[0].UUID);
                    return UUID.Zero;
                }
            }
            else
            {
                // Folder magic
                //
                if (action == DeRezAction.Delete)
                {
                    // Deleting someone else's item
                    //

                    if (SP == null || SP.ControllingClient == null ||
                        objectGroups[0].OwnerID != agentId)
                    {
                        folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown,
                                                                           AssetType.LostAndFoundFolder);
                    }
                    else
                    {
                        folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown,
                                                                           AssetType.TrashFolder);
                    }
                }
                else if (action == DeRezAction.Return)
                {
                    // Dump to lost + found unconditionally
                    //
                    folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown,
                                                                       AssetType.LostAndFoundFolder);
                }

                if (folderID == UUID.Zero && folder == null)
                {
                    if (action == DeRezAction.Delete)
                    {
                        // Deletes go to trash by default
                        //
                        folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown,
                                                                           AssetType.TrashFolder);
                    }
                    else
                    {
                        if (SP == null || SP.ControllingClient == null ||
                            objectGroups[0].OwnerID != agentId)
                        {
                            folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown,
                                                                               AssetType.LostAndFoundFolder);
                        }
                        else
                        {
                            folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown,
                                                                               AssetType.TrashFolder);
                        }
                    }
                }

                // Override and put into where it came from, if it came
                // from anywhere in inventory
                //
                if (action == DeRezAction.Attachment || action == DeRezAction.Take ||
                    action == DeRezAction.AcquireToUserInventory)
                {
                    if (objectGroups[0].RootChild.FromUserInventoryItemID != UUID.Zero)
                    {
                        InventoryFolderBase f =
                            new InventoryFolderBase(objectGroups[0].RootChild.FromUserInventoryItemID, userID);
                        folder = m_scene.InventoryService.GetFolder(f);
                    }
                    else
                    {
                        folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Object,
                                                                           AssetType.Object);
                    }
                }

                if (folder == null) // None of the above
                {
                    folder = new InventoryFolderBase(folderID);
                }

                item = new InventoryItemBase
                           {
                               CreatorId = objectGroups[0].RootChild.CreatorID.ToString(),
                               ID = UUID.Random(),
                               InvType = (int) InventoryType.Object,
                               Folder = folder.ID,
                               Owner = userID
                           };
            }

            AssetBase asset;
            UUID assetID = SaveAsAsset(objectGroups, out asset);
            item.AssetID = assetID;
            if (DeRezAction.SaveToExistingUserInventoryItem != action)
            {
                item.Description = asset.Description;
                item.Name = asset.Name;
                item.AssetType = asset.Type;
            }

            if (DeRezAction.SaveToExistingUserInventoryItem == action)
            {
                m_scene.InventoryService.UpdateItem(item);
            }
            else
            {
                if (SP != null && SP.ControllingClient != null &&
                    (SP.ControllingClient.AgentId != objectGroups[0].OwnerID) &&
                    m_scene.Permissions.PropagatePermissions())
                {
                    foreach (ISceneEntity group in objectGroups)
                    {
                        uint perms = group.GetEffectivePermissions();
                        uint nextPerms = (perms & 7) << 13;
                        if ((nextPerms & (uint) PermissionMask.Copy) == 0)
                            perms &= ~(uint) PermissionMask.Copy;
                        if ((nextPerms & (uint) PermissionMask.Transfer) == 0)
                            perms &= ~(uint) PermissionMask.Transfer;
                        if ((nextPerms & (uint) PermissionMask.Modify) == 0)
                            perms &= ~(uint) PermissionMask.Modify;

                        // Make sure all bits but the ones we want are clear
                        // on take.
                        // This will be applied to the current perms, so
                        // it will do what we want.
                        group.RootChild.NextOwnerMask &=
                            ((uint) PermissionMask.Copy |
                             (uint) PermissionMask.Transfer |
                             (uint) PermissionMask.Modify);
                        group.RootChild.NextOwnerMask |=
                            (uint) PermissionMask.Move;

                        item.BasePermissions = perms & group.RootChild.NextOwnerMask;
                        item.CurrentPermissions = item.BasePermissions;
                        item.NextPermissions = group.RootChild.NextOwnerMask;
                        item.EveryOnePermissions = group.RootChild.EveryoneMask & group.RootChild.NextOwnerMask;
                        item.GroupPermissions = group.RootChild.GroupMask & group.RootChild.NextOwnerMask;

                        // Magic number badness. Maybe this deserves an enum.
                        // bit 4 (16) is the "Slam" bit, it means treat as passed
                        // and apply next owner perms on rez
                        item.CurrentPermissions |= 16; // Slam!

                        item.SalePrice = group.RootChild.SalePrice;
                        item.SaleType = group.RootChild.ObjectSaleType;
                    }
                }
                else
                {
                    foreach (ISceneEntity group in objectGroups)
                    {
                        item.BasePermissions = group.GetEffectivePermissions();
                        item.CurrentPermissions = group.GetEffectivePermissions();
                        item.NextPermissions = group.RootChild.NextOwnerMask;
                        item.EveryOnePermissions = group.RootChild.EveryoneMask;
                        item.GroupPermissions = group.RootChild.GroupMask;

                        item.SalePrice = group.RootChild.SalePrice;
                        item.SaleType = group.RootChild.ObjectSaleType;

                        item.CurrentPermissions &=
                            ((uint) PermissionMask.Copy |
                             (uint) PermissionMask.Transfer |
                             (uint) PermissionMask.Modify |
                             (uint) PermissionMask.Move |
                             7); // Preserve folded permissions
                    }
                }

                if (objectGroups.Count != 1)
                    item.Flags |= (uint) InventoryItemFlags.ObjectHasMultipleItems;
                item.CreationDate = Util.UnixTimeSinceEpoch();

                m_LLCLientInventoryModule.AddInventoryItem(item);

                if (SP != null && SP.ControllingClient != null && item.Owner == SP.ControllingClient.AgentId)
                {
                    SP.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
                }
                else
                {
                    IScenePresence notifyUser = m_scene.GetScenePresence(item.Owner);
                    if (notifyUser != null)
                    {
                        notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
                    }
                }
            }
            itemID = item.ID;
            return assetID;
        }
        /// <summary>
        ///     Move the given items from the object task inventory to the agent's inventory
        /// </summary>
        /// <param name="destID"></param>
        /// <param name="name"></param>
        /// <param name="host"></param>
        /// <param name="items"></param>
        /// <returns></returns>
        public UUID MoveTaskInventoryItemsToUserInventory(UUID destID, string name, ISceneChildEntity host,
                                                          List<UUID> items)
        {
            UUID newFolderID = UUID.Random();

            Util.FireAndForget((o) =>
                                   {
                                       InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(destID);

                                       InventoryFolderBase newFolder = new InventoryFolderBase(newFolderID, name, destID,
                                                                                               -1, rootFolder.ID,
                                                                                               rootFolder.Version);
                                       m_scene.InventoryService.AddFolder(newFolder);

                                       foreach (UUID itemID in items)
                                       {
                                           InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(destID, host,
                                                                                                          itemID);

                                           if (agentItem != null)
                                           {
                                               agentItem.Folder = newFolderID;

                                               m_scene.InventoryService.AddItem(agentItem);
                                           }
                                       }

                                       IScenePresence avatar;
                                       if (m_scene.TryGetScenePresence(destID, out avatar))
                                       {
                                           SendInventoryUpdate(avatar.ControllingClient, rootFolder, true, false);
                                           SendInventoryUpdate(avatar.ControllingClient, newFolder, false, true);
                                       }
                                   });

            return newFolderID;
        }
        /// <summary>
        ///     Resolve a destination folder
        /// </summary>
        /// We require here a root destination folder (usually the root of the user's inventory) and the archive
        /// path.  We also pass in a list of previously resolved folders in case we've found this one previously.
        /// <param name="archivePath">
        ///     The item archive path to resolve.  The portion of the path passed back is that
        ///     which corresponds to the resolved desintation folder.
        /// </param>
        /// <param name="rootDestFolder">
        ///     The root folder for the inventory load
        /// </param>
        /// <param name="resolvedFolders">
        ///     The folders that we have resolved so far for a given archive path.
        /// </param>
        /// <returns>
        ///     The folder in the user's inventory that matches best the archive path given.  If no such folder was found
        ///     then the passed in root destination folder is returned.
        /// </returns>
        protected InventoryFolderBase ResolveDestinationFolder(
            InventoryFolderBase rootDestFolder,
            ref string archivePath,
            ref Dictionary<string, InventoryFolderBase> resolvedFolders)
        {
            //            string originalArchivePath = archivePath;

            while (archivePath.Length > 0)
            {
                //                MainConsole.Instance.DebugFormat("[INVENTORY ARCHIVER]: Trying to resolve destination folder {0}", archivePath);

                if (resolvedFolders.ContainsKey(archivePath))
                {
                    //                    MainConsole.Instance.DebugFormat(
                    //                        "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath);
                    return resolvedFolders[archivePath];
                }
                if (m_merge)
                {
                    // TODO: Using m_invPath is totally wrong - what we need to do is strip the uuid from the
                    // iar name and try to find that instead.
                    string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath);
                    List<InventoryFolderBase> folderCandidates
                        = InventoryArchiveUtils.FindFolderByPath(
                            m_registry.RequestModuleInterface<IInventoryService>(), m_userInfo.PrincipalID,
                            plainPath);

                    if (folderCandidates.Count != 0)
                    {
                        InventoryFolderBase destFolder = folderCandidates[0];
                        resolvedFolders[archivePath] = destFolder;
                        return destFolder;
                    }
                }

                // Don't include the last slash so find the penultimate one
                int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2);

                if (penultimateSlashIndex >= 0)
                {
                    // Remove the last section of path so that we can see if we've already resolved the parent
                    archivePath = archivePath.Remove(penultimateSlashIndex + 1);
                }
                else
                {
                    //                        MainConsole.Instance.DebugFormat(
                    //                            "[INVENTORY ARCHIVER]: Found no previously created folder for archive path {0}",
                    //                            originalArchivePath);
                    archivePath = string.Empty;
                    return rootDestFolder;
                }
            }

            return rootDestFolder;
        }
 /// <summary>
 ///     Handle an inventory folder creation request from the client.
 /// </summary>
 /// <param name="remoteClient"></param>
 /// <param name="folderID"></param>
 /// <param name="folderType"></param>
 /// <param name="folderName"></param>
 /// <param name="parentID"></param>
 protected void HandleCreateInventoryFolder(IClientAPI remoteClient, UUID folderID, ushort folderType,
                                            string folderName, UUID parentID)
 {
     InventoryFolderBase folder = new InventoryFolderBase(folderID, folderName, remoteClient.AgentId,
                                                          (short) folderType, parentID, 1);
     if (!m_scene.InventoryService.AddFolder(folder))
     {
         MainConsole.Instance.WarnFormat(
             "[AGENT INVENTORY]: Failed to create folder for user {0} {1}",
             remoteClient.Name, remoteClient.AgentId);
     }
 }
        /// <summary>
        ///     Handle a client request to update the inventory folder
        /// </summary>
        /// FIXME: We call add new inventory folder because in the data layer, we happen to use an SQL REPLACE
        /// so this will work to rename an existing folder.  Needless to say, to rely on this is very confusing,
        /// and needs to be changed.
        /// <param name="remoteClient"></param>
        /// <param name="folderID"></param>
        /// <param name="type"></param>
        /// <param name="name"></param>
        /// <param name="parentID"></param>
        protected void HandleUpdateInventoryFolder(IClientAPI remoteClient, UUID folderID, ushort type, string name,
                                                   UUID parentID)
        {
            //            MainConsole.Instance.DebugFormat(
            //                "[AGENT INVENTORY]: Updating inventory folder {0} {1} for {2} {3}", folderID, name, remoteClient.Name, remoteClient.AgentId);

            InventoryFolderBase folder = new InventoryFolderBase(folderID, remoteClient.AgentId);
            folder = m_scene.InventoryService.GetFolder(folder);
            if (folder != null)
            {
                folder.Name = name;
                folder.Type = (short) type;
                folder.ParentID = parentID;
                if (!m_scene.InventoryService.UpdateFolder(folder))
                {
                    MainConsole.Instance.ErrorFormat(
                        "[AGENT INVENTORY]: Failed to update folder for user {0} {1}",
                        remoteClient.Name, remoteClient.AgentId);
                }
            }
        }
        public virtual bool UpdateFolder(InventoryFolderBase folder)
        {
            object remoteValue = DoRemoteByURL("InventoryServerURI", folder);
            if (remoteValue != null || m_doRemoteOnly)
                return remoteValue == null ? false : (bool) remoteValue;

            if (!m_AllowDelete) //Initial item MUST be created as a link folder
                if (folder.Type == (sbyte) AssetType.LinkFolder)
                    return false;

            InventoryFolderBase check = GetFolder(folder);
            if (check == null)
                return AddFolder(folder);

            if (check.Type != -1 || folder.Type != -1)
            {
                if (folder.Version > check.Version)
                    return false;
                check.Version = folder.Version;
                check.Type = folder.Type;
                check.Version++;
                return m_Database.StoreFolder(check);
            }

            if (folder.Version < check.Version)
                folder.Version = check.Version;
            folder.ID = check.ID;

            folder.Version++;
            return m_Database.StoreFolder(folder);
        }
        /// <summary>
        ///     Find an item given a PATH_DELIMITOR delimited path starting from this folder.
        ///     This method does not handle paths that contain multiple delimitors
        ///     FIXME: We do not yet handle situations where folders or items have the same name.  We could handle this by some
        ///     XPath like expression
        ///     FIXME: Delimitors which occur in names themselves are not currently escapable.
        /// </summary>
        /// <param name="inventoryService">
        ///     Inventory service to query
        /// </param>
        /// <param name="startFolder">
        ///     The folder from which the path starts
        /// </param>
        /// <param name="path">
        ///     The path to the required item.
        /// </param>
        /// <returns>null if the item is not found</returns>
        public static InventoryItemBase FindItemByPath(
            IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
        {
            // If the path isn't just / then trim any starting extraneous slashes
            path = path.TrimStart(new[] {PATH_DELIMITER});

            string[] components = SplitEscapedPath(path);
            components[0] = UnescapePath(components[0]);

            //string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None);

            if (components.Length == 1)
            {
            //                MainConsole.Instance.DebugFormat(
            //                    "FOUND SINGLE COMPONENT [{0}].  Looking for this in [{1}] {2}",
            //                    components[0], startFolder.Name, startFolder.ID);

                List<InventoryItemBase> items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID);

            //                MainConsole.Instance.DebugFormat("[INVENTORY ARCHIVE UTILS]: Found {0} items in FindItemByPath()", items.Count);

                return items.FirstOrDefault(item => item.Name == components[0]);
            }
            else
            {
            //                MainConsole.Instance.DebugFormat("FOUND COMPONENTS [{0}] and [{1}]", components[0], components[1]);

                InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID);

                return (from folder in contents.Folders
                        where folder.Name == components[0]
                        select FindItemByPath(inventoryService, folder, components[1])).FirstOrDefault();
            }
        }
        public virtual bool MoveFolder(InventoryFolderBase folder)
        {
            object remoteValue = DoRemoteByURL("InventoryServerURI", folder);
            if (remoteValue != null || m_doRemoteOnly)
                return remoteValue == null ? false : (bool) remoteValue;

            List<InventoryFolderBase> x = m_Database.GetFolders(
                new[] {"folderID"},
                new[] {folder.ID.ToString()});

            if (x.Count == 0)
                return false;

            x[0].ParentID = folder.ParentID;

            return m_Database.StoreFolder(x[0]);
        }
        public virtual bool PurgeFolder(InventoryFolderBase folder)
        {
            object remoteValue = DoRemoteByURL("InventoryServerURI", folder);
            if (remoteValue != null || m_doRemoteOnly)
                return remoteValue == null ? false : (bool) remoteValue;

            if (!m_AllowDelete && !ParentIsLinkFolder(folder.ID))
                return false;

            if (!ParentIsTrash(folder.ID))
                return false;

            List<InventoryFolderBase> subFolders = m_Database.GetFolders(
                new[] {"parentFolderID"},
                new[] {folder.ID.ToString()});

            foreach (InventoryFolderBase x in subFolders)
            {
                PurgeFolder(x);
                m_Database.DeleteFolders("folderID", x.ID.ToString(), true);
            }

            m_Database.DeleteItems("parentFolderID", folder.ID.ToString());

            return true;
        }
        /// <summary>
        ///     Give an entire inventory folder from one user to another.  The entire contents (including all descendent
        ///     folders) is given.
        /// </summary>
        /// <param name="recipientId"></param>
        /// <param name="senderId">ID of the sender of the item</param>
        /// <param name="folderId"></param>
        /// <param name="recipientParentFolderId">
        ///     The id of the receipient folder in which the send folder should be placed.  If UUID.Zero then the
        ///     recipient folder is the root folder
        /// </param>
        /// <param name="success"></param>
        /// <returns>
        ///     The inventory folder copy given, null if the copy was unsuccessful
        /// </returns>
        public void GiveInventoryFolderAsync(
            UUID recipientId, UUID senderId, UUID folderId, UUID recipientParentFolderId, GiveFolderParam success)
        {
            Util.FireAndForget(o =>
                                   {
                                       // Retrieve the folder from the sender
                                       InventoryFolderBase folder = GetFolder(new InventoryFolderBase(folderId));
                                       if (null == folder)
                                       {
                                           MainConsole.Instance.ErrorFormat(
                                               "[InventoryService]: Could not find inventory folder {0} to give",
                                               folderId);
                                           success(null);
                                           return;
                                       }

                                       //Find the folder for the receiver
                                       if (recipientParentFolderId == UUID.Zero)
                                       {
                                           InventoryFolderBase recipientRootFolder = GetRootFolder(recipientId);
                                           if (recipientRootFolder != null)
                                               recipientParentFolderId = recipientRootFolder.ID;
                                           else
                                           {
                                               MainConsole.Instance.WarnFormat(
                                                   "[InventoryService]: Unable to find root folder for receiving agent");
                                               success(null);
                                               return;
                                           }
                                       }

                                       UUID newFolderId = UUID.Random();
                                       InventoryFolderBase newFolder
                                           = new InventoryFolderBase(
                                               newFolderId, folder.Name, recipientId, folder.Type,
                                               recipientParentFolderId, folder.Version);
                                       AddFolder(newFolder);

                                       // Give all the subfolders
                                       InventoryCollection contents = GetFolderContent(senderId, folderId);
                                       foreach (InventoryFolderBase childFolder in contents.Folders)
                                       {
                                           GiveInventoryFolderAsync(recipientId, senderId, childFolder.ID, newFolder.ID,
                                                                    null);
                                       }

                                       // Give all the items
                                       foreach (InventoryItemBase item in contents.Items)
                                       {
                                           InnerGiveInventoryItem(recipientId, senderId, item, newFolder.ID, true, true);
                                       }
                                       success(newFolder);
                                   });
        }
        public AvatarAppearance WearFolder(AvatarAppearance avappearance, UUID user, UUID folderOwnerID)
        {
            InventoryFolderBase Folder2Wear = m_InventoryService.GetFolderByOwnerAndName(folderOwnerID,
                                                                                         m_forceUserToWearFolderName);
            if (Folder2Wear != null)
            {
                List<InventoryItemBase> itemsInFolder = m_InventoryService.GetFolderItems(UUID.Zero, Folder2Wear.ID);

                InventoryFolderBase appearanceFolder = m_InventoryService.GetFolderForType(user, InventoryType.Wearable,
                                                                                           AssetType.Clothing);

                InventoryFolderBase folderForAppearance = new InventoryFolderBase(UUID.Random(), "GridWear", user, -1,
                                                                                  appearanceFolder.ID, 1);
                List<InventoryFolderBase> userFolders = m_InventoryService.GetFolderFolders(user, appearanceFolder.ID);
                bool alreadyThere = false;
                List<UUID> items2RemoveFromAppearence = new List<UUID>();
                List<UUID> toDelete = new List<UUID>();
                foreach (InventoryFolderBase folder in userFolders)
                {
                    if (folder.Name == folderForAppearance.Name)
                    {
                        List<InventoryItemBase> itemsInCurrentFolder = m_InventoryService.GetFolderItems(UUID.Zero,
                                                                                                         folder.ID);
                        foreach (InventoryItemBase itemBase in itemsInCurrentFolder)
                        {
                            items2RemoveFromAppearence.Add(itemBase.AssetID);
                            items2RemoveFromAppearence.Add(itemBase.ID);
                            toDelete.Add(itemBase.ID);
                        }
                        folderForAppearance = folder;
                        alreadyThere = true;
                        m_InventoryService.DeleteItems(user, toDelete);
                        break;
                    }
                }

                if (!alreadyThere)
                    m_InventoryService.AddFolder(folderForAppearance);
                else
                {
                    // we have to remove all the old items if they are currently wearing them
                    for (int i = 0; i < avappearance.Wearables.Length; i++)
                    {
                        AvatarWearable wearable = avappearance.Wearables[i];
                        for (int ii = 0; ii < wearable.Count; ii++)
                        {
                            if (items2RemoveFromAppearence.Contains(wearable[ii].ItemID))
                            {
                                avappearance.Wearables[i] = AvatarWearable.DefaultWearables[i];
                                break;
                            }
                        }
                    }

                    List<AvatarAttachment> attachments = avappearance.GetAttachments();
                    foreach (AvatarAttachment attachment in attachments)
                    {
                        if ((items2RemoveFromAppearence.Contains(attachment.AssetID)) ||
                            (items2RemoveFromAppearence.Contains(attachment.ItemID)))
                        {
                            avappearance.DetachAttachment(attachment.ItemID);
                        }
                    }
                }

                // ok, now we have a empty folder, lets add the items
                foreach (InventoryItemBase itemBase in itemsInFolder)
                {
                    InventoryItemBase newcopy = m_InventoryService.InnerGiveInventoryItem(user, folderOwnerID, itemBase,
                                                                                          folderForAppearance.ID,
                                                                                          true, true);

                    if (newcopy.InvType == (int) InventoryType.Object)
                    {
                        byte[] attobj = m_AssetService.GetData(newcopy.AssetID.ToString());

                        if (attobj != null)
                        {
                            string xmlData = Utils.BytesToString(attobj);
                            XmlDocument doc = new XmlDocument();
                            try
                            {
                                doc.LoadXml(xmlData);
                            }
                            catch
                            {
                                continue;
                            }

                            if (doc.FirstChild.OuterXml.StartsWith("<groups>") ||
                                (doc.FirstChild.NextSibling != null &&
                                 doc.FirstChild.NextSibling.OuterXml.StartsWith("<groups>")))
                                continue;

                            string xml = "";
                            if ((doc.FirstChild.NodeType == XmlNodeType.XmlDeclaration) &&
                                (doc.FirstChild.NextSibling != null))
                                xml = doc.FirstChild.NextSibling.OuterXml;
                            else
                                xml = doc.FirstChild.OuterXml;
                            doc.LoadXml(xml);

                            if (doc.DocumentElement == null) continue;

                            XmlNodeList xmlNodeList = doc.DocumentElement.SelectNodes("//State");
                            int attchspot;
                            if ((xmlNodeList != null) && (int.TryParse(xmlNodeList[0].InnerText, out attchspot)))
                            {
                                AvatarAttachment a = new AvatarAttachment(attchspot, newcopy.ID, newcopy.AssetID);
                                Dictionary<int, List<AvatarAttachment>> ac = avappearance.Attachments;

                                if (!ac.ContainsKey(attchspot))
                                    ac[attchspot] = new List<AvatarAttachment>();

                                ac[attchspot].Add(a);
                                avappearance.Attachments = ac;
                            }
                        }
                    }
                    m_InventoryService.AddItem(newcopy);
                }
            }
            return avappearance;
        }
        private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
        {
            //MainConsole.Instance.InfoFormat("[INVENTORY TRANSFER]: OnInstantMessage {0}", im.dialog);

            if (im.Dialog == (byte) InstantMessageDialog.InventoryOffered)
            {
                //MainConsole.Instance.DebugFormat("Asset type {0}", ((AssetType)im.binaryBucket[0]));

                if (im.BinaryBucket.Length < 17) // Invalid
                    return;

                UUID receipientID = im.ToAgentID;
                IScenePresence user = m_Scene.GetScenePresence(receipientID);
                UUID copyID;

                // Send the IM to the recipient. The item is already
                // in their inventory, so it will not be lost if
                // they are offline.
                //
                if (user != null)
                {
                    // First byte is the asset type
                    AssetType assetType = (AssetType) im.BinaryBucket[0];

                    if (AssetType.Folder == assetType)
                    {
                        UUID folderID = new UUID(im.BinaryBucket, 1);

                        MainConsole.Instance.DebugFormat("[INVENTORY TRANSFER]: Inserting original folder {0} " +
                                                         "into agent {1}'s inventory",
                                                         folderID, im.ToAgentID);

                        m_Scene.InventoryService.GiveInventoryFolderAsync(receipientID, client.AgentId,
                                                                          folderID, UUID.Zero, (folder) =>
                                                                                                   {
                                                                                                       if (folder ==
                                                                                                           null)
                                                                                                       {
                                                                                                           client
                                                                                                               .SendAgentAlertMessage
                                                                                                               ("Can't find folder to give. Nothing given.",
                                                                                                                false);
                                                                                                           return;
                                                                                                       }

                                                                                                       // The outgoing binary bucket should contain only the byte which signals an asset folder is
                                                                                                       // being copied and the following bytes for the copied folder's UUID
                                                                                                       copyID =
                                                                                                           folder.ID;
                                                                                                       byte[]
                                                                                                           copyIDBytes =
                                                                                                               copyID
                                                                                                                   .GetBytes
                                                                                                                   ();
                                                                                                       im.BinaryBucket =
                                                                                                           new byte[
                                                                                                               1 +
                                                                                                               copyIDBytes
                                                                                                                   .Length
                                                                                                               ];
                                                                                                       im.BinaryBucket[0
                                                                                                           ] =
                                                                                                           (byte)
                                                                                                           AssetType
                                                                                                               .Folder;
                                                                                                       Array.Copy(
                                                                                                           copyIDBytes,
                                                                                                           0,
                                                                                                           im
                                                                                                               .BinaryBucket,
                                                                                                           1,
                                                                                                           copyIDBytes
                                                                                                               .Length);

                                                                                                       if (user != null)
                                                                                                           user
                                                                                                               .ControllingClient
                                                                                                               .SendBulkUpdateInventory
                                                                                                               (folder);

                                                                                                       im.SessionID =
                                                                                                           copyID;
                                                                                                       user
                                                                                                           .ControllingClient
                                                                                                           .SendInstantMessage
                                                                                                           (im);
                                                                                                   });
                    }
                    else
                    {
                        // First byte of the array is probably the item type
                        // Next 16 bytes are the UUID

                        UUID itemID = new UUID(im.BinaryBucket, 1);

                        MainConsole.Instance.DebugFormat("[INVENTORY TRANSFER]: (giving) Inserting item {0} " +
                                                         "into agent {1}'s inventory",
                                                         itemID, im.ToAgentID);

                        m_Scene.InventoryService.GiveInventoryItemAsync(
                            im.ToAgentID,
                            im.FromAgentID, itemID, UUID.Zero, false, (itemCopy) =>
                                                                          {
                                                                              if (itemCopy == null)
                                                                              {
                                                                                  client.SendAgentAlertMessage(
                                                                                      "Can't find item to give. Nothing given.",
                                                                                      false);
                                                                                  return;
                                                                              }

                                                                              copyID = itemCopy.ID;
                                                                              Array.Copy(copyID.GetBytes(), 0,
                                                                                         im.BinaryBucket, 1, 16);

                                                                              if (user != null)
                                                                              {
                                                                                  user.ControllingClient
                                                                                      .SendBulkUpdateInventory(itemCopy);
                                                                              }

                                                                              im.SessionID = itemCopy.ID;
                                                                              user.ControllingClient.SendInstantMessage(
                                                                                  im);
                                                                          });
                    }
                }
                else
                {
                    if (m_TransferModule != null)
                        m_TransferModule.SendInstantMessage(im);
                }
            }
            else if (im.Dialog == (byte) InstantMessageDialog.InventoryAccepted)
            {
                IScenePresence user = m_Scene.GetScenePresence(im.ToAgentID);

                if (user != null) // Local
                {
                    user.ControllingClient.SendInstantMessage(im);
                }
                else
                {
                    if (m_TransferModule != null)
                        m_TransferModule.SendInstantMessage(im);
                }
            }
            else if (im.Dialog == (byte) InstantMessageDialog.InventoryDeclined)
            {
                // Here, the recipient is local and we can assume that the
                // inventory is loaded. Courtesy of the above bulk update,
                // It will have been pushed to the client, too
                //
                IInventoryService invService = m_Scene.InventoryService;

                InventoryFolderBase trashFolder =
                    invService.GetFolderForType(client.AgentId, InventoryType.Unknown, AssetType.TrashFolder);

                UUID inventoryID = im.SessionID; // The inventory item/folder, back from it's trip

                InventoryItemBase item = invService.GetItem(client.AgentId, inventoryID);
                InventoryFolderBase folder = null;

                if (item != null && trashFolder != null)
                {
                    item.Folder = trashFolder.ID;

                    // Diva comment: can't we just update this item???
                    List<UUID> uuids = new List<UUID> {item.ID};
                    invService.DeleteItems(item.Owner, uuids);
                    ILLClientInventory inventory = client.Scene.RequestModuleInterface<ILLClientInventory>();
                    if (inventory != null)
                        inventory.AddInventoryItemAsync(client, item);
                }
                else
                {
                    folder = new InventoryFolderBase(inventoryID, client.AgentId);
                    folder = invService.GetFolder(folder);

                    if (folder != null & trashFolder != null)
                    {
                        folder.ParentID = trashFolder.ID;
                        invService.MoveFolder(folder);
                        client.SendBulkUpdateInventory(folder);
                    }
                }

                if ((null == item && null == folder) | null == trashFolder)
                {
                    string reason = String.Empty;

                    if (trashFolder == null)
                        reason += " Trash folder not found.";
                    if (item == null)
                        reason += " Item not found.";
                    if (folder == null)
                        reason += " Folder not found.";

                    client.SendAgentAlertMessage("Unable to delete " +
                                                 "received inventory" + reason, false);
                }

                IScenePresence user = m_Scene.GetScenePresence(im.ToAgentID);

                if (user != null) // Local
                {
                    user.ControllingClient.SendInstantMessage(im);
                }
                else
                {
                    if (m_TransferModule != null)
                        m_TransferModule.SendInstantMessage(im);
                }
            }
        }
        public byte[] CreateInventoryCategory(string path, Stream request, OSHttpRequest httpRequest,
                                              OSHttpResponse httpResponse)
        {
            OSDMap map = (OSDMap) OSDParser.DeserializeLLSDXml(HttpServerHandlerHelpers.ReadFully(request));
            UUID folder_id = map["folder_id"].AsUUID();
            UUID parent_id = map["parent_id"].AsUUID();
            int type = map["type"].AsInteger();
            string name = map["name"].AsString();

            InventoryFolderBase newFolder
                = new InventoryFolderBase(
                    folder_id, name, m_agentID, (short)type, parent_id, 1);
            m_inventoryService.AddFolder(newFolder);
            OSDMap resp = new OSDMap();
            resp["folder_id"] = folder_id;
            resp["parent_id"] = parent_id;
            resp["type"] = type;
            resp["name"] = name;

            return OSDParser.SerializeLLSDXmlBytes(map);
        }
        protected InventoryFolderBase CreateFolder(UUID principalID, UUID parentID, int type, string name)
        {
            InventoryFolderBase newFolder = new InventoryFolderBase
                                                {
                                                    Name = name,
                                                    Type = (short) type,
                                                    Version = 1,
                                                    ID = UUID.Random(),
                                                    Owner = principalID,
                                                    ParentID = parentID
                                                };

            m_Database.StoreFolder(newFolder);

            return newFolder;
        }
        /// <summary>
        ///     Find a folder given a PATH_DELIMITER delimited path starting from this folder
        /// </summary>
        /// This method does not handle paths that contain multiple delimitors
        /// 
        /// FIXME: We have no way of distinguishing folders with the same path.
        /// 
        /// FIXME: Delimitors which occur in names themselves are not currently escapable.
        /// <param name="inventoryService">
        ///     Inventory service to query
        /// </param>
        /// <param name="startFolder">
        ///     The folder from which the path starts
        /// </param>
        /// <param name="path">
        ///     The path to the required folder.
        ///     It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned.
        /// </param>
        /// <returns>An empty list if the folder is not found, otherwise a list of all folders that match the name</returns>
        public static List<InventoryFolderBase> FindFolderByPath(
            IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
        {
            List<InventoryFolderBase> foundFolders = new List<InventoryFolderBase>();

            if (path == string.Empty)
            {
                foundFolders.Add(startFolder);
                return foundFolders;
            }

            path = path.Trim();

            if (path == PATH_DELIMITER.ToString())
            {
                foundFolders.Add(startFolder);
                return foundFolders;
            }

            // If the path isn't just / then trim any starting extraneous slashes
            path = path.TrimStart(new[] {PATH_DELIMITER});

            //            MainConsole.Instance.DebugFormat("[INVENTORY ARCHIVE UTILS]: Adjusted path in FindFolderByPath() is [{0}]", path);

            string[] components = SplitEscapedPath(path);
            components[0] = UnescapePath(components[0]);

            //string[] components = path.Split(new string[] { PATH_DELIMITER.ToString() }, 2, StringSplitOptions.None);

            InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID);

            foreach (InventoryFolderBase folder in contents.Folders.Where(folder => folder.Name == components[0]))
            {
                if (components.Length > 1)
                    foundFolders.AddRange(FindFolderByPath(inventoryService, folder, components[1]));
                else
                    foundFolders.Add(folder);
            }
            return foundFolders;
        }
        public virtual bool DeleteFolders(UUID principalID, List<UUID> folderIDs)
        {
            object remoteValue = DoRemoteByURL("InventoryServerURI", principalID, folderIDs);
            if (remoteValue != null || m_doRemoteOnly)
                return remoteValue == null ? false : (bool) remoteValue;

            if (!m_AllowDelete)
            {
                foreach (UUID id in folderIDs)
                {
                    if (!ParentIsLinkFolder(id))
                        continue;
                    InventoryFolderBase f = new InventoryFolderBase {ID = id};
                    PurgeFolder(f);
                    m_Database.DeleteFolders("folderID", id.ToString(), true);
                }
                return true;
            }

            // Ignore principal ID, it's bogus at connector level
            //
            foreach (UUID id in folderIDs)
            {
                if (!ParentIsTrash(id))
                    continue;
                InventoryFolderBase f = new InventoryFolderBase {ID = id};
                PurgeFolder(f);
                m_Database.DeleteFolders("folderID", id.ToString(), true);
            }

            return true;
        }
        /// <summary>
        ///     Create a set of folders for the given path.
        /// </summary>
        /// <param name="destFolder">
        ///     The root folder from which the creation will take place.
        /// </param>
        /// <param name="iarPathExisting">
        ///     the part of the iar path that already exists
        /// </param>
        /// <param name="iarPathToReplicate">
        ///     The path to replicate in the user's inventory from iar
        /// </param>
        /// <param name="resolvedFolders">
        ///     The folders that we have resolved so far for a given archive path.
        /// </param>
        /// <param name="loadedNodes">
        ///     Track the inventory nodes created.
        /// </param>
        protected void CreateFoldersForPath(
            InventoryFolderBase destFolder,
            string iarPathExisting,
            string iarPathToReplicate,
            ref Dictionary<string, InventoryFolderBase> resolvedFolders,
            ref HashSet<InventoryNodeBase> loadedNodes)
        {
            string[] rawDirsToCreate = iarPathToReplicate.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);

            for (int i = 0; i < rawDirsToCreate.Length; i++)
            {
                //                MainConsole.Instance.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0} from IAR", rawDirsToCreate[i]);

                if (!rawDirsToCreate[i].Contains(ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR))
                    continue;

                int identicalNameIdentifierIndex
                    = rawDirsToCreate[i].LastIndexOf(
                        ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR);

                string newFolderName = rawDirsToCreate[i].Remove(identicalNameIdentifierIndex);

                newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName);
                UUID newFolderId = UUID.Random();

                // Asset type has to be Unknown here rather than Folder, otherwise the created folder can't be
                // deleted once the client has relogged.
                // The root folder appears to be labelled AssetType.Folder (shows up as "Category" in the client)
                // even though there is a AssetType.RootCategory
                destFolder
                    = new InventoryFolderBase(
                        newFolderId, newFolderName, m_userInfo.PrincipalID,
                        (short) AssetType.Unknown, destFolder.ID, 1);
                m_registry.RequestModuleInterface<IInventoryService>().AddFolder(destFolder);

                // Record that we have now created this folder
                iarPathExisting += rawDirsToCreate[i] + "/";
                MainConsole.Instance.DebugFormat("[INVENTORY ARCHIVER]: Created folder {0} from IAR", iarPathExisting);
                resolvedFolders[iarPathExisting] = destFolder;

                if (0 == i && loadedNodes != null)
                    loadedNodes.Add(destFolder);
            }
        }
        public virtual void FixInventory(IScene scene, string[] cmd)
        {
            string userName = MainConsole.Instance.Prompt("Name of user");
            UserAccount account = m_UserAccountService.GetUserAccount(null, userName);
            if (account == null)
            {
                MainConsole.Instance.Warn("Could not find user");
                return;
            }
            InventoryFolderBase rootFolder = GetRootFolder(account.PrincipalID);

            //Fix having a default root folder
            if (rootFolder == null)
            {
                MainConsole.Instance.Warn("Fixing default root folder...");
                List<InventoryFolderBase> skel = GetInventorySkeleton(account.PrincipalID);
                if (skel.Count == 0)
                {
                    CreateUserInventory(account.PrincipalID, false);
                    rootFolder = GetRootFolder(account.PrincipalID);
                }
                else
                {
                    rootFolder = new InventoryFolderBase
                                     {
                                         Name = "My Inventory",
                                         Type = (short) AssetType.RootFolder,
                                         Version = 1,
                                         ID = skel[0].ParentID,
                                         Owner = account.PrincipalID,
                                         ParentID = UUID.Zero
                                     };
                }
            }
            //Check against multiple root folders
            List<InventoryFolderBase> rootFolders = GetRootFolders(account.PrincipalID);
            List<UUID> badFolders = new List<UUID>();
            if (rootFolders.Count != 1)
            {
                //No duplicate folders!
                foreach (
                    InventoryFolderBase f in rootFolders.Where(f => !badFolders.Contains(f.ID) && f.ID != rootFolder.ID)
                    )
                {
                    MainConsole.Instance.Warn("Removing duplicate root folder " + f.Name);
                    badFolders.Add(f.ID);
                }
            }
            //Fix any root folders that shouldn't be root folders
            List<InventoryFolderBase> skeleton = GetInventorySkeleton(account.PrincipalID);
            List<UUID> foundFolders = new List<UUID>();
            foreach (InventoryFolderBase f in skeleton)
            {
                if (!foundFolders.Contains(f.ID))
                    foundFolders.Add(f.ID);
                if (f.Name == "My Inventory" && f.ParentID != UUID.Zero)
                {
                    //Merge them all together
                    badFolders.Add(f.ID);
                }
            }
            foreach (InventoryFolderBase f in skeleton)
            {
                if ((!foundFolders.Contains(f.ParentID) && f.ParentID != UUID.Zero) ||
                    f.ID == f.ParentID)
                {
                    //The viewer loses the parentID when something goes wrong
                    //it puts it in the top where My Inventory should be
                    //We need to put it back in the My Inventory folder, as the sub folders are right for some reason
                    f.ParentID = rootFolder.ID;
                    m_Database.StoreFolder(f);
                    MainConsole.Instance.WarnFormat("Fixing folder {0}", f.Name);
                }
                else if (badFolders.Contains(f.ParentID))
                {
                    //Put it back in the My Inventory folder
                    f.ParentID = rootFolder.ID;
                    m_Database.StoreFolder(f);
                    MainConsole.Instance.WarnFormat("Fixing folder {0}", f.Name);
                }
                else if (f.Type == (short) AssetType.CurrentOutfitFolder)
                {
                    List<InventoryItemBase> items = GetFolderItems(account.PrincipalID, f.ID);
                    //Check the links!
                    List<UUID> brokenLinks = new List<UUID>();
                    foreach (InventoryItemBase item in items)
                    {
                        InventoryItemBase linkedItem = null;
                        if ((linkedItem = GetItem(account.PrincipalID, item.AssetID)) == null)
                        {
                            //Broken link...
                            brokenLinks.Add(item.ID);
                        }
                        else if (linkedItem.ID == AvatarWearable.DEFAULT_EYES_ITEM ||
                                 linkedItem.ID == AvatarWearable.DEFAULT_BODY_ITEM ||
                                 linkedItem.ID == AvatarWearable.DEFAULT_HAIR_ITEM ||
                                 linkedItem.ID == AvatarWearable.DEFAULT_PANTS_ITEM ||
                                 linkedItem.ID == AvatarWearable.DEFAULT_SHIRT_ITEM ||
                                 linkedItem.ID == AvatarWearable.DEFAULT_SKIN_ITEM)
                        {
                            //Default item link, needs removed
                            brokenLinks.Add(item.ID);
                        }
                    }
                    if (brokenLinks.Count != 0)
                        DeleteItems(account.PrincipalID, brokenLinks);
                }
                else if (f.Type == (short) AssetType.Mesh)
                {
                    ForcePurgeFolder(f);
                }
            }
            foreach (UUID id in badFolders)
            {
                m_Database.DeleteFolders("folderID", id.ToString(), false);
            }
            //Make sure that all default folders exist
            CreateUserInventory(account.PrincipalID, false);
            //Refetch the skeleton now
            skeleton = GetInventorySkeleton(account.PrincipalID);
            Dictionary<int, UUID> defaultFolders = new Dictionary<int, UUID>();
            Dictionary<UUID, UUID> changedFolders = new Dictionary<UUID, UUID>();
            foreach (InventoryFolderBase folder in skeleton.Where(folder => folder.Type != -1))
            {
                if (!defaultFolders.ContainsKey(folder.Type))
                    defaultFolders[folder.Type] = folder.ID;
                else
                    changedFolders.Add(folder.ID, defaultFolders[folder.Type]);
            }
            foreach (InventoryFolderBase folder in skeleton)
            {
                if (folder.Type != -1 && defaultFolders[folder.Type] != folder.ID)
                {
                    //Delete the dup
                    ForcePurgeFolder(folder);
                    MainConsole.Instance.Warn("Purging duplicate default inventory type folder " + folder.Name);
                }
                if (changedFolders.ContainsKey(folder.ParentID))
                {
                    folder.ParentID = changedFolders[folder.ParentID];
                    MainConsole.Instance.Warn("Merging child folder of default inventory type " + folder.Name);
                    m_Database.StoreFolder(folder);
                }
            }
            MainConsole.Instance.Warn("Completed the check");
        }
 /// <summary>
 ///     Move the inventory folder to another place in the user's inventory
 /// </summary>
 /// <param name="remoteClient">The client that requested the change</param>
 /// <param name="folderID">The folder UUID to move</param>
 /// <param name="parentID">The folder to move the folder (folderID) into</param>
 protected void HandleMoveInventoryFolder(IClientAPI remoteClient, UUID folderID, UUID parentID)
 {
     InventoryFolderBase folder = new InventoryFolderBase(folderID, remoteClient.AgentId);
     folder = m_scene.InventoryService.GetFolder(folder);
     if (folder != null)
     {
         folder.ParentID = parentID;
         if (!m_scene.InventoryService.MoveFolder(folder))
             MainConsole.Instance.WarnFormat("[AGENT INVENTORY]: could not move folder {0}", folderID);
         else
             MainConsole.Instance.DebugFormat("[AGENT INVENTORY]: folder {0} moved to parent {1}", folderID,
                                              parentID);
     }
     else
     {
         MainConsole.Instance.WarnFormat("[AGENT INVENTORY]: request to move folder {0} but folder not found",
                                         folderID);
     }
 }
 public virtual bool StoreFolder(InventoryFolderBase folder)
 {
     QueryFilter filter = new QueryFilter();
     filter.andFilters["folderID"] = folder.ID;
     GD.Delete(m_foldersrealm, filter);
     Dictionary<string, object> row = new Dictionary<string, object>(6);
     row["folderName"] = folder.Name;
     row["type"] = folder.Type;
     row["version"] = folder.Version;
     row["folderID"] = folder.ID;
     row["agentID"] = folder.Owner;
     row["parentFolderID"] = folder.ParentID;
     return GD.Insert(m_foldersrealm, row);
 }
        /// <summary>
        ///     Send an update to the client about the given folder
        /// </summary>
        /// <param name="client">The client to send the update to</param>
        /// <param name="folder">The folder that we need to send</param>
        /// <param name="fetchFolders">Should we fetch folders inside of this folder</param>
        /// <param name="fetchItems">Should we fetch items inside of this folder</param>
        protected void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders,
                                           bool fetchItems)
        {
            if (folder == null)
                return;

            // Fetch the folder contents
            InventoryCollection contents = m_scene.InventoryService.GetFolderContent(client.AgentId, folder.ID);

            // Fetch the folder itself to get its current version
            InventoryFolderBase containingFolder = new InventoryFolderBase(folder.ID, client.AgentId);
            containingFolder = m_scene.InventoryService.GetFolder(containingFolder);

            //MainConsole.Instance.DebugFormat("[AGENT INVENTORY]: Sending inventory folder contents ({0} nodes) for \"{1}\" to {2} {3}",
            //    contents.Folders.Count + contents.Items.Count, containingFolder.Name, client.FirstName, client.LastName);

            if (containingFolder != null)
                client.SendInventoryFolderDetails(client.AgentId, folder.ID, contents.Items, contents.Folders,
                                                  containingFolder.Version, fetchFolders, fetchItems);
        }
        /// <summary>
        ///     Replicate the inventory paths in the archive to the user's inventory as necessary.
        /// </summary>
        /// <param name="iarPath">The item archive path to replicate</param>
        /// <param name="rootDestFolder">The root folder for the inventory load</param>
        /// <param name="resolvedFolders">
        ///     The folders that we have resolved so far for a given archive path.
        ///     This method will add more folders if necessary
        /// </param>
        /// <param name="loadedNodes">
        ///     Track the inventory nodes created.
        /// </param>
        /// <returns>The last user inventory folder created or found for the archive path</returns>
        public InventoryFolderBase ReplicateArchivePathToUserInventory(
            string iarPath,
            InventoryFolderBase rootDestFolder,
            ref Dictionary<string, InventoryFolderBase> resolvedFolders,
            ref HashSet<InventoryNodeBase> loadedNodes)
        {
            string iarPathExisting = iarPath;

            //            MainConsole.Instance.DebugFormat(
            //                "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID);

            InventoryFolderBase destFolder
                = ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, ref resolvedFolders);

            //            MainConsole.Instance.DebugFormat(
            //                "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]",
            //                iarPath, iarPathExisting);

            string iarPathToCreate = iarPath.Substring(iarPathExisting.Length);
            CreateFoldersForPath(destFolder, iarPathExisting, iarPathToCreate, ref resolvedFolders, ref loadedNodes);

            return destFolder;
        }
        //[CanBeReflected(ThreatLevel = ThreatLevel.Full)]
        public virtual bool ForcePurgeFolder(InventoryFolderBase folder)
        {
            /*object remoteValue = DoRemoteByURL("InventoryServerURI", folder);
            if (remoteValue != null || m_doRemoteOnly)
                return remoteValue == null ? false : (bool)remoteValue;*/

            List<InventoryFolderBase> subFolders = m_Database.GetFolders(
                new[] {"parentFolderID"},
                new[] {folder.ID.ToString()});

            foreach (InventoryFolderBase x in subFolders)
            {
                ForcePurgeFolder(x);
                m_Database.DeleteFolders("folderID", x.ID.ToString(), false);
            }

            m_Database.DeleteItems("parentFolderID", folder.ID.ToString());
            m_Database.DeleteFolders("folderID", folder.ID.ToString(), false);

            return true;
        }
        /// <summary>
        ///     Load an item from the archive
        /// </summary>
        /// <param name="data">The raw item data</param>
        /// <param name="loadFolder"> </param>
        protected InventoryItemBase LoadItem(byte[] data, InventoryFolderBase loadFolder)
        {
            InventoryItemBase item = UserInventoryItemSerializer.Deserialize(data);

            // Don't use the item ID that's in the file
            item.ID = UUID.Random();

            UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId,
                                                         m_registry.RequestModuleInterface<IUserAccountService>());
            if (UUID.Zero != ospResolvedId)
            {
                item.CreatorIdAsUuid = ospResolvedId;

                // Don't preserve the OSPA in the creator id (which actually gets persisted to the
                // database).  Instead, replace with the UUID that we found.
                item.CreatorId = ospResolvedId.ToString();

                item.CreatorData = string.Empty;
            }
            else if (string.IsNullOrEmpty(item.CreatorData))
            {
                item.CreatorId = m_userInfo.PrincipalID.ToString();
                item.CreatorIdAsUuid = new UUID(item.CreatorId);
            }

            item.Owner = m_userInfo.PrincipalID;

            // Record the creator id for the item's asset so that we can use it later, if necessary, when the asset
            // is loaded.
            // 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;

            // Reset folder ID to the one in which we want to load it
            item.Folder = loadFolder.ID;

            itemsSavedOff.Add(item);

            return item;
        }
 private List<InventoryFolderBase> ParseInventoryFolders(ref Dictionary<string, List<string>> retVal)
 {
     List<InventoryFolderBase> folders = new List<InventoryFolderBase>();
     if (retVal.Count == 0)
         return folders;
     for (int i = 0; i < retVal.ElementAt(0).Value.Count; i++)
     {
         InventoryFolderBase folder = new InventoryFolderBase
                                          {
                                              Name = retVal["folderName"][i],
                                              Type = short.Parse(retVal["type"][i]),
                                              Version = (ushort) int.Parse(retVal["version"][i]),
                                              ID = UUID.Parse(retVal["folderID"][i]),
                                              Owner = UUID.Parse(retVal["agentID"][i]),
                                              ParentID = UUID.Parse(retVal["parentFolderID"][i])
                                          };
         folders.Add(folder);
     }
     //retVal.Clear();
     return folders;
 }
        /// <summary>
        ///     Save an inventory folder
        /// </summary>
        /// <param name="inventoryFolder">The inventory folder to save</param>
        /// <param name="path">The path to which the folder should be saved</param>
        /// <param name="saveThisFolderItself">If true, save this folder itself.  If false, only saves contents</param>
        protected void SaveInvFolder(InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself)
        {
            if (saveThisFolderItself)
            {
                path += CreateArchiveFolderName(inventoryFolder);

                // We need to make sure that we record empty folders
                m_archiveWriter.WriteDir(path);
            }

            InventoryCollection contents
                = m_registry.RequestModuleInterface<IInventoryService>().GetFolderContent(inventoryFolder.Owner,
                                                                                          inventoryFolder.ID);

            foreach (InventoryFolderBase childFolder in contents.Folders)
            {
                SaveInvFolder(childFolder, path, true);
            }

            foreach (InventoryItemBase item in contents.Items)
            {
                SaveInvItem(item, path);
            }
        }