// Constructors public InventoryFolderImpl(InventoryFolderBase folderbase) { Owner = folderbase.Owner; ID = folderbase.ID; Name = folderbase.Name; ParentID = folderbase.ParentID; Type = folderbase.Type; Version = folderbase.Version; }
public virtual bool AddFolder(InventoryFolderBase folder) { object remoteValue = DoRemoteByURL("InventoryServerURI", folder); if (remoteValue != null || m_doRemoteOnly) return remoteValue == null ? false : (bool) remoteValue; InventoryFolderBase check = GetFolder(folder); if (check != null) return false; return m_Database.StoreFolder(folder); }
public override void FromOSD(OSDMap map) { OSDArray items = (OSDArray) map["Items"]; Items = items.ConvertAll<InventoryItemBase>((osd) => { InventoryItemBase item = new InventoryItemBase(); item.FromOSD((OSDMap) osd); return item; } ); OSDArray folders = (OSDArray) map["Folders"]; Folders = folders.ConvertAll<InventoryFolderBase>((osd) => { InventoryFolderBase folder = new InventoryFolderBase(); folder.FromOSD((OSDMap) osd); return folder; } ); UserID = map["UserID"]; FolderID = map["FolderID"]; }
public virtual InventoryFolderBase GetFolder(InventoryFolderBase folder) { object remoteValue = DoRemoteByURL("InventoryServerURI", folder); if (remoteValue != null || m_doRemoteOnly) return (InventoryFolderBase) remoteValue; List<InventoryFolderBase> folders = m_Database.GetFolders( new[] {"folderID"}, new[] {folder.ID.ToString()}); if (folders.Count == 0) return null; return folders[0]; }
/// <summary> /// Delete a scene object from a scene and place in the given avatar's inventory. /// Returns the UUID of the newly created asset. /// </summary> /// <param name="action"></param> /// <param name="folderID"></param> /// <param name="objectGroups"></param> /// <param name="agentId"></param> /// <param name="itemID"></param> public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, List<ISceneEntity> objectGroups, UUID agentId, out UUID itemID) { itemID = UUID.Zero; if (objectGroups.Count == 0) return UUID.Zero; // Get the user info of the item destination // IScenePresence SP = m_scene.GetScenePresence(agentId); UUID userID = UUID.Zero; if (action == DeRezAction.Take || action == DeRezAction.AcquireToUserInventory || action == DeRezAction.SaveToExistingUserInventoryItem) { // Take or take copy require a taker // Saving changes requires a local user // if (SP == null || SP.ControllingClient == null) return UUID.Zero; userID = agentId; } else { // All returns / deletes go to the object owner // userID = objectGroups[0].OwnerID; } if (userID == UUID.Zero) // Can't proceed { return UUID.Zero; } // If we're returning someone's item, it goes back to the // owner's Lost And Found folder. // Delete is treated like return in this case // Deleting your own items makes them go to trash // InventoryFolderBase folder = null; InventoryItemBase item = null; if (DeRezAction.SaveToExistingUserInventoryItem == action) { item = m_scene.InventoryService.GetItem(userID, objectGroups[0].RootChild.FromUserInventoryItemID); //item = userInfo.RootFolder.FindItem( // objectGroup.RootPart.FromUserInventoryItemID); if (null == item) { MainConsole.Instance.DebugFormat( "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", objectGroups[0].Name, objectGroups[0].UUID); return UUID.Zero; } } else { // Folder magic // if (action == DeRezAction.Delete) { // Deleting someone else's item // if (SP == null || SP.ControllingClient == null || objectGroups[0].OwnerID != agentId) { folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, AssetType.LostAndFoundFolder); } else { folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, AssetType.TrashFolder); } } else if (action == DeRezAction.Return) { // Dump to lost + found unconditionally // folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, AssetType.LostAndFoundFolder); } if (folderID == UUID.Zero && folder == null) { if (action == DeRezAction.Delete) { // Deletes go to trash by default // folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, AssetType.TrashFolder); } else { if (SP == null || SP.ControllingClient == null || objectGroups[0].OwnerID != agentId) { folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, AssetType.LostAndFoundFolder); } else { folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, AssetType.TrashFolder); } } } // Override and put into where it came from, if it came // from anywhere in inventory // if (action == DeRezAction.Attachment || action == DeRezAction.Take || action == DeRezAction.AcquireToUserInventory) { if (objectGroups[0].RootChild.FromUserInventoryItemID != UUID.Zero) { InventoryFolderBase f = new InventoryFolderBase(objectGroups[0].RootChild.FromUserInventoryItemID, userID); folder = m_scene.InventoryService.GetFolder(f); } else { folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Object, AssetType.Object); } } if (folder == null) // None of the above { folder = new InventoryFolderBase(folderID); } item = new InventoryItemBase { CreatorId = objectGroups[0].RootChild.CreatorID.ToString(), ID = UUID.Random(), InvType = (int) InventoryType.Object, Folder = folder.ID, Owner = userID }; } AssetBase asset; UUID assetID = SaveAsAsset(objectGroups, out asset); item.AssetID = assetID; if (DeRezAction.SaveToExistingUserInventoryItem != action) { item.Description = asset.Description; item.Name = asset.Name; item.AssetType = asset.Type; } if (DeRezAction.SaveToExistingUserInventoryItem == action) { m_scene.InventoryService.UpdateItem(item); } else { if (SP != null && SP.ControllingClient != null && (SP.ControllingClient.AgentId != objectGroups[0].OwnerID) && m_scene.Permissions.PropagatePermissions()) { foreach (ISceneEntity group in objectGroups) { uint perms = group.GetEffectivePermissions(); uint nextPerms = (perms & 7) << 13; if ((nextPerms & (uint) PermissionMask.Copy) == 0) perms &= ~(uint) PermissionMask.Copy; if ((nextPerms & (uint) PermissionMask.Transfer) == 0) perms &= ~(uint) PermissionMask.Transfer; if ((nextPerms & (uint) PermissionMask.Modify) == 0) perms &= ~(uint) PermissionMask.Modify; // Make sure all bits but the ones we want are clear // on take. // This will be applied to the current perms, so // it will do what we want. group.RootChild.NextOwnerMask &= ((uint) PermissionMask.Copy | (uint) PermissionMask.Transfer | (uint) PermissionMask.Modify); group.RootChild.NextOwnerMask |= (uint) PermissionMask.Move; item.BasePermissions = perms & group.RootChild.NextOwnerMask; item.CurrentPermissions = item.BasePermissions; item.NextPermissions = group.RootChild.NextOwnerMask; item.EveryOnePermissions = group.RootChild.EveryoneMask & group.RootChild.NextOwnerMask; item.GroupPermissions = group.RootChild.GroupMask & group.RootChild.NextOwnerMask; // Magic number badness. Maybe this deserves an enum. // bit 4 (16) is the "Slam" bit, it means treat as passed // and apply next owner perms on rez item.CurrentPermissions |= 16; // Slam! item.SalePrice = group.RootChild.SalePrice; item.SaleType = group.RootChild.ObjectSaleType; } } else { foreach (ISceneEntity group in objectGroups) { item.BasePermissions = group.GetEffectivePermissions(); item.CurrentPermissions = group.GetEffectivePermissions(); item.NextPermissions = group.RootChild.NextOwnerMask; item.EveryOnePermissions = group.RootChild.EveryoneMask; item.GroupPermissions = group.RootChild.GroupMask; item.SalePrice = group.RootChild.SalePrice; item.SaleType = group.RootChild.ObjectSaleType; item.CurrentPermissions &= ((uint) PermissionMask.Copy | (uint) PermissionMask.Transfer | (uint) PermissionMask.Modify | (uint) PermissionMask.Move | 7); // Preserve folded permissions } } if (objectGroups.Count != 1) item.Flags |= (uint) InventoryItemFlags.ObjectHasMultipleItems; item.CreationDate = Util.UnixTimeSinceEpoch(); m_LLCLientInventoryModule.AddInventoryItem(item); if (SP != null && SP.ControllingClient != null && item.Owner == SP.ControllingClient.AgentId) { SP.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } else { IScenePresence notifyUser = m_scene.GetScenePresence(item.Owner); if (notifyUser != null) { notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } } } itemID = item.ID; return assetID; }
/// <summary> /// Move the given items from the object task inventory to the agent's inventory /// </summary> /// <param name="destID"></param> /// <param name="name"></param> /// <param name="host"></param> /// <param name="items"></param> /// <returns></returns> public UUID MoveTaskInventoryItemsToUserInventory(UUID destID, string name, ISceneChildEntity host, List<UUID> items) { UUID newFolderID = UUID.Random(); Util.FireAndForget((o) => { InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(destID); InventoryFolderBase newFolder = new InventoryFolderBase(newFolderID, name, destID, -1, rootFolder.ID, rootFolder.Version); m_scene.InventoryService.AddFolder(newFolder); foreach (UUID itemID in items) { InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(destID, host, itemID); if (agentItem != null) { agentItem.Folder = newFolderID; m_scene.InventoryService.AddItem(agentItem); } } IScenePresence avatar; if (m_scene.TryGetScenePresence(destID, out avatar)) { SendInventoryUpdate(avatar.ControllingClient, rootFolder, true, false); SendInventoryUpdate(avatar.ControllingClient, newFolder, false, true); } }); return newFolderID; }
/// <summary> /// Resolve a destination folder /// </summary> /// We require here a root destination folder (usually the root of the user's inventory) and the archive /// path. We also pass in a list of previously resolved folders in case we've found this one previously. /// <param name="archivePath"> /// The item archive path to resolve. The portion of the path passed back is that /// which corresponds to the resolved desintation folder. /// </param> /// <param name="rootDestFolder"> /// The root folder for the inventory load /// </param> /// <param name="resolvedFolders"> /// The folders that we have resolved so far for a given archive path. /// </param> /// <returns> /// The folder in the user's inventory that matches best the archive path given. If no such folder was found /// then the passed in root destination folder is returned. /// </returns> protected InventoryFolderBase ResolveDestinationFolder( InventoryFolderBase rootDestFolder, ref string archivePath, ref Dictionary<string, InventoryFolderBase> resolvedFolders) { // string originalArchivePath = archivePath; while (archivePath.Length > 0) { // MainConsole.Instance.DebugFormat("[INVENTORY ARCHIVER]: Trying to resolve destination folder {0}", archivePath); if (resolvedFolders.ContainsKey(archivePath)) { // MainConsole.Instance.DebugFormat( // "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath); return resolvedFolders[archivePath]; } if (m_merge) { // TODO: Using m_invPath is totally wrong - what we need to do is strip the uuid from the // iar name and try to find that instead. string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath); List<InventoryFolderBase> folderCandidates = InventoryArchiveUtils.FindFolderByPath( m_registry.RequestModuleInterface<IInventoryService>(), m_userInfo.PrincipalID, plainPath); if (folderCandidates.Count != 0) { InventoryFolderBase destFolder = folderCandidates[0]; resolvedFolders[archivePath] = destFolder; return destFolder; } } // Don't include the last slash so find the penultimate one int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2); if (penultimateSlashIndex >= 0) { // Remove the last section of path so that we can see if we've already resolved the parent archivePath = archivePath.Remove(penultimateSlashIndex + 1); } else { // MainConsole.Instance.DebugFormat( // "[INVENTORY ARCHIVER]: Found no previously created folder for archive path {0}", // originalArchivePath); archivePath = string.Empty; return rootDestFolder; } } return rootDestFolder; }
/// <summary> /// Handle an inventory folder creation request from the client. /// </summary> /// <param name="remoteClient"></param> /// <param name="folderID"></param> /// <param name="folderType"></param> /// <param name="folderName"></param> /// <param name="parentID"></param> protected void HandleCreateInventoryFolder(IClientAPI remoteClient, UUID folderID, ushort folderType, string folderName, UUID parentID) { InventoryFolderBase folder = new InventoryFolderBase(folderID, folderName, remoteClient.AgentId, (short) folderType, parentID, 1); if (!m_scene.InventoryService.AddFolder(folder)) { MainConsole.Instance.WarnFormat( "[AGENT INVENTORY]: Failed to create folder for user {0} {1}", remoteClient.Name, remoteClient.AgentId); } }
/// <summary> /// Handle a client request to update the inventory folder /// </summary> /// FIXME: We call add new inventory folder because in the data layer, we happen to use an SQL REPLACE /// so this will work to rename an existing folder. Needless to say, to rely on this is very confusing, /// and needs to be changed. /// <param name="remoteClient"></param> /// <param name="folderID"></param> /// <param name="type"></param> /// <param name="name"></param> /// <param name="parentID"></param> protected void HandleUpdateInventoryFolder(IClientAPI remoteClient, UUID folderID, ushort type, string name, UUID parentID) { // MainConsole.Instance.DebugFormat( // "[AGENT INVENTORY]: Updating inventory folder {0} {1} for {2} {3}", folderID, name, remoteClient.Name, remoteClient.AgentId); InventoryFolderBase folder = new InventoryFolderBase(folderID, remoteClient.AgentId); folder = m_scene.InventoryService.GetFolder(folder); if (folder != null) { folder.Name = name; folder.Type = (short) type; folder.ParentID = parentID; if (!m_scene.InventoryService.UpdateFolder(folder)) { MainConsole.Instance.ErrorFormat( "[AGENT INVENTORY]: Failed to update folder for user {0} {1}", remoteClient.Name, remoteClient.AgentId); } } }
public virtual bool UpdateFolder(InventoryFolderBase folder) { object remoteValue = DoRemoteByURL("InventoryServerURI", folder); if (remoteValue != null || m_doRemoteOnly) return remoteValue == null ? false : (bool) remoteValue; if (!m_AllowDelete) //Initial item MUST be created as a link folder if (folder.Type == (sbyte) AssetType.LinkFolder) return false; InventoryFolderBase check = GetFolder(folder); if (check == null) return AddFolder(folder); if (check.Type != -1 || folder.Type != -1) { if (folder.Version > check.Version) return false; check.Version = folder.Version; check.Type = folder.Type; check.Version++; return m_Database.StoreFolder(check); } if (folder.Version < check.Version) folder.Version = check.Version; folder.ID = check.ID; folder.Version++; return m_Database.StoreFolder(folder); }
/// <summary> /// Find an item given a PATH_DELIMITOR delimited path starting from this folder. /// This method does not handle paths that contain multiple delimitors /// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some /// XPath like expression /// FIXME: Delimitors which occur in names themselves are not currently escapable. /// </summary> /// <param name="inventoryService"> /// Inventory service to query /// </param> /// <param name="startFolder"> /// The folder from which the path starts /// </param> /// <param name="path"> /// The path to the required item. /// </param> /// <returns>null if the item is not found</returns> public static InventoryItemBase FindItemByPath( IInventoryService inventoryService, InventoryFolderBase startFolder, string path) { // If the path isn't just / then trim any starting extraneous slashes path = path.TrimStart(new[] {PATH_DELIMITER}); string[] components = SplitEscapedPath(path); components[0] = UnescapePath(components[0]); //string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); if (components.Length == 1) { // MainConsole.Instance.DebugFormat( // "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}", // components[0], startFolder.Name, startFolder.ID); List<InventoryItemBase> items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID); // MainConsole.Instance.DebugFormat("[INVENTORY ARCHIVE UTILS]: Found {0} items in FindItemByPath()", items.Count); return items.FirstOrDefault(item => item.Name == components[0]); } else { // MainConsole.Instance.DebugFormat("FOUND COMPONENTS [{0}] and [{1}]", components[0], components[1]); InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); return (from folder in contents.Folders where folder.Name == components[0] select FindItemByPath(inventoryService, folder, components[1])).FirstOrDefault(); } }
public virtual bool MoveFolder(InventoryFolderBase folder) { object remoteValue = DoRemoteByURL("InventoryServerURI", folder); if (remoteValue != null || m_doRemoteOnly) return remoteValue == null ? false : (bool) remoteValue; List<InventoryFolderBase> x = m_Database.GetFolders( new[] {"folderID"}, new[] {folder.ID.ToString()}); if (x.Count == 0) return false; x[0].ParentID = folder.ParentID; return m_Database.StoreFolder(x[0]); }
public virtual bool PurgeFolder(InventoryFolderBase folder) { object remoteValue = DoRemoteByURL("InventoryServerURI", folder); if (remoteValue != null || m_doRemoteOnly) return remoteValue == null ? false : (bool) remoteValue; if (!m_AllowDelete && !ParentIsLinkFolder(folder.ID)) return false; if (!ParentIsTrash(folder.ID)) return false; List<InventoryFolderBase> subFolders = m_Database.GetFolders( new[] {"parentFolderID"}, new[] {folder.ID.ToString()}); foreach (InventoryFolderBase x in subFolders) { PurgeFolder(x); m_Database.DeleteFolders("folderID", x.ID.ToString(), true); } m_Database.DeleteItems("parentFolderID", folder.ID.ToString()); return true; }
/// <summary> /// Give an entire inventory folder from one user to another. The entire contents (including all descendent /// folders) is given. /// </summary> /// <param name="recipientId"></param> /// <param name="senderId">ID of the sender of the item</param> /// <param name="folderId"></param> /// <param name="recipientParentFolderId"> /// The id of the receipient folder in which the send folder should be placed. If UUID.Zero then the /// recipient folder is the root folder /// </param> /// <param name="success"></param> /// <returns> /// The inventory folder copy given, null if the copy was unsuccessful /// </returns> public void GiveInventoryFolderAsync( UUID recipientId, UUID senderId, UUID folderId, UUID recipientParentFolderId, GiveFolderParam success) { Util.FireAndForget(o => { // Retrieve the folder from the sender InventoryFolderBase folder = GetFolder(new InventoryFolderBase(folderId)); if (null == folder) { MainConsole.Instance.ErrorFormat( "[InventoryService]: Could not find inventory folder {0} to give", folderId); success(null); return; } //Find the folder for the receiver if (recipientParentFolderId == UUID.Zero) { InventoryFolderBase recipientRootFolder = GetRootFolder(recipientId); if (recipientRootFolder != null) recipientParentFolderId = recipientRootFolder.ID; else { MainConsole.Instance.WarnFormat( "[InventoryService]: Unable to find root folder for receiving agent"); success(null); return; } } UUID newFolderId = UUID.Random(); InventoryFolderBase newFolder = new InventoryFolderBase( newFolderId, folder.Name, recipientId, folder.Type, recipientParentFolderId, folder.Version); AddFolder(newFolder); // Give all the subfolders InventoryCollection contents = GetFolderContent(senderId, folderId); foreach (InventoryFolderBase childFolder in contents.Folders) { GiveInventoryFolderAsync(recipientId, senderId, childFolder.ID, newFolder.ID, null); } // Give all the items foreach (InventoryItemBase item in contents.Items) { InnerGiveInventoryItem(recipientId, senderId, item, newFolder.ID, true, true); } success(newFolder); }); }
public AvatarAppearance WearFolder(AvatarAppearance avappearance, UUID user, UUID folderOwnerID) { InventoryFolderBase Folder2Wear = m_InventoryService.GetFolderByOwnerAndName(folderOwnerID, m_forceUserToWearFolderName); if (Folder2Wear != null) { List<InventoryItemBase> itemsInFolder = m_InventoryService.GetFolderItems(UUID.Zero, Folder2Wear.ID); InventoryFolderBase appearanceFolder = m_InventoryService.GetFolderForType(user, InventoryType.Wearable, AssetType.Clothing); InventoryFolderBase folderForAppearance = new InventoryFolderBase(UUID.Random(), "GridWear", user, -1, appearanceFolder.ID, 1); List<InventoryFolderBase> userFolders = m_InventoryService.GetFolderFolders(user, appearanceFolder.ID); bool alreadyThere = false; List<UUID> items2RemoveFromAppearence = new List<UUID>(); List<UUID> toDelete = new List<UUID>(); foreach (InventoryFolderBase folder in userFolders) { if (folder.Name == folderForAppearance.Name) { List<InventoryItemBase> itemsInCurrentFolder = m_InventoryService.GetFolderItems(UUID.Zero, folder.ID); foreach (InventoryItemBase itemBase in itemsInCurrentFolder) { items2RemoveFromAppearence.Add(itemBase.AssetID); items2RemoveFromAppearence.Add(itemBase.ID); toDelete.Add(itemBase.ID); } folderForAppearance = folder; alreadyThere = true; m_InventoryService.DeleteItems(user, toDelete); break; } } if (!alreadyThere) m_InventoryService.AddFolder(folderForAppearance); else { // we have to remove all the old items if they are currently wearing them for (int i = 0; i < avappearance.Wearables.Length; i++) { AvatarWearable wearable = avappearance.Wearables[i]; for (int ii = 0; ii < wearable.Count; ii++) { if (items2RemoveFromAppearence.Contains(wearable[ii].ItemID)) { avappearance.Wearables[i] = AvatarWearable.DefaultWearables[i]; break; } } } List<AvatarAttachment> attachments = avappearance.GetAttachments(); foreach (AvatarAttachment attachment in attachments) { if ((items2RemoveFromAppearence.Contains(attachment.AssetID)) || (items2RemoveFromAppearence.Contains(attachment.ItemID))) { avappearance.DetachAttachment(attachment.ItemID); } } } // ok, now we have a empty folder, lets add the items foreach (InventoryItemBase itemBase in itemsInFolder) { InventoryItemBase newcopy = m_InventoryService.InnerGiveInventoryItem(user, folderOwnerID, itemBase, folderForAppearance.ID, true, true); if (newcopy.InvType == (int) InventoryType.Object) { byte[] attobj = m_AssetService.GetData(newcopy.AssetID.ToString()); if (attobj != null) { string xmlData = Utils.BytesToString(attobj); XmlDocument doc = new XmlDocument(); try { doc.LoadXml(xmlData); } catch { continue; } if (doc.FirstChild.OuterXml.StartsWith("<groups>") || (doc.FirstChild.NextSibling != null && doc.FirstChild.NextSibling.OuterXml.StartsWith("<groups>"))) continue; string xml = ""; if ((doc.FirstChild.NodeType == XmlNodeType.XmlDeclaration) && (doc.FirstChild.NextSibling != null)) xml = doc.FirstChild.NextSibling.OuterXml; else xml = doc.FirstChild.OuterXml; doc.LoadXml(xml); if (doc.DocumentElement == null) continue; XmlNodeList xmlNodeList = doc.DocumentElement.SelectNodes("//State"); int attchspot; if ((xmlNodeList != null) && (int.TryParse(xmlNodeList[0].InnerText, out attchspot))) { AvatarAttachment a = new AvatarAttachment(attchspot, newcopy.ID, newcopy.AssetID); Dictionary<int, List<AvatarAttachment>> ac = avappearance.Attachments; if (!ac.ContainsKey(attchspot)) ac[attchspot] = new List<AvatarAttachment>(); ac[attchspot].Add(a); avappearance.Attachments = ac; } } } m_InventoryService.AddItem(newcopy); } } return avappearance; }
private void OnInstantMessage(IClientAPI client, GridInstantMessage im) { //MainConsole.Instance.InfoFormat("[INVENTORY TRANSFER]: OnInstantMessage {0}", im.dialog); if (im.Dialog == (byte) InstantMessageDialog.InventoryOffered) { //MainConsole.Instance.DebugFormat("Asset type {0}", ((AssetType)im.binaryBucket[0])); if (im.BinaryBucket.Length < 17) // Invalid return; UUID receipientID = im.ToAgentID; IScenePresence user = m_Scene.GetScenePresence(receipientID); UUID copyID; // Send the IM to the recipient. The item is already // in their inventory, so it will not be lost if // they are offline. // if (user != null) { // First byte is the asset type AssetType assetType = (AssetType) im.BinaryBucket[0]; if (AssetType.Folder == assetType) { UUID folderID = new UUID(im.BinaryBucket, 1); MainConsole.Instance.DebugFormat("[INVENTORY TRANSFER]: Inserting original folder {0} " + "into agent {1}'s inventory", folderID, im.ToAgentID); m_Scene.InventoryService.GiveInventoryFolderAsync(receipientID, client.AgentId, folderID, UUID.Zero, (folder) => { if (folder == null) { client .SendAgentAlertMessage ("Can't find folder to give. Nothing given.", false); return; } // The outgoing binary bucket should contain only the byte which signals an asset folder is // being copied and the following bytes for the copied folder's UUID copyID = folder.ID; byte[] copyIDBytes = copyID .GetBytes (); im.BinaryBucket = new byte[ 1 + copyIDBytes .Length ]; im.BinaryBucket[0 ] = (byte) AssetType .Folder; Array.Copy( copyIDBytes, 0, im .BinaryBucket, 1, copyIDBytes .Length); if (user != null) user .ControllingClient .SendBulkUpdateInventory (folder); im.SessionID = copyID; user .ControllingClient .SendInstantMessage (im); }); } else { // First byte of the array is probably the item type // Next 16 bytes are the UUID UUID itemID = new UUID(im.BinaryBucket, 1); MainConsole.Instance.DebugFormat("[INVENTORY TRANSFER]: (giving) Inserting item {0} " + "into agent {1}'s inventory", itemID, im.ToAgentID); m_Scene.InventoryService.GiveInventoryItemAsync( im.ToAgentID, im.FromAgentID, itemID, UUID.Zero, false, (itemCopy) => { if (itemCopy == null) { client.SendAgentAlertMessage( "Can't find item to give. Nothing given.", false); return; } copyID = itemCopy.ID; Array.Copy(copyID.GetBytes(), 0, im.BinaryBucket, 1, 16); if (user != null) { user.ControllingClient .SendBulkUpdateInventory(itemCopy); } im.SessionID = itemCopy.ID; user.ControllingClient.SendInstantMessage( im); }); } } else { if (m_TransferModule != null) m_TransferModule.SendInstantMessage(im); } } else if (im.Dialog == (byte) InstantMessageDialog.InventoryAccepted) { IScenePresence user = m_Scene.GetScenePresence(im.ToAgentID); if (user != null) // Local { user.ControllingClient.SendInstantMessage(im); } else { if (m_TransferModule != null) m_TransferModule.SendInstantMessage(im); } } else if (im.Dialog == (byte) InstantMessageDialog.InventoryDeclined) { // Here, the recipient is local and we can assume that the // inventory is loaded. Courtesy of the above bulk update, // It will have been pushed to the client, too // IInventoryService invService = m_Scene.InventoryService; InventoryFolderBase trashFolder = invService.GetFolderForType(client.AgentId, InventoryType.Unknown, AssetType.TrashFolder); UUID inventoryID = im.SessionID; // The inventory item/folder, back from it's trip InventoryItemBase item = invService.GetItem(client.AgentId, inventoryID); InventoryFolderBase folder = null; if (item != null && trashFolder != null) { item.Folder = trashFolder.ID; // Diva comment: can't we just update this item??? List<UUID> uuids = new List<UUID> {item.ID}; invService.DeleteItems(item.Owner, uuids); ILLClientInventory inventory = client.Scene.RequestModuleInterface<ILLClientInventory>(); if (inventory != null) inventory.AddInventoryItemAsync(client, item); } else { folder = new InventoryFolderBase(inventoryID, client.AgentId); folder = invService.GetFolder(folder); if (folder != null & trashFolder != null) { folder.ParentID = trashFolder.ID; invService.MoveFolder(folder); client.SendBulkUpdateInventory(folder); } } if ((null == item && null == folder) | null == trashFolder) { string reason = String.Empty; if (trashFolder == null) reason += " Trash folder not found."; if (item == null) reason += " Item not found."; if (folder == null) reason += " Folder not found."; client.SendAgentAlertMessage("Unable to delete " + "received inventory" + reason, false); } IScenePresence user = m_Scene.GetScenePresence(im.ToAgentID); if (user != null) // Local { user.ControllingClient.SendInstantMessage(im); } else { if (m_TransferModule != null) m_TransferModule.SendInstantMessage(im); } } }
public byte[] CreateInventoryCategory(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { OSDMap map = (OSDMap) OSDParser.DeserializeLLSDXml(HttpServerHandlerHelpers.ReadFully(request)); UUID folder_id = map["folder_id"].AsUUID(); UUID parent_id = map["parent_id"].AsUUID(); int type = map["type"].AsInteger(); string name = map["name"].AsString(); InventoryFolderBase newFolder = new InventoryFolderBase( folder_id, name, m_agentID, (short)type, parent_id, 1); m_inventoryService.AddFolder(newFolder); OSDMap resp = new OSDMap(); resp["folder_id"] = folder_id; resp["parent_id"] = parent_id; resp["type"] = type; resp["name"] = name; return OSDParser.SerializeLLSDXmlBytes(map); }
protected InventoryFolderBase CreateFolder(UUID principalID, UUID parentID, int type, string name) { InventoryFolderBase newFolder = new InventoryFolderBase { Name = name, Type = (short) type, Version = 1, ID = UUID.Random(), Owner = principalID, ParentID = parentID }; m_Database.StoreFolder(newFolder); return newFolder; }
/// <summary> /// Find a folder given a PATH_DELIMITER delimited path starting from this folder /// </summary> /// This method does not handle paths that contain multiple delimitors /// /// FIXME: We have no way of distinguishing folders with the same path. /// /// FIXME: Delimitors which occur in names themselves are not currently escapable. /// <param name="inventoryService"> /// Inventory service to query /// </param> /// <param name="startFolder"> /// The folder from which the path starts /// </param> /// <param name="path"> /// The path to the required folder. /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. /// </param> /// <returns>An empty list if the folder is not found, otherwise a list of all folders that match the name</returns> public static List<InventoryFolderBase> FindFolderByPath( IInventoryService inventoryService, InventoryFolderBase startFolder, string path) { List<InventoryFolderBase> foundFolders = new List<InventoryFolderBase>(); if (path == string.Empty) { foundFolders.Add(startFolder); return foundFolders; } path = path.Trim(); if (path == PATH_DELIMITER.ToString()) { foundFolders.Add(startFolder); return foundFolders; } // If the path isn't just / then trim any starting extraneous slashes path = path.TrimStart(new[] {PATH_DELIMITER}); // MainConsole.Instance.DebugFormat("[INVENTORY ARCHIVE UTILS]: Adjusted path in FindFolderByPath() is [{0}]", path); string[] components = SplitEscapedPath(path); components[0] = UnescapePath(components[0]); //string[] components = path.Split(new string[] { PATH_DELIMITER.ToString() }, 2, StringSplitOptions.None); InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); foreach (InventoryFolderBase folder in contents.Folders.Where(folder => folder.Name == components[0])) { if (components.Length > 1) foundFolders.AddRange(FindFolderByPath(inventoryService, folder, components[1])); else foundFolders.Add(folder); } return foundFolders; }
public virtual bool DeleteFolders(UUID principalID, List<UUID> folderIDs) { object remoteValue = DoRemoteByURL("InventoryServerURI", principalID, folderIDs); if (remoteValue != null || m_doRemoteOnly) return remoteValue == null ? false : (bool) remoteValue; if (!m_AllowDelete) { foreach (UUID id in folderIDs) { if (!ParentIsLinkFolder(id)) continue; InventoryFolderBase f = new InventoryFolderBase {ID = id}; PurgeFolder(f); m_Database.DeleteFolders("folderID", id.ToString(), true); } return true; } // Ignore principal ID, it's bogus at connector level // foreach (UUID id in folderIDs) { if (!ParentIsTrash(id)) continue; InventoryFolderBase f = new InventoryFolderBase {ID = id}; PurgeFolder(f); m_Database.DeleteFolders("folderID", id.ToString(), true); } return true; }
/// <summary> /// Create a set of folders for the given path. /// </summary> /// <param name="destFolder"> /// The root folder from which the creation will take place. /// </param> /// <param name="iarPathExisting"> /// the part of the iar path that already exists /// </param> /// <param name="iarPathToReplicate"> /// The path to replicate in the user's inventory from iar /// </param> /// <param name="resolvedFolders"> /// The folders that we have resolved so far for a given archive path. /// </param> /// <param name="loadedNodes"> /// Track the inventory nodes created. /// </param> protected void CreateFoldersForPath( InventoryFolderBase destFolder, string iarPathExisting, string iarPathToReplicate, ref Dictionary<string, InventoryFolderBase> resolvedFolders, ref HashSet<InventoryNodeBase> loadedNodes) { string[] rawDirsToCreate = iarPathToReplicate.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < rawDirsToCreate.Length; i++) { // MainConsole.Instance.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0} from IAR", rawDirsToCreate[i]); if (!rawDirsToCreate[i].Contains(ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR)) continue; int identicalNameIdentifierIndex = rawDirsToCreate[i].LastIndexOf( ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR); string newFolderName = rawDirsToCreate[i].Remove(identicalNameIdentifierIndex); newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName); UUID newFolderId = UUID.Random(); // Asset type has to be Unknown here rather than Folder, otherwise the created folder can't be // deleted once the client has relogged. // The root folder appears to be labelled AssetType.Folder (shows up as "Category" in the client) // even though there is a AssetType.RootCategory destFolder = new InventoryFolderBase( newFolderId, newFolderName, m_userInfo.PrincipalID, (short) AssetType.Unknown, destFolder.ID, 1); m_registry.RequestModuleInterface<IInventoryService>().AddFolder(destFolder); // Record that we have now created this folder iarPathExisting += rawDirsToCreate[i] + "/"; MainConsole.Instance.DebugFormat("[INVENTORY ARCHIVER]: Created folder {0} from IAR", iarPathExisting); resolvedFolders[iarPathExisting] = destFolder; if (0 == i && loadedNodes != null) loadedNodes.Add(destFolder); } }
public virtual void FixInventory(IScene scene, string[] cmd) { string userName = MainConsole.Instance.Prompt("Name of user"); UserAccount account = m_UserAccountService.GetUserAccount(null, userName); if (account == null) { MainConsole.Instance.Warn("Could not find user"); return; } InventoryFolderBase rootFolder = GetRootFolder(account.PrincipalID); //Fix having a default root folder if (rootFolder == null) { MainConsole.Instance.Warn("Fixing default root folder..."); List<InventoryFolderBase> skel = GetInventorySkeleton(account.PrincipalID); if (skel.Count == 0) { CreateUserInventory(account.PrincipalID, false); rootFolder = GetRootFolder(account.PrincipalID); } else { rootFolder = new InventoryFolderBase { Name = "My Inventory", Type = (short) AssetType.RootFolder, Version = 1, ID = skel[0].ParentID, Owner = account.PrincipalID, ParentID = UUID.Zero }; } } //Check against multiple root folders List<InventoryFolderBase> rootFolders = GetRootFolders(account.PrincipalID); List<UUID> badFolders = new List<UUID>(); if (rootFolders.Count != 1) { //No duplicate folders! foreach ( InventoryFolderBase f in rootFolders.Where(f => !badFolders.Contains(f.ID) && f.ID != rootFolder.ID) ) { MainConsole.Instance.Warn("Removing duplicate root folder " + f.Name); badFolders.Add(f.ID); } } //Fix any root folders that shouldn't be root folders List<InventoryFolderBase> skeleton = GetInventorySkeleton(account.PrincipalID); List<UUID> foundFolders = new List<UUID>(); foreach (InventoryFolderBase f in skeleton) { if (!foundFolders.Contains(f.ID)) foundFolders.Add(f.ID); if (f.Name == "My Inventory" && f.ParentID != UUID.Zero) { //Merge them all together badFolders.Add(f.ID); } } foreach (InventoryFolderBase f in skeleton) { if ((!foundFolders.Contains(f.ParentID) && f.ParentID != UUID.Zero) || f.ID == f.ParentID) { //The viewer loses the parentID when something goes wrong //it puts it in the top where My Inventory should be //We need to put it back in the My Inventory folder, as the sub folders are right for some reason f.ParentID = rootFolder.ID; m_Database.StoreFolder(f); MainConsole.Instance.WarnFormat("Fixing folder {0}", f.Name); } else if (badFolders.Contains(f.ParentID)) { //Put it back in the My Inventory folder f.ParentID = rootFolder.ID; m_Database.StoreFolder(f); MainConsole.Instance.WarnFormat("Fixing folder {0}", f.Name); } else if (f.Type == (short) AssetType.CurrentOutfitFolder) { List<InventoryItemBase> items = GetFolderItems(account.PrincipalID, f.ID); //Check the links! List<UUID> brokenLinks = new List<UUID>(); foreach (InventoryItemBase item in items) { InventoryItemBase linkedItem = null; if ((linkedItem = GetItem(account.PrincipalID, item.AssetID)) == null) { //Broken link... brokenLinks.Add(item.ID); } else if (linkedItem.ID == AvatarWearable.DEFAULT_EYES_ITEM || linkedItem.ID == AvatarWearable.DEFAULT_BODY_ITEM || linkedItem.ID == AvatarWearable.DEFAULT_HAIR_ITEM || linkedItem.ID == AvatarWearable.DEFAULT_PANTS_ITEM || linkedItem.ID == AvatarWearable.DEFAULT_SHIRT_ITEM || linkedItem.ID == AvatarWearable.DEFAULT_SKIN_ITEM) { //Default item link, needs removed brokenLinks.Add(item.ID); } } if (brokenLinks.Count != 0) DeleteItems(account.PrincipalID, brokenLinks); } else if (f.Type == (short) AssetType.Mesh) { ForcePurgeFolder(f); } } foreach (UUID id in badFolders) { m_Database.DeleteFolders("folderID", id.ToString(), false); } //Make sure that all default folders exist CreateUserInventory(account.PrincipalID, false); //Refetch the skeleton now skeleton = GetInventorySkeleton(account.PrincipalID); Dictionary<int, UUID> defaultFolders = new Dictionary<int, UUID>(); Dictionary<UUID, UUID> changedFolders = new Dictionary<UUID, UUID>(); foreach (InventoryFolderBase folder in skeleton.Where(folder => folder.Type != -1)) { if (!defaultFolders.ContainsKey(folder.Type)) defaultFolders[folder.Type] = folder.ID; else changedFolders.Add(folder.ID, defaultFolders[folder.Type]); } foreach (InventoryFolderBase folder in skeleton) { if (folder.Type != -1 && defaultFolders[folder.Type] != folder.ID) { //Delete the dup ForcePurgeFolder(folder); MainConsole.Instance.Warn("Purging duplicate default inventory type folder " + folder.Name); } if (changedFolders.ContainsKey(folder.ParentID)) { folder.ParentID = changedFolders[folder.ParentID]; MainConsole.Instance.Warn("Merging child folder of default inventory type " + folder.Name); m_Database.StoreFolder(folder); } } MainConsole.Instance.Warn("Completed the check"); }
/// <summary> /// Move the inventory folder to another place in the user's inventory /// </summary> /// <param name="remoteClient">The client that requested the change</param> /// <param name="folderID">The folder UUID to move</param> /// <param name="parentID">The folder to move the folder (folderID) into</param> protected void HandleMoveInventoryFolder(IClientAPI remoteClient, UUID folderID, UUID parentID) { InventoryFolderBase folder = new InventoryFolderBase(folderID, remoteClient.AgentId); folder = m_scene.InventoryService.GetFolder(folder); if (folder != null) { folder.ParentID = parentID; if (!m_scene.InventoryService.MoveFolder(folder)) MainConsole.Instance.WarnFormat("[AGENT INVENTORY]: could not move folder {0}", folderID); else MainConsole.Instance.DebugFormat("[AGENT INVENTORY]: folder {0} moved to parent {1}", folderID, parentID); } else { MainConsole.Instance.WarnFormat("[AGENT INVENTORY]: request to move folder {0} but folder not found", folderID); } }
public virtual bool StoreFolder(InventoryFolderBase folder) { QueryFilter filter = new QueryFilter(); filter.andFilters["folderID"] = folder.ID; GD.Delete(m_foldersrealm, filter); Dictionary<string, object> row = new Dictionary<string, object>(6); row["folderName"] = folder.Name; row["type"] = folder.Type; row["version"] = folder.Version; row["folderID"] = folder.ID; row["agentID"] = folder.Owner; row["parentFolderID"] = folder.ParentID; return GD.Insert(m_foldersrealm, row); }
/// <summary> /// Send an update to the client about the given folder /// </summary> /// <param name="client">The client to send the update to</param> /// <param name="folder">The folder that we need to send</param> /// <param name="fetchFolders">Should we fetch folders inside of this folder</param> /// <param name="fetchItems">Should we fetch items inside of this folder</param> protected void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems) { if (folder == null) return; // Fetch the folder contents InventoryCollection contents = m_scene.InventoryService.GetFolderContent(client.AgentId, folder.ID); // Fetch the folder itself to get its current version InventoryFolderBase containingFolder = new InventoryFolderBase(folder.ID, client.AgentId); containingFolder = m_scene.InventoryService.GetFolder(containingFolder); //MainConsole.Instance.DebugFormat("[AGENT INVENTORY]: Sending inventory folder contents ({0} nodes) for \"{1}\" to {2} {3}", // contents.Folders.Count + contents.Items.Count, containingFolder.Name, client.FirstName, client.LastName); if (containingFolder != null) client.SendInventoryFolderDetails(client.AgentId, folder.ID, contents.Items, contents.Folders, containingFolder.Version, fetchFolders, fetchItems); }
/// <summary> /// Replicate the inventory paths in the archive to the user's inventory as necessary. /// </summary> /// <param name="iarPath">The item archive path to replicate</param> /// <param name="rootDestFolder">The root folder for the inventory load</param> /// <param name="resolvedFolders"> /// The folders that we have resolved so far for a given archive path. /// This method will add more folders if necessary /// </param> /// <param name="loadedNodes"> /// Track the inventory nodes created. /// </param> /// <returns>The last user inventory folder created or found for the archive path</returns> public InventoryFolderBase ReplicateArchivePathToUserInventory( string iarPath, InventoryFolderBase rootDestFolder, ref Dictionary<string, InventoryFolderBase> resolvedFolders, ref HashSet<InventoryNodeBase> loadedNodes) { string iarPathExisting = iarPath; // MainConsole.Instance.DebugFormat( // "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID); InventoryFolderBase destFolder = ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, ref resolvedFolders); // MainConsole.Instance.DebugFormat( // "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]", // iarPath, iarPathExisting); string iarPathToCreate = iarPath.Substring(iarPathExisting.Length); CreateFoldersForPath(destFolder, iarPathExisting, iarPathToCreate, ref resolvedFolders, ref loadedNodes); return destFolder; }
//[CanBeReflected(ThreatLevel = ThreatLevel.Full)] public virtual bool ForcePurgeFolder(InventoryFolderBase folder) { /*object remoteValue = DoRemoteByURL("InventoryServerURI", folder); if (remoteValue != null || m_doRemoteOnly) return remoteValue == null ? false : (bool)remoteValue;*/ List<InventoryFolderBase> subFolders = m_Database.GetFolders( new[] {"parentFolderID"}, new[] {folder.ID.ToString()}); foreach (InventoryFolderBase x in subFolders) { ForcePurgeFolder(x); m_Database.DeleteFolders("folderID", x.ID.ToString(), false); } m_Database.DeleteItems("parentFolderID", folder.ID.ToString()); m_Database.DeleteFolders("folderID", folder.ID.ToString(), false); return true; }
/// <summary> /// Load an item from the archive /// </summary> /// <param name="data">The raw item data</param> /// <param name="loadFolder"> </param> protected InventoryItemBase LoadItem(byte[] data, InventoryFolderBase loadFolder) { InventoryItemBase item = UserInventoryItemSerializer.Deserialize(data); // Don't use the item ID that's in the file item.ID = UUID.Random(); UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_registry.RequestModuleInterface<IUserAccountService>()); if (UUID.Zero != ospResolvedId) { item.CreatorIdAsUuid = ospResolvedId; // Don't preserve the OSPA in the creator id (which actually gets persisted to the // database). Instead, replace with the UUID that we found. item.CreatorId = ospResolvedId.ToString(); item.CreatorData = string.Empty; } else if (string.IsNullOrEmpty(item.CreatorData)) { item.CreatorId = m_userInfo.PrincipalID.ToString(); item.CreatorIdAsUuid = new UUID(item.CreatorId); } item.Owner = m_userInfo.PrincipalID; // Record the creator id for the item's asset so that we can use it later, if necessary, when the asset // is loaded. // FIXME: This relies on the items coming before the assets in the TAR file. Need to create stronger // checks for this, and maybe even an external tool for creating OARs which enforces this, rather than // relying on native tar tools. m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid; // Reset folder ID to the one in which we want to load it item.Folder = loadFolder.ID; itemsSavedOff.Add(item); return item; }
private List<InventoryFolderBase> ParseInventoryFolders(ref Dictionary<string, List<string>> retVal) { List<InventoryFolderBase> folders = new List<InventoryFolderBase>(); if (retVal.Count == 0) return folders; for (int i = 0; i < retVal.ElementAt(0).Value.Count; i++) { InventoryFolderBase folder = new InventoryFolderBase { Name = retVal["folderName"][i], Type = short.Parse(retVal["type"][i]), Version = (ushort) int.Parse(retVal["version"][i]), ID = UUID.Parse(retVal["folderID"][i]), Owner = UUID.Parse(retVal["agentID"][i]), ParentID = UUID.Parse(retVal["parentFolderID"][i]) }; folders.Add(folder); } //retVal.Clear(); return folders; }
/// <summary> /// Save an inventory folder /// </summary> /// <param name="inventoryFolder">The inventory folder to save</param> /// <param name="path">The path to which the folder should be saved</param> /// <param name="saveThisFolderItself">If true, save this folder itself. If false, only saves contents</param> protected void SaveInvFolder(InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself) { if (saveThisFolderItself) { path += CreateArchiveFolderName(inventoryFolder); // We need to make sure that we record empty folders m_archiveWriter.WriteDir(path); } InventoryCollection contents = m_registry.RequestModuleInterface<IInventoryService>().GetFolderContent(inventoryFolder.Owner, inventoryFolder.ID); foreach (InventoryFolderBase childFolder in contents.Folders) { SaveInvFolder(childFolder, path, true); } foreach (InventoryItemBase item in contents.Items) { SaveInvItem(item, path); } }