// Constructors public InventoryFolderImpl (InventoryFolderBase folderbase) { Owner = folderbase.Owner; ID = folderbase.ID; Name = folderbase.Name; ParentID = folderbase.ParentID; Type = folderbase.Type; Version = folderbase.Version; }
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 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 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> /// 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(); } }
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> /// 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; if (DeRezAction.SaveToExistingUserInventoryItem == action) { item = m_scene.InventoryService.GetItem(userID, objectGroups[0].RootChild.FromUserInventoryItemID); //item = userInfo.RootFolder.FindItem( // objectGroup.RootPart.FromUserInventoryItemID); if (item == null) { 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, FolderType.LostAndFound); } else { folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, FolderType.Trash); } } else if (action == DeRezAction.Return) { // Dump to lost + found unconditionally // folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, FolderType.LostAndFound); } if (folderID == UUID.Zero && folder == null) { if (action == DeRezAction.Delete) { // Deletes go to trash by default // folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, FolderType.Trash); } else { if (SP == null || SP.ControllingClient == null || objectGroups[0].OwnerID != agentId) { folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, FolderType.LostAndFound); } else { folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, FolderType.Trash); } } } // 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, FolderType.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> /// 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) { // ignore viewer folders (special folders?) if (inventoryFolder.Name.StartsWith ("#")) return; if (saveThisFolderItself) { path += CreateArchiveFolderName(inventoryFolder); // We need to make sure that we record empty folders m_archiveWriter.WriteDir(path); } InventoryCollection contents = m_inventoryService.GetFolderContent(inventoryFolder.Owner, inventoryFolder.ID); foreach (InventoryFolderBase childFolder in contents.Folders) { SaveInvFolder(childFolder, path, true); } foreach (InventoryItemBase item in contents.Items) { SaveInvItem(item, path); } }
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 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); }
/// <summary> /// Constructor /// </summary> public InventoryArchiveWriteRequest( Guid id, InventoryArchiverModule module, IRegistryCore registry, UserAccount userInfo, string invPath, Stream saveStream, bool UseAssets, InventoryFolderBase folderBase, List<AssetBase> assetsToAdd, string checkPermissions) { m_id = id; m_module = module; m_registry = registry; m_userInfo = userInfo; m_invPath = invPath; m_saveStream = saveStream; m_saveAssets = UseAssets; m_defaultFolderToSave = folderBase; m_assetsToAdd = assetsToAdd; // Set Permission filter if available if (checkPermissions != null) FilterContent = checkPermissions.ToUpper(); // some necessary services m_inventoryService = m_registry.RequestModuleInterface<IInventoryService> (); m_assetService = m_registry.RequestModuleInterface<IAssetService> (); m_accountService = m_registry.RequestModuleInterface<IUserAccountService> (); // lastly as it is dependant m_assetGatherer = new UuidGatherer(m_assetService); }
/// <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 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); }
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, FolderType.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> /// 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> (); string filePath = "ERROR"; int successfulAssetRestores = 0; int failedAssetRestores = 0; int successfulItemRestores = 0; HashSet<InventoryNodeBase> loadedNodes = loadAll ? new HashSet<InventoryNodeBase> () : null; try { 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); if (rootFolder == null) { if (m_inventoryService.CreateUserInventory (m_userInfo.PrincipalID, true)) rootFolder = m_inventoryService.GetRootFolder (m_userInfo.PrincipalID); else { MainConsole.Instance.Error ("[Inventory Archiver]: Unable to create Inventory root folder"); return loadedNodes; // major bummer } } 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 = (short)FolderType.None; // 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) { string fName; try { fName = Path.GetFileName (filePath); if (fName.StartsWith (".", StringComparison.Ordinal)) // ignore hidden files continue; } catch { MainConsole.Instance.ErrorFormat ("[Archiver]: Invalid file name in archive: {0}", filePath); continue; } } ticker++; if (ticker % 5 == 0) MainConsole.Instance.Ticker (); if (filePath.StartsWith (ArchiveConstants.ASSETS_PATH, StringComparison.Ordinal)) { if (LoadAsset (filePath, data)) successfulAssetRestores++; else failedAssetRestores++; if ((successfulAssetRestores) % 50 == 0) MainConsole.Instance.Ticker( string.Format (" [Inventory Archiver]: Loaded {0} assets...", successfulAssetRestores),true); } else if (filePath.StartsWith (ArchiveConstants.INVENTORY_PATH, StringComparison.Ordinal)) { 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 ("/", StringComparison.Ordinal) + 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.Ticker( string.Format("[Inventory Archiver]: Restored {0} items...", successfulItemRestores), true); // 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.Ticker( string.Format ("[Inventory Archiver]: Restored {0} items of {1}...", successfulItemLoaded, itemsSavedOff.Count), true) ; } 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); } finally { m_loadStream.Close (); } return loadedNodes; }
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> /// 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; }
/// <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, StringComparison.Ordinal); 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 a folder given a PATH_DELIMITER delimited path starting from this folder /// </summary> /// This method does not handle paths that contain multiple delimiters /// /// FIXME: We have no way of distinguishing folders with the same path. /// /// FIXME: Delimiters 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; }
/// <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, StringComparison.Ordinal); 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)FolderType.None, 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, StringComparison.Ordinal); 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 OnInstantMessage(IClientAPI client, GridInstantMessage im) { //MainConsole.Instance.InfoFormat("[INVENTORY TRANSFER]: OnInstantMessage {0}", im.dialog); IScene clientScene = FindClientScene(client.AgentId); if (clientScene == null) // Something seriously wrong here. { MainConsole.Instance.DebugFormat ("[INVENTORY TRANSFER]: Cannot find originating user scene"); return; } if (im.Dialog == (byte) InstantMessageDialog.InventoryOffered) { //MainConsole.Instance.DebugFormat("Asset type {0}", ((AssetType)im.binaryBucket[0])); if (im.BinaryBucket.Length < 17) // Invalid { MainConsole.Instance.DebugFormat ("[INVENTORY TRANSFER]: Invalid length {0} for asset type {1}", im.BinaryBucket.Length, ((AssetType)im.BinaryBucket[0])); return; } UUID receipientID = im.ToAgentID; IScenePresence recipientUser = null; IScene recipientUserScene = FindClientScene(client.AgentId); if (recipientUserScene != null) recipientUser = recipientUserScene.GetScenePresence(receipientID); UUID copyID; // user is online now... if (recipientUser != null) { // First byte is the asset type AssetType assetType = (AssetType)im.BinaryBucket [0]; if (assetType == AssetType.Folder) { UUID folderID = new UUID (im.BinaryBucket, 1); MainConsole.Instance.DebugFormat ( "[INVENTORY TRANSFER]: Inserting original folder {0} into agent {1}'s inventory", folderID, im.ToAgentID); clientScene.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); // m_currencyService.UserCurrencyTransfer(im.FromAgentID, im.ToAgentID, 0, // "Inworld inventory folder transfer", TransactionType.GiveInventory, UUID.Zero); if (moneyService != null) moneyService.Transfer(im.ToAgentID, im.FromAgentID, 0, "Inworld inventory folder transfer", TransactionType.GiveInventory); if (recipientUser != null) { recipientUser.ControllingClient.SendBulkUpdateInventory (folder); im.SessionID = copyID; recipientUser.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); clientScene.InventoryService.GiveInventoryItemAsync ( im.ToAgentID, im.FromAgentID, itemID, UUID.Zero, false, (itemCopy) => { if (itemCopy == null) { MainConsole.Instance.DebugFormat ( "[INVENTORY TRANSFER]: (giving) Unable to find item {0} to give to agent {1}'s inventory", itemID, im.ToAgentID); 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 (moneyService != null) moneyService.Transfer(im.ToAgentID, im.FromAgentID, 0, "Inworld inventory item transfer", TransactionType.GiveInventory); if (recipientUser != null) { recipientUser.ControllingClient.SendBulkUpdateInventory (itemCopy); im.SessionID = itemCopy.ID; recipientUser.ControllingClient.SendInstantMessage (im); } }); } } else { // recipient is offline. // Send the IM to the recipient. The item is already // in their inventory, so it will not be lost if // they are offline. // if (m_TransferModule != null) m_TransferModule.SendInstantMessage(im); } } else if (im.Dialog == (byte) InstantMessageDialog.InventoryAccepted) { IScenePresence user = clientScene.GetScenePresence(im.ToAgentID); MainConsole.Instance.DebugFormat ("[INVENTORY TRANSFER]: Acceptance message received"); 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 = clientScene.InventoryService; MainConsole.Instance.DebugFormat ("[INVENTORY TRANSFER]: Declined message received"); InventoryFolderBase trashFolder = invService.GetFolderForType(client.AgentId, InventoryType.Unknown, FolderType.Trash); 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); } //m_currencyService.UserCurrencyTransfer(im.FromAgentID, im.ToAgentID, 0, // "Inworld inventory transfer declined", TransactionType.GiveInventory, UUID.Zero); if (moneyService != null) moneyService.Transfer(im.ToAgentID, im.FromAgentID, 0, "Inworld inventory transfer declined", TransactionType.GiveInventory); IScenePresence user = clientScene.GetScenePresence(im.ToAgentID); if (user != null) // Local { user.ControllingClient.SendInstantMessage(im); } else { if (m_TransferModule != null) m_TransferModule.SendInstantMessage(im); } } }
/// <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; }
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> /// 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 recipient 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); }); }