From b6a02269f77b0086804a90e3509a7f14be92ced3 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 28 Apr 2020 13:48:49 +0100 Subject: [PATCH] change update of agent or object inventory items assets. This may need better check --- .../Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 120 ++++++++++++------ .../InventoryAccess/InventoryAccessModule.cs | 109 ++++++++++++---- .../World/WorldMap/WorldMapModule.cs | 3 +- .../Framework/Scenes/Scene.Inventory.cs | 101 +++++++++++++-- 4 files changed, 255 insertions(+), 78 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index 03521a065e..05a98762f4 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -65,7 +65,7 @@ namespace OpenSim.Region.ClientStack.Linden int cost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances, bool IsAtestUpload, ref string error, ref int nextOwnerMask, ref int groupMask, ref int everyoneMask, int[] meshesSides); - public delegate UUID UpdateItem(UUID itemID, byte[] data); + public delegate UUID UpdateItem(UUID itemID, UUID objectID, byte[] data); public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors); @@ -73,14 +73,11 @@ namespace OpenSim.Region.ClientStack.Linden public delegate void NewAsset(AssetBase asset); - public delegate UUID ItemUpdatedCallback(UUID userID, UUID itemID, byte[] data); + public delegate UUID ItemUpdatedCallback(UUID userID, UUID itemID, UUID objectID, byte[] data); public delegate ArrayList TaskScriptUpdatedCallback(UUID userID, UUID itemID, UUID primID, bool isScriptRunning, byte[] data); - public delegate InventoryCollection FetchInventoryDescendentsCAPS(UUID agentID, UUID folderID, UUID ownerID, - bool fetchFolders, bool fetchItems, int sortOrder, out int version); - /// /// XXX Probably not a particularly nice way of allow us to get the scene presence from the scene (chiefly so that /// we can popup a message on the user's client if the inventory service has permanently failed). But I didn't want @@ -107,7 +104,6 @@ namespace OpenSim.Region.ClientStack.Linden public NewAsset AddNewAsset = null; public ItemUpdatedCallback ItemUpdatedCall = null; public TaskScriptUpdatedCallback TaskScriptUpdatedCall = null; - public FetchInventoryDescendentsCAPS CAPSFetchInventoryDescendents = null; public GetClientDelegate GetClient = null; private bool m_persistBakedTextures = false; @@ -227,7 +223,7 @@ namespace OpenSim.Region.ClientStack.Linden RegisterHandlers(); AddNewInventoryItem = m_Scene.AddUploadedInventoryItem; - ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset; + ItemUpdatedCall = m_Scene.CapsUpdateItemAsset; TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset; GetClient = m_Scene.SceneGraph.GetControllingClient; @@ -313,11 +309,17 @@ namespace OpenSim.Region.ClientStack.Linden "POST", GetNewCapPath(), NewAgentInventoryRequest, "NewFileAgentInventory", null)); IRequestHandler req = new RestStreamHandler( - "POST", GetNewCapPath(), NoteCardAgentInventory, "Update*", null); + "POST", GetNewCapPath(), UpdateInventoryItemAsset, "Update*", null); + m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req); + m_HostCapsObj.RegisterHandler("UpdateNotecardTaskInventory", req); // a object inv m_HostCapsObj.RegisterHandler("UpdateAnimSetAgentInventory", req); m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req); m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req); + m_HostCapsObj.RegisterHandler("UpdateSettingsAgentInventory", req); + m_HostCapsObj.RegisterHandler("UpdateSettingsTaskInventory", req); // a object inv + m_HostCapsObj.RegisterHandler("UpdateGestureAgentInventory", req); + m_HostCapsObj.RegisterHandler("UpdateGestureTaskInventory", req); m_HostCapsObj.RegisterSimpleHandler("UpdateAgentInformation", new SimpleStreamHandler(GetNewCapPath(), UpdateAgentInformation)); @@ -499,11 +501,11 @@ namespace OpenSim.Region.ClientStack.Linden /// Item to update /// New asset data /// - public UUID ItemUpdated(UUID itemID, byte[] data) + public UUID ItemUpdated(UUID itemID, UUID objectID, byte[] data) { if (ItemUpdatedCall != null) { - return ItemUpdatedCall(m_HostCapsObj.AgentID, itemID, data); + return ItemUpdatedCall(m_HostCapsObj.AgentID, itemID, objectID, data); } return UUID.Zero; @@ -1364,31 +1366,66 @@ namespace OpenSim.Region.ClientStack.Linden /// /// /// - public string NoteCardAgentInventory(string request, string path, string param, + public string UpdateInventoryItemAsset(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - //m_log.Debug("[CAPS]: NoteCardAgentInventory Request in region: " + m_regionName + "\n" + request); - //m_log.Debug("[CAPS]: NoteCardAgentInventory Request is: " + request); + m_log.Debug("[CAPS]: UpdateInventoryItemAsset Request in region: " + m_regionName + "\n" + request); - //OpenMetaverse.StructuredData.OSDMap hash = (OpenMetaverse.StructuredData.OSDMap)OpenMetaverse.StructuredData.LLSDParser.DeserializeBinary(Utils.StringToBytes(request)); - Hashtable hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); - LLSDItemUpdate llsdRequest = new LLSDItemUpdate(); - LLSDHelpers.DeserialiseOSDMap(hash, llsdRequest); + UUID itemID = UUID.Zero; + UUID objectID = UUID.Zero; + + try + { + OSD oreq = OSDParser.DeserializeLLSDXml(request); + if(oreq is OSDMap) + { + OSDMap map = oreq as OSDMap; + if (map.TryGetValue("item_id", out OSD itmp)) + itemID = itmp; + if (map.TryGetValue("task_id", out OSD tmp)) + objectID = tmp; + } + } + catch { } + + if(itemID == UUID.Zero) + { + LLSDAssetUploadError error = new LLSDAssetUploadError(); + error.message = "failed to recode request"; + error.identifier = UUID.Zero; + return LLSDHelpers.SerialiseLLSDReply(error); + } + + if (objectID != UUID.Zero) + { + SceneObjectPart sop = m_Scene.GetSceneObjectPart(objectID); + if (sop == null) + { + LLSDAssetUploadError error = new LLSDAssetUploadError(); + error.message = "object not found"; + error.identifier = UUID.Zero; + return LLSDHelpers.SerialiseLLSDReply(error); + } + + if(!m_Scene.Permissions.CanEditObjectInventory(objectID, m_AgentID)) + { + LLSDAssetUploadError error = new LLSDAssetUploadError(); + error.message = "No permissions to edit objec"; + error.identifier = UUID.Zero; + return LLSDHelpers.SerialiseLLSDReply(error); + } + } string uploaderPath = GetNewCapPath(); - ItemUpdater uploader = - new ItemUpdater(llsdRequest.item_id, uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile); + ItemUpdater uploader = new ItemUpdater(itemID, objectID, uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile); uploader.OnUpLoad += ItemUpdated; m_HostCapsObj.HttpListener.AddStreamHandler( new BinaryStreamHandler( - "POST", uploaderPath, uploader.uploaderCaps, "NoteCardAgentInventory", null)); + "POST", uploaderPath, uploader.uploaderCaps, "UpdateInventoryItemAsset", null)); - string protocol = "http://"; - - if (m_HostCapsObj.SSLCaps) - protocol = "https://"; + string protocol = m_HostCapsObj.SSLCaps ? "https://" : "http://"; string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + uploaderPath; @@ -1396,8 +1433,7 @@ namespace OpenSim.Region.ClientStack.Linden uploadResponse.uploader = uploaderURL; uploadResponse.state = "upload"; - // m_log.InfoFormat("[CAPS]: " + - // "NoteCardAgentInventory response: {0}", + // m_log.InfoFormat("[CAPS]: UpdateAgentInventoryAsset response: {0}", // LLSDHelpers.SerialiseLLSDReply(uploadResponse))); return LLSDHelpers.SerialiseLLSDReply(uploadResponse); @@ -2349,14 +2385,16 @@ namespace OpenSim.Region.ClientStack.Linden private string uploaderPath = String.Empty; private UUID inventoryItemID; + private UUID objectID; private IHttpServer httpListener; private bool m_dumpAssetToFile; - public ItemUpdater(UUID inventoryItem, string path, IHttpServer httpServer, bool dumpAssetToFile) + public ItemUpdater(UUID inventoryItem, UUID objectid, string path, IHttpServer httpServer, bool dumpAssetToFile) { m_dumpAssetToFile = dumpAssetToFile; inventoryItemID = inventoryItem; + objectID = objectid; uploaderPath = path; httpListener = httpServer; } @@ -2370,23 +2408,31 @@ namespace OpenSim.Region.ClientStack.Linden /// public string uploaderCaps(byte[] data, string path, string param) { + httpListener.RemoveStreamHandler("POST", uploaderPath); + UUID inv = inventoryItemID; string res = String.Empty; - LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); + UUID assetID = UUID.Zero; handlerUpdateItem = OnUpLoad; if (handlerUpdateItem != null) + assetID = handlerUpdateItem(inv, objectID, data); + + if(assetID == UUID.Zero) { - assetID = handlerUpdateItem(inv, data); + LLSDAssetUploadError uperror = new LLSDAssetUploadError(); + uperror.message ="Failed to update inventory item asset"; + uperror.identifier = inv; + res = LLSDHelpers.SerialiseLLSDReply(uperror); + } + else + { + LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); + uploadComplete.new_asset = assetID.ToString(); + uploadComplete.new_inventory_item = inv; + uploadComplete.state = "complete"; + res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); } - - uploadComplete.new_asset = assetID.ToString(); - uploadComplete.new_inventory_item = inv; - uploadComplete.state = "complete"; - - res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); - - httpListener.RemoveStreamHandler("POST", uploaderPath); if (m_dumpAssetToFile) { diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index facb7a028e..fb389c4cd7 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -171,11 +171,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess /// /// /// - /// + /// /// public void CreateNewInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID, uint callbackID, string description, string name, sbyte invType, - sbyte assetType, byte wearableType, + sbyte assetType, byte subType, uint nextOwnerMask, int creationDate) { m_log.DebugFormat("[INVENTORY ACCESS MODULE]: Received request to create inventory item {0} in folder {1}, transactionID {2}", name, @@ -203,7 +203,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { if (agentTransactions.HandleItemCreationFromTransaction( remoteClient, transactionID, folderID, callbackID, description, - name, invType, assetType, wearableType, nextOwnerMask)) + name, invType, assetType, subType, nextOwnerMask)) return; } } @@ -214,6 +214,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess byte[] data = null; uint everyonemask = 0; uint groupmask = 0; + uint flags = 0; if (invType == (sbyte)InventoryType.Landmark && presence != null) { @@ -225,12 +226,35 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess groupmask = (uint)PermissionMask.AllAndExport; everyonemask = (uint)(PermissionMask.AllAndExport & ~PermissionMask.Modify); } +/* + if(assetType == (byte)AssetType.Settings) + { + if(data == null) + { + IEnvironmentModule envModule = m_Scene.RequestModuleInterface(); + if(envModule == null) + return; + data = envModule.GetDefaultAssetData(name); + if(data == null) + { + m_log.ErrorFormat( + "[INVENTORY ACCESS MODULE CreateNewInventoryItem]: failed to create default enviroment setting asset {0} for agent {1}", name, remoteClient.AgentId); + return; + } + } + flags = subType; + } + else +*/ + if( assetType == (byte)AssetType.Clothing || + assetType == (byte)AssetType.Bodypart) + flags = subType; AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); m_Scene.AssetService.Store(asset); m_Scene.CreateNewInventoryItem( remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, - name, description, 0, callbackID, asset.FullID, asset.Type, invType, + name, description, flags, callbackID, asset.FullID, asset.Type, invType, (uint)PermissionMask.AllAndExport, // Base (uint)PermissionMask.AllAndExport, // Current everyonemask, @@ -276,30 +300,35 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (item.Owner != remoteClient.AgentId) return UUID.Zero; - if ((InventoryType)item.InvType == InventoryType.Notecard) + InventoryType itemType = (InventoryType)item.InvType; + switch (itemType) { - if (!m_Scene.Permissions.CanEditNotecard(itemID, UUID.Zero, remoteClient.AgentId)) + case InventoryType.Notecard: { - remoteClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false); - return UUID.Zero; - } + if (!m_Scene.Permissions.CanEditNotecard(itemID, UUID.Zero, remoteClient.AgentId)) + { + remoteClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false); + return UUID.Zero; + } - remoteClient.SendAlertMessage("Notecard saved"); - } - else if ((InventoryType)item.InvType == InventoryType.LSL) - { - if (!m_Scene.Permissions.CanEditScript(itemID, UUID.Zero, remoteClient.AgentId)) + remoteClient.SendAlertMessage("Notecard updated"); + break; + } + case InventoryType.LSL: { - remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false); - return UUID.Zero; - } + if (!m_Scene.Permissions.CanEditScript(itemID, UUID.Zero, remoteClient.AgentId)) + { + remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false); + return UUID.Zero; + } - remoteClient.SendAlertMessage("Script saved"); - } - else if ((CustomInventoryType)item.InvType == CustomInventoryType.AnimationSet) - { - AnimationSet animSet = new AnimationSet(data); - uint res = animSet.Validate(x => { + remoteClient.SendAlertMessage("Script updated"); + break; + } + case (InventoryType)CustomInventoryType.AnimationSet: + { + AnimationSet animSet = new AnimationSet(data); + uint res = animSet.Validate(x => { const int required = (int)(PermissionMask.Transfer | PermissionMask.Copy); int perms = m_Scene.InventoryService.GetAssetPermissions(remoteClient.AgentId, x); // enforce previus perm rule @@ -307,10 +336,34 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess return 0; return (uint) perms; }); - if(res == 0) + if(res == 0) + { + remoteClient.SendAgentAlertMessage("Not enought permissions on asset(s) referenced by animation set '{0}', update failed", false); + return UUID.Zero; + } + break; + } + case InventoryType.Gesture: { - remoteClient.SendAgentAlertMessage("Not enought permissions on asset(s) referenced by animation set '{0}', update failed", false); - return UUID.Zero; + if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0) + { + remoteClient.SendAgentAlertMessage("Insufficient permissions to edit gesture", false); + return UUID.Zero; + } + + remoteClient.SendAlertMessage("gesture updated"); + break; + } + case InventoryType.Settings: + { + if((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0) + { + remoteClient.SendAgentAlertMessage("Insufficient permissions to edit setting", false); + return UUID.Zero; + } + + remoteClient.SendAlertMessage("Setting updated"); + break; } } @@ -621,8 +674,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess (uint)PermissionMask.Move | (uint)PermissionMask.Export | (uint)PermissionMask.FoldedMask); // Preserve folded permissions ?? - } - + } + return item; } diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index eabcc73200..efc70fd23b 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -225,8 +225,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap public void OnRegisterCaps(UUID agentID, Caps caps) { //m_log.DebugFormat("[WORLD MAP]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps); - string capspath = "/CAPS/" + UUID.Random(); - caps.RegisterSimpleHandler("MapLayer", new SimpleStreamHandler("/CAPS/" + UUID.Random(), MapLayerRequest)); + caps.RegisterSimpleHandler("MapLayer", new SimpleStreamHandler("/" + UUID.Random(), MapLayerRequest)); } /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 30118be98c..1407768fa3 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -265,25 +265,104 @@ namespace OpenSim.Region.Framework.Scenes /// /// CapsUpdatedInventoryItemAsset(IClientAPI, UUID, byte[]) /// - public UUID CapsUpdateInventoryItemAsset(UUID avatarId, UUID itemID, byte[] data) + public UUID CapsUpdateItemAsset(UUID avatarId, UUID itemID, UUID objectID, byte[] data) { - ScenePresence avatar; + if (!TryGetScenePresence(avatarId, out ScenePresence avatar)) + { + m_log.ErrorFormat("[CapsUpdateItemAsset]: Avatar {0} cannot be found to update item asset", avatarId); + return UUID.Zero; + } - if (TryGetScenePresence(avatarId, out avatar)) + if (objectID == UUID.Zero) { IInventoryAccessModule invAccess = RequestModuleInterface(); if (invAccess != null) return invAccess.CapsUpdateInventoryItemAsset(avatar.ControllingClient, itemID, data); - } - else - { - m_log.ErrorFormat( - "[AGENT INVENTORY]: " + - "Avatar {0} cannot be found to update its inventory item asset", - avatarId); + else + return UUID.Zero; } - return UUID.Zero; + SceneObjectPart sop = GetSceneObjectPart(objectID); + if(sop == null || sop.ParentGroup.IsDeleted) + { + m_log.ErrorFormat("[CapsUpdateItemAsset]: Object {0} cannot be found to update item asset", objectID); + return UUID.Zero; + } + + TaskInventoryItem item = sop.Inventory.GetInventoryItem(itemID); + if (item == null) + { + m_log.ErrorFormat("[CapsUpdateItemAsset]: Could not find item {0} for asset update", itemID); + return UUID.Zero; + } + + if (item.OwnerID != avatarId) + return UUID.Zero; + + InventoryType itemType = (InventoryType)item.InvType; + switch (itemType) + { + case InventoryType.Notecard: + { + if (!Permissions.CanEditNotecard(itemID, objectID, avatarId)) + { + avatar.ControllingClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false); + return UUID.Zero; + } + + avatar.ControllingClient.SendAlertMessage("Notecard updated"); + break; + } + case (InventoryType)CustomInventoryType.AnimationSet: + { + AnimationSet animSet = new AnimationSet(data); + uint res = animSet.Validate(x => { + const int required = (int)(PermissionMask.Transfer | PermissionMask.Copy); + int perms = InventoryService.GetAssetPermissions(avatarId, x); + // enforce previus perm rule + if ((perms & required) != required) + return 0; + return (uint)perms; + }); + if (res == 0) + { + avatar.ControllingClient.SendAgentAlertMessage("Not enought permissions on asset(s) referenced by animation set '{0}', update failed", false); + return UUID.Zero; + } + break; + } + case InventoryType.Gesture: + { + if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0) + { + avatar.ControllingClient.SendAgentAlertMessage("Insufficient permissions to edit gesture", false); + return UUID.Zero; + } + + avatar.ControllingClient.SendAlertMessage("gesture updated"); + break; + } + case InventoryType.Settings: + { + if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0) + { + avatar.ControllingClient.SendAgentAlertMessage("Insufficient permissions to edit setting", false); + return UUID.Zero; + } + + avatar.ControllingClient.SendAlertMessage("getting updated"); + break; + } + } + + AssetBase asset = CreateAsset(item.Name, item.Description, (sbyte)item.Type, data, avatarId); + item.AssetID = asset.FullID; + AssetService.Store(asset); + + sop.Inventory.UpdateInventoryItem(item); + + // remoteClient.SendInventoryItemCreateUpdate(item); + return asset.FullID; } ///