// 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"]; }
/// <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); UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_accountService); 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); } // Don't use the item ID that's in the file, this could be a local user's folder //item.ID = UUID.Random(); 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; }
/// <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; }
public AvatarArchive LoadAvatarArchive (string fileName, UUID principalID) { AvatarArchive archive = new AvatarArchive (); UserAccount account = userAccountService.GetUserAccount (null, principalID); if (account == null) { MainConsole.Instance.Error ("[Avatar Archiver]: User not found!"); return null; } // need to be smart here... fileName = PathHelpers.VerifyReadFile (fileName, ".aa", m_storeDirectory); if (!File.Exists (fileName)) { MainConsole.Instance.Error ("[Avatar Archiver]: Unable to load from file: file does not exist!"); return null; } MainConsole.Instance.Info ("[Avatar Archiver]: Loading archive from " + fileName); archive.FromOSD ((OSDMap)OSDParser.DeserializeLLSDXml (File.ReadAllText (fileName))); AvatarAppearance appearance = ConvertXMLToAvatarAppearance (archive.BodyMap); appearance.Owner = principalID; InventoryFolderBase AppearanceFolder = inventoryService.GetFolderForType (account.PrincipalID, InventoryType.Wearable, FolderType.Clothing); if (AppearanceFolder == null) { AppearanceFolder = new InventoryFolderBase (); // does not exist so... AppearanceFolder.Owner = account.PrincipalID; AppearanceFolder.ID = UUID.Random (); AppearanceFolder.Type = (short)FolderType.Clothing; } List<InventoryItemBase> items; InventoryFolderBase folderForAppearance = new InventoryFolderBase ( UUID.Random (), archive.FolderName, account.PrincipalID, (short)FolderType.None, AppearanceFolder.ID, 1); inventoryService.AddFolder (folderForAppearance); folderForAppearance = inventoryService.GetFolder (folderForAppearance); try { LoadAssets (archive.AssetsMap); appearance = CopyWearablesAndAttachments (account.PrincipalID, UUID.Zero, appearance, folderForAppearance, account.PrincipalID, archive.ItemsMap, out items); } catch (Exception ex) { MainConsole.Instance.Warn ("[AvatarArchiver]: Error loading assets and items, " + ex); } /* implement fully if we need to // inform the client if needed ScenePresence SP; MainConsole.Instance.ConsoleScenes[0].TryGetScenePresence(account.PrincipalID, out SP); if (SP == null) return; // nobody home! SP.ControllingClient.SendAlertMessage("Appearance loading in progress..."); SP.ControllingClient.SendBulkUpdateInventory(folderForAppearance); */ MainConsole.Instance.Info ("[Avatar Archiver]: Loaded archive from " + fileName); archive.Appearance = appearance; return archive; }
InventoryItemBase GiveInventoryItem (UUID senderId, UUID recipient, InventoryItemBase item, InventoryFolderBase parentFolder) { InventoryItemBase itemCopy = new InventoryItemBase { Owner = recipient, CreatorId = item.CreatorId, CreatorData = item.CreatorData, ID = UUID.Random (), AssetID = item.AssetID, Description = item.Description, Name = item.Name, AssetType = item.AssetType, InvType = item.InvType, Folder = UUID.Zero, NextPermissions = (uint)PermissionMask.All, GroupPermissions = (uint)PermissionMask.All, EveryOnePermissions = (uint)PermissionMask.All, CurrentPermissions = (uint)PermissionMask.All }; //Give full permissions for them if (parentFolder == null) { InventoryFolderBase folder = inventoryService.GetFolderForType (recipient, InventoryType.Unknown, (FolderType)itemCopy.AssetType); if (folder != null) itemCopy.Folder = folder.ID; else { InventoryFolderBase root = inventoryService.GetRootFolder (recipient); if (root != null) itemCopy.Folder = root.ID; else return null; // No destination } } else itemCopy.Folder = parentFolder.ID; //We already have a folder to put it in itemCopy.GroupID = UUID.Zero; itemCopy.GroupOwned = false; itemCopy.Flags = item.Flags; itemCopy.SalePrice = item.SalePrice; itemCopy.SaleType = item.SaleType; inventoryService.AddItem (itemCopy); return itemCopy; }
/// <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 char[] { 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) { if (folder.Name == components[0]) { if (components.Length > 1) foundFolders.AddRange(FindFolderByPath(inventoryService, folder, components[1])); else foundFolders.Add(folder); } } return foundFolders; }
/// <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> /// Create the archive name for a particular folder. /// </summary> /// /// These names are prepended with an inventory folder's UUID so that more than one folder can have the /// same name /// /// <param name="folder"></param> /// <returns></returns> public static string CreateArchiveFolderName(InventoryFolderBase folder) { return CreateArchiveFolderName (folder.Name, folder.ID); }
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]; }
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; }
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_SHAPE_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"); }
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; }
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; }
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); }
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); }
/// <summary> /// Execute the inventory write request /// </summary> public void Execute(string fileName) { Stream m_saveStream = new GZipStream (new FileStream (fileName, FileMode.Create), CompressionMode.Compress); try { InventoryFolderBase inventoryFolder = new InventoryFolderBase (UUID.Zero, UUID.Zero); if (m_rootFolders.Count == 1) inventoryFolder = m_rootFolders[0]; bool saveFolderContentsOnly = false; m_archiveWriter = new TarArchiveWriter (m_saveStream); if (inventoryFolder != null) { //recurse through all dirs getting dirs and files SaveInvFolder (inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly); } } catch (Exception) { m_saveStream.Close (); throw; } foreach (AssetBase asset in m_loadedAssets.Values) { WriteData (asset); } m_saveStream.Close (); MessageBox.Show ("Save complete!"); }
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; }
/// <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) { string[] rawDirsToCreate = iarPathToReplicate.Split (new char[] { '/' }, 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, UUID.Zero, (short)AssetType.Unknown, destFolder.ID, 1); // Record that we have now created this folder iarPathExisting += rawDirsToCreate[i] + "/"; resolvedFolders[iarPathExisting] = destFolder; m_folders.Add (destFolder); if(!m_childFolders.ContainsKey(destFolder.ParentID)) m_childFolders.Add (destFolder.ParentID, new List<InventoryFolderBase>()); m_childFolders[destFolder.ParentID].Add (destFolder); m_folderList.Add (destFolder.ID, destFolder); } }
/// <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"> /// <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 char[] { 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); foreach (InventoryItemBase item in items) { // MainConsole.Instance.DebugFormat("[INVENTORY ARCHIVE UTILS]: Inspecting item {0} {1}", item.Name, item.ID); if (item.Name == components[0]) return item; } } else { // MainConsole.Instance.DebugFormat("FOUND COMPONENTS [{0}] and [{1}]", components[0], components[1]); InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); foreach (InventoryFolderBase folder in contents.Folders) { if (folder.Name == components[0]) return FindItemByPath(inventoryService, folder, components[1]); } } // We didn't find an item or intermediate folder with the given name return null; }
/// <summary> /// Load an item from the archive /// </summary> /// <param name="filePath">The archive path for the item</param> /// <param name="data">The raw item data</param> /// <param name="rootDestinationFolder">The root destination folder for loaded items</param> /// <param name="nodesLoaded">All the inventory nodes (items and folders) loaded so far</param> protected InventoryItemBase LoadItem(byte[] data, InventoryFolderBase loadFolder) { InventoryItemBase item = UserInventoryItemSerializer.Deserialize (data); item.Folder = loadFolder.ID; if(!m_items.ContainsKey(item.Folder)) m_items.Add (item.Folder, new List<InventoryItemBase>()); m_items[item.Folder].Add (item); m_itemList[item.ID] = item; return item; }
AvatarAppearance CopyWearablesAndAttachments (UUID destination, UUID source, AvatarAppearance avatarAppearance, InventoryFolderBase destinationFolder, UUID agentid, OSDMap itemsMap, out List<InventoryItemBase> items) { items = new List<InventoryItemBase> (); if (destinationFolder == null) { MainConsole.Instance.Error ("[Avatar Archiver]: Cannot locate folder(s) for copying wearables!"); return avatarAppearance; } List<InventoryItemBase> litems = new List<InventoryItemBase> (); foreach (KeyValuePair<string, OSD> kvp in itemsMap) { InventoryItemBase item = new InventoryItemBase (); item.FromOSD ((OSDMap)kvp.Value); MainConsole.Instance.Info ("[Avatar Archiver]: Loading item " + item.ID); litems.Add (item); } // Wearables AvatarWearable [] wearables = avatarAppearance.Wearables; MainConsole.Instance.InfoFormat ("[Avatar Archiver] Adding {0} wearables", wearables.Length); for (int i = 0; i < wearables.Length; i++) { AvatarWearable wearable = wearables [i]; for (int ii = 0; ii < wearable.Count; ii++) { if (wearable [ii].ItemID != UUID.Zero) { // Get inventory item and copy it InventoryItemBase item = inventoryService.GetItem (UUID.Zero, wearable [ii].ItemID); if (item == null) { //Attempt to get from the map if it doesn't already exist on the grid item = litems.First ((itm) => itm.ID == wearable [ii].ItemID); } if (item != null) { InventoryItemBase destinationItem = inventoryService.InnerGiveInventoryItem (destination, destination, item, destinationFolder .ID, false, false); items.Add (destinationItem); MainConsole.Instance.DebugFormat ("[Avatar Archiver]: Added item {0} to folder {1}", destinationItem.ID, destinationFolder.ID); // Wear item AvatarWearable newWearable = new AvatarWearable (); newWearable.Wear (destinationItem.ID, destinationItem.AssetID); avatarAppearance.SetWearable (i, newWearable); } else { MainConsole.Instance.WarnFormat ("[Avatar Archiver]: Unable to transfer {0} to folder {1}", wearable [ii].ItemID, destinationFolder.ID); } } } } // Attachments List<AvatarAttachment> attachments = avatarAppearance.GetAttachments (); MainConsole.Instance.InfoFormat ("[Avatar Archiver] Adding {0} attachments", attachments.Count); foreach (AvatarAttachment attachment in attachments) { int attachpoint = attachment.AttachPoint; UUID itemID = attachment.ItemID; if (itemID != UUID.Zero) { // Get inventory item and copy it InventoryItemBase item = inventoryService.GetItem (UUID.Zero, itemID); if (item == null) { //Attempt to get from the map if it doesn't already exist on the grid item = litems.First ((itm) => itm.ID == itemID); } if (item != null) { InventoryItemBase destinationItem = inventoryService.InnerGiveInventoryItem (destination, destination, item, destinationFolder.ID, false, false); items.Add (destinationItem); MainConsole.Instance.DebugFormat ("[Avatar Archiver]: Added item {0} to folder {1}", destinationItem.ID, destinationFolder.ID); // Attach item avatarAppearance.SetAttachment (attachpoint, destinationItem.ID, destinationItem.AssetID); MainConsole.Instance.DebugFormat ("[Avatar Archiver]: Attached {0}", destinationItem.ID); } else { MainConsole.Instance.WarnFormat ("[Avatar Archiver]: Error transferring {0} to folder {1}", itemID, destinationFolder.ID); } } } return avatarAppearance; }
/// <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 name="rootDestinationFolder"> /// 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]; } else { // 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> /// Execute the request /// </summary> /// <returns> /// A list of the inventory nodes loaded. If folders were loaded then only the root folders are /// returned /// </returns> public HashSet<InventoryNodeBase> Execute(bool loadAll) { if (m_loadStream == null) return new HashSet<InventoryNodeBase>(); try { string filePath = "ERROR"; int successfulAssetRestores = 0; int failedAssetRestores = 0; int successfulItemRestores = 0; HashSet<InventoryNodeBase> loadedNodes = loadAll ? new HashSet<InventoryNodeBase>() : null; List<InventoryFolderBase> folderCandidates = InventoryArchiveUtils.FindFolderByPath(m_inventoryService, m_userInfo.PrincipalID, m_invPath); if (folderCandidates.Count == 0) { // try and create requested folder var rootFolder = m_inventoryService.GetRootFolder(m_userInfo.PrincipalID); InventoryFolderBase iarImportFolder = new InventoryFolderBase(); iarImportFolder.ID = UUID.Random(); iarImportFolder.Name = m_invPath; // the path iarImportFolder.Owner = m_userInfo.PrincipalID; // owner iarImportFolder.ParentID = rootFolder.ID; // the root folder iarImportFolder.Type = -1; // user defined folder iarImportFolder.Version = 1; // initial version m_inventoryService.AddFolder(iarImportFolder); // ensure that it now exists... folderCandidates = InventoryArchiveUtils.FindFolderByPath(m_inventoryService, m_userInfo.PrincipalID, m_invPath); if (folderCandidates.Count == 0) { MainConsole.Instance.ErrorFormat("[INVENTORY ARCHIVER]: Unable to create Inventory path {0}", m_invPath); return loadedNodes; } } // we have the base folder... do it... InventoryFolderBase rootDestinationFolder = folderCandidates[0]; archive = new TarArchiveReader(m_loadStream); // In order to load identically named folders, we need to keep track of the folders that we have already // resolved Dictionary<string, InventoryFolderBase> resolvedFolders = new Dictionary<string, InventoryFolderBase>(); MainConsole.Instance.Info("[ARCHIVER]: Commencing load from archive"); int ticker = 0; byte[] data; TarArchiveReader.TarEntryType entryType; while ((data = archive.ReadEntry(out filePath, out entryType)) != null) { if (TarArchiveReader.TarEntryType.TYPE_NORMAL_FILE == entryType) { var fName = Path.GetFileName (filePath); if (fName.StartsWith (".")) // ignore hidden files continue; } ticker ++; if (ticker % 5 == 0) MainConsole.Instance.Ticker(); if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) { if (LoadAsset(filePath, data)) successfulAssetRestores++; else failedAssetRestores++; if ((successfulAssetRestores)%50 == 0) MainConsole.Instance.InfoFormat( " [INVENTORY ARCHIVER]: Loaded {0} assets...", successfulAssetRestores); } else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH)) { filePath = filePath.Substring(ArchiveConstants.INVENTORY_PATH.Length); // Trim off the file portion if we aren't already dealing with a directory path if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) filePath = filePath.Remove(filePath.LastIndexOf("/") + 1); InventoryFolderBase foundFolder = ReplicateArchivePathToUserInventory( filePath, rootDestinationFolder, ref resolvedFolders, ref loadedNodes); if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) { InventoryItemBase item = LoadItem(data, foundFolder); if (item != null) { successfulItemRestores++; if ((successfulItemRestores)%50 == 0) MainConsole.Instance.InfoFormat( "[INVENTORY ARCHIVER]: Restored {0} items...",successfulItemRestores); // If we aren't loading the folder containing the item then well need to update the // viewer separately for that item. if (loadAll && !loadedNodes.Contains(foundFolder)) loadedNodes.Add(item); } item = null; } } else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) { LoadControlFile(data); } data = null; } MainConsole.Instance.CleanInfo(""); MainConsole.Instance.Info("[INVENTORY ARCHIVER]: Saving loaded inventory items"); ticker = 0; int successfulItemLoaded = 0; foreach (InventoryItemBase item in itemsSavedOff) { ticker++; if (ticker % 5 == 0) MainConsole.Instance.Ticker(); AddInventoryItem(item); successfulItemLoaded++; if ((successfulItemLoaded)%50 == 0) MainConsole.Instance.InfoFormat( "[INVENTORY ARCHIVER]: Loaded {0} items of {1}...", successfulItemLoaded, itemsSavedOff.Count); } itemsSavedOff.Clear(); assets2Save.Clear(); MainConsole.Instance.CleanInfo(""); MainConsole.Instance.InfoFormat( "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", successfulAssetRestores, failedAssetRestores); MainConsole.Instance.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores); return loadedNodes; } finally { m_loadStream.Close(); } }
/// <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 = FindInventoryCollection (inventoryFolder.Owner, inventoryFolder.ID); foreach (InventoryFolderBase childFolder in contents.Folders) { SaveInvFolder (childFolder, path, true); } foreach (InventoryItemBase item in contents.Items) { SaveInvItem (item, path); } }
/// <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 (); // assume we need a new ID // 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); // Check for existing folders string resPath = ""; foreach (var rPath in resolvedFolders) { var pName = rPath.Key; if (pName.Contains (ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR)) { int splitIndex = pName.LastIndexOf (ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR); pName = pName.Remove (splitIndex); } resPath += pName + "/"; } var existingFolder = m_inventoryService.GetUserFolderID (m_userInfo.PrincipalID, resPath + newFolderName); if (existingFolder.Count == 0) m_inventoryService.AddFolder (destFolder); // add the folder else destFolder.ID = (UUID)existingFolder [0]; // use the existing ID // 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); } }
void LoadIAR(string fileName) { //Load the iar into memory TarArchiveReader archive = new TarArchiveReader (new GZipStream (ArchiveHelpers.GetStream (fileName), CompressionMode.Decompress)); byte[] data; TarArchiveReader.TarEntryType entryType; string filePath; InventoryFolderBase rootDestFolder = new InventoryFolderBase (UUID.Zero, UUID.Zero); Dictionary<string, InventoryFolderBase> resolvedFolders = new Dictionary<string, InventoryFolderBase> (); while ((data = archive.ReadEntry (out filePath, out entryType)) != null) { if (filePath.StartsWith (ArchiveConstants.ASSETS_PATH)) { LoadAsset (filePath, data); } else if (filePath.StartsWith (ArchiveConstants.INVENTORY_PATH)) { filePath = filePath.Substring (ArchiveConstants.INVENTORY_PATH.Length); // Trim off the file portion if we aren't already dealing with a directory path if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) filePath = filePath.Remove (filePath.LastIndexOf ("/") + 1); InventoryFolderBase foundFolder = ReplicateArchivePathToUserInventory ( filePath, rootDestFolder, ref resolvedFolders); if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) { LoadItem (data, foundFolder); } } } archive.Close (); //Got the .iar loaded into memory now // Time to put it into the GUI RebuildTreeView (); }
/// <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 destination 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_inventoryService, 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> /// Find an item given a PATH_DELIMITOR delimited path starting from this folder. /// This method does not handle paths that contain multiple delimiters /// 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: Delimiters 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(); } }