From 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 19 May 2019 21:24:15 +1000 Subject: Dump OpenSim 0.9.0.1 into it's own branch. --- .../Framework/Scenes/SceneObjectPartInventory.cs | 973 +++++++++++++-------- 1 file changed, 614 insertions(+), 359 deletions(-) (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index ec39726..30f7151 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -26,6 +26,7 @@ */ using System; +using System.Text; using System.Xml; using System.IO; using System.Collections.Generic; @@ -46,10 +47,15 @@ namespace OpenSim.Region.Framework.Scenes { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private string m_inventoryFileName = String.Empty; private byte[] m_inventoryFileData = new byte[0]; + private byte[] m_inventoryFileNameBytes = new byte[0]; + private string m_inventoryFileName = ""; private uint m_inventoryFileNameSerial = 0; - + private bool m_inventoryPrivileged = false; + private object m_inventoryFileLock = new object(); + + private Dictionary m_scriptErrors = new Dictionary(); + /// /// The part to which the inventory belongs. /// @@ -70,7 +76,7 @@ namespace OpenSim.Region.Framework.Scenes /// Tracks whether inventory has changed since the last persistent backup /// internal bool HasInventoryChanged; - + /// /// Inventory serial number /// @@ -85,7 +91,10 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal TaskInventoryDictionary Items { - get { return m_items; } + get + { + return m_items; + } set { m_items = value; @@ -102,7 +111,7 @@ namespace OpenSim.Region.Framework.Scenes return m_items.Count; } } - + /// /// Constructor /// @@ -133,39 +142,54 @@ namespace OpenSim.Region.Framework.Scenes /// public void ResetInventoryIDs() { - if (null == m_part) + if (m_part == null) return; - - lock (m_items) + + m_items.LockItemsForWrite(true); + if (m_items.Count == 0) { - if (0 == m_items.Count) - return; + m_items.LockItemsForWrite(false); + return; + } - IList items = GetInventoryItems(); - m_items.Clear(); + UUID partID = m_part.UUID; + IList items = new List(m_items.Values); + m_items.Clear(); - foreach (TaskInventoryItem item in items) - { - item.ResetIDs(m_part.UUID); - m_items.Add(item.ItemID, item); - } + foreach (TaskInventoryItem item in items) + { + item.ResetIDs(partID); + m_items.Add(item.ItemID, item); } + m_inventorySerial++; + m_items.LockItemsForWrite(false); } public void ResetObjectID() { - lock (Items) + if (m_part == null) + return; + + m_items.LockItemsForWrite(true); + + if (m_items.Count == 0) { - IList items = new List(Items.Values); - Items.Clear(); - - foreach (TaskInventoryItem item in items) - { - item.ParentPartID = m_part.UUID; - item.ParentID = m_part.UUID; - Items.Add(item.ItemID, item); - } + m_items.LockItemsForWrite(false); + return; } + + IList items = new List(m_items.Values); + m_items.Clear(); + + UUID partID = m_part.UUID; + foreach (TaskInventoryItem item in items) + { + item.ParentPartID = partID; + item.ParentID = partID; + m_items.Add(item.ItemID, item); + } + m_inventorySerial++; + m_items.LockItemsForWrite(false); } /// @@ -174,18 +198,17 @@ namespace OpenSim.Region.Framework.Scenes /// public void ChangeInventoryOwner(UUID ownerId) { - lock (Items) + if(m_part == null) + return; + + m_items.LockItemsForWrite(true); + if (m_items.Count == 0) { - if (0 == Items.Count) - { - return; - } + m_items.LockItemsForWrite(false); + return; } - HasInventoryChanged = true; - m_part.ParentGroup.HasGroupChanged = true; - List items = GetInventoryItems(); - foreach (TaskInventoryItem item in items) + foreach (TaskInventoryItem item in m_items.Values) { if (ownerId != item.OwnerID) item.LastOwnerID = item.OwnerID; @@ -195,6 +218,10 @@ namespace OpenSim.Region.Framework.Scenes item.PermsGranter = UUID.Zero; item.OwnerChanged = true; } + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + m_inventorySerial++; + m_items.LockItemsForWrite(false); } /// @@ -203,14 +230,16 @@ namespace OpenSim.Region.Framework.Scenes /// public void ChangeInventoryGroup(UUID groupID) { - lock (Items) + if(m_part == null) + return; + + m_items.LockItemsForWrite(true); + if (m_items.Count == 0) { - if (0 == Items.Count) - { - return; - } + m_items.LockItemsForWrite(false); + return; } - + m_inventorySerial++; // Don't let this set the HasGroupChanged flag for attachments // as this happens during rez and we don't want a new asset // for each attachment each time @@ -220,12 +249,10 @@ namespace OpenSim.Region.Framework.Scenes m_part.ParentGroup.HasGroupChanged = true; } - List items = GetInventoryItems(); - foreach (TaskInventoryItem item in items) - { - if (groupID != item.GroupID) - item.GroupID = groupID; - } + foreach (TaskInventoryItem item in m_items.Values) + item.GroupID = groupID; + + m_items.LockItemsForWrite(false); } private void QueryScriptStates() @@ -233,15 +260,18 @@ namespace OpenSim.Region.Framework.Scenes if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) return; - lock (Items) + m_items.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in Items.Values) + if (item.InvType == (int)InventoryType.LSL) { bool running; if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running)) item.ScriptRunning = running; } } + + m_items.LockItemsForRead(false); } public bool TryGetScriptInstanceRunning(UUID itemId, out bool running) @@ -318,7 +348,10 @@ namespace OpenSim.Region.Framework.Scenes { List scripts = GetInventoryItems(InventoryType.LSL); foreach (TaskInventoryItem item in scripts) + { RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); + m_part.RemoveScriptEvents(item.ItemID); + } } /// @@ -326,7 +359,9 @@ namespace OpenSim.Region.Framework.Scenes /// public void StopScriptInstances() { - GetInventoryItems(InventoryType.LSL).ForEach(i => StopScriptInstance(i)); + List scripts = GetInventoryItems(InventoryType.LSL); + foreach (TaskInventoryItem item in scripts) + StopScriptInstance(item); } /// @@ -339,8 +374,11 @@ namespace OpenSim.Region.Framework.Scenes // m_log.DebugFormat("[PRIM INVENTORY]: Starting script {0} {1} in prim {2} {3} in {4}", // item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName); - if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) + if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item, m_part)) + { + StoreScriptError(item.ItemID, "no permission"); return false; + } m_part.AddFlag(PrimFlags.Scripted); @@ -350,14 +388,13 @@ namespace OpenSim.Region.Framework.Scenes if (stateSource == 2 && // Prim crossing m_part.ParentGroup.Scene.m_trustBinaries) { - lock (m_items) - { - m_items[item.ItemID].PermsMask = 0; - m_items[item.ItemID].PermsGranter = UUID.Zero; - } - + m_items.LockItemsForWrite(true); + m_items[item.ItemID].PermsMask = 0; + m_items[item.ItemID].PermsGranter = UUID.Zero; + m_items.LockItemsForWrite(false); m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); + StoreScriptErrors(item.ItemID, null); m_part.ParentGroup.AddActiveScriptCount(1); m_part.ScheduleFullUpdate(); return true; @@ -366,9 +403,11 @@ namespace OpenSim.Region.Framework.Scenes AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); if (null == asset) { + string msg = String.Format("asset ID {0} could not be found", item.AssetID); + StoreScriptError(item.ItemID, msg); m_log.ErrorFormat( "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", - item.Name, item.ItemID, m_part.AbsolutePosition, + item.Name, item.ItemID, m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID); return false; @@ -378,16 +417,18 @@ namespace OpenSim.Region.Framework.Scenes if (m_part.ParentGroup.m_savedScriptState != null) item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID); - lock (m_items) - { - m_items[item.ItemID].OldItemID = item.OldItemID; - m_items[item.ItemID].PermsMask = 0; - m_items[item.ItemID].PermsGranter = UUID.Zero; - } + m_items.LockItemsForWrite(true); + + m_items[item.ItemID].OldItemID = item.OldItemID; + m_items[item.ItemID].PermsMask = 0; + m_items[item.ItemID].PermsGranter = UUID.Zero; + + m_items.LockItemsForWrite(false); string script = Utils.BytesToString(asset.Data); m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); + StoreScriptErrors(item.ItemID, null); if (!item.ScriptRunning) m_part.ParentGroup.Scene.EventManager.TriggerStopScript( m_part.LocalId, item.ItemID); @@ -401,7 +442,7 @@ namespace OpenSim.Region.Framework.Scenes private UUID RestoreSavedScriptState(UUID loadedID, UUID oldID, UUID newID) { // m_log.DebugFormat( -// "[PRIM INVENTORY]: Restoring scripted state for item {0}, oldID {1}, loadedID {2}", +// "[PRIM INVENTORY]: Restoring scripted state for item {0}, oldID {1}, loadedID {2}", // newID, oldID, loadedID); IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); @@ -414,7 +455,7 @@ namespace OpenSim.Region.Framework.Scenes if (m_part.ParentGroup.m_savedScriptState.ContainsKey(stateID)) { XmlDocument doc = new XmlDocument(); - + doc.XmlResolver=null; doc.LoadXml(m_part.ParentGroup.m_savedScriptState[stateID]); ////////// CRUFT WARNING /////////////////////////////////// @@ -450,7 +491,7 @@ namespace OpenSim.Region.Framework.Scenes m_part.ParentGroup.m_savedScriptState[stateID] = newDoc.OuterXml; } - + foreach (IScriptModule e in engines) { if (e != null) @@ -466,22 +507,138 @@ namespace OpenSim.Region.Framework.Scenes return stateID; } + /// + /// Start a script which is in this prim's inventory. + /// Some processing may occur in the background, but this routine returns asap. + /// + /// + /// A + /// public bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) { - TaskInventoryItem item = GetInventoryItem(itemId); - if (item != null) + lock (m_scriptErrors) + { + // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion + m_scriptErrors.Remove(itemId); + } + CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource); + return true; + } + + private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) + { + m_items.LockItemsForRead(true); + + if (m_items.ContainsKey(itemId)) { - return CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); + TaskInventoryItem it = m_items[itemId]; + m_items.LockItemsForRead(false); + + CreateScriptInstance(it, startParam, postOnRez, engine, stateSource); } else { - m_log.ErrorFormat( - "[PRIM INVENTORY]: Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", - itemId, m_part.Name, m_part.UUID, + m_items.LockItemsForRead(false); + string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID, m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); + StoreScriptError(itemId, msg); + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "Couldn't start script with ID {0} since it {1}", itemId, msg); + } + } - return false; + /// + /// Start a script which is in this prim's inventory and return any compilation error messages. + /// + /// + /// A + /// + public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) + { + ArrayList errors; + + // Indicate to CreateScriptInstanceInternal() we want it to + // post any compilation/loading error messages + lock (m_scriptErrors) + { + m_scriptErrors[itemId] = null; } + + // Perform compilation/loading + CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource); + + // Wait for and retrieve any errors + lock (m_scriptErrors) + { + while ((errors = m_scriptErrors[itemId]) == null) + { + if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000)) + { + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "timedout waiting for script {0} errors", itemId); + errors = m_scriptErrors[itemId]; + if (errors == null) + { + errors = new ArrayList(1); + errors.Add("timedout waiting for errors"); + } + break; + } + } + m_scriptErrors.Remove(itemId); + } + return errors; + } + + // Signal to CreateScriptInstanceEr() that compilation/loading is complete + private void StoreScriptErrors(UUID itemId, ArrayList errors) + { + lock (m_scriptErrors) + { + // If compilation/loading initiated via CreateScriptInstance(), + // it does not want the errors, so just get out + if (!m_scriptErrors.ContainsKey(itemId)) + { + return; + } + + // Initiated via CreateScriptInstanceEr(), if we know what the + // errors are, save them and wake CreateScriptInstanceEr(). + if (errors != null) + { + m_scriptErrors[itemId] = errors; + System.Threading.Monitor.PulseAll(m_scriptErrors); + return; + } + } + + // Initiated via CreateScriptInstanceEr() but we don't know what + // the errors are yet, so retrieve them from the script engine. + // This may involve some waiting internal to GetScriptErrors(). + errors = GetScriptErrors(itemId); + + // Get a default non-null value to indicate success. + if (errors == null) + { + errors = new ArrayList(); + } + + // Post to CreateScriptInstanceEr() and wake it up + lock (m_scriptErrors) + { + m_scriptErrors[itemId] = errors; + System.Threading.Monitor.PulseAll(m_scriptErrors); + } + } + + // Like StoreScriptErrors(), but just posts a single string message + private void StoreScriptError(UUID itemId, string message) + { + ArrayList errors = new ArrayList(1); + errors.Add(message); + StoreScriptErrors(itemId, errors); } /// @@ -494,19 +651,11 @@ namespace OpenSim.Region.Framework.Scenes /// public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) { - bool scriptPresent = false; - - lock (m_items) - { - if (m_items.ContainsKey(itemId)) - scriptPresent = true; - } - - if (scriptPresent) + if (m_items.ContainsKey(itemId)) { if (!sceneObjectBeingDeleted) m_part.RemoveScriptEvents(itemId); - + m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemId); m_part.ParentGroup.AddActiveScriptCount(-1); } @@ -515,7 +664,7 @@ namespace OpenSim.Region.Framework.Scenes m_log.WarnFormat( "[PRIM INVENTORY]: " + "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", - itemId, m_part.Name, m_part.UUID, + itemId, m_part.Name, m_part.UUID, m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); } } @@ -544,7 +693,7 @@ namespace OpenSim.Region.Framework.Scenes m_log.WarnFormat( "[PRIM INVENTORY]: " + "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", - itemId, m_part.Name, m_part.UUID, + itemId, m_part.Name, m_part.UUID, m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); } } @@ -573,14 +722,16 @@ namespace OpenSim.Region.Framework.Scenes /// private bool InventoryContainsName(string name) { - lock (m_items) + m_items.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in m_items.Values) + if (item.Name == name) { - if (item.Name == name) - return true; + m_items.LockItemsForRead(false); + return true; } } + m_items.LockItemsForRead(false); return false; } @@ -622,8 +773,9 @@ namespace OpenSim.Region.Framework.Scenes /// public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) { - List il = GetInventoryItems(); - + m_items.LockItemsForRead(true); + List il = new List(m_items.Values); + m_items.LockItemsForRead(false); foreach (TaskInventoryItem i in il) { if (i.Name == item.Name) @@ -661,16 +813,16 @@ namespace OpenSim.Region.Framework.Scenes item.Name = name; item.GroupID = m_part.GroupID; - lock (m_items) - m_items.Add(item.ItemID, item); - - if (allowedDrop) - m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); - else - m_part.TriggerScriptChangedEvent(Changed.INVENTORY); + m_items.LockItemsForWrite(true); + m_items.Add(item.ItemID, item); + m_items.LockItemsForWrite(false); + if (allowedDrop) + m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); + else + m_part.TriggerScriptChangedEvent(Changed.INVENTORY); + m_part.AggregateInnerPerms(); m_inventorySerial++; - //m_inventorySerial += 2; HasInventoryChanged = true; m_part.ParentGroup.HasGroupChanged = true; } @@ -684,15 +836,15 @@ namespace OpenSim.Region.Framework.Scenes /// public void RestoreInventoryItems(ICollection items) { - lock (m_items) + m_items.LockItemsForWrite(true); + foreach (TaskInventoryItem item in items) { - foreach (TaskInventoryItem item in items) - { - m_items.Add(item.ItemID, item); -// m_part.TriggerScriptChangedEvent(Changed.INVENTORY); - } - m_inventorySerial++; + m_items.Add(item.ItemID, item); +// m_part.TriggerScriptChangedEvent(Changed.INVENTORY); } + m_items.LockItemsForWrite(false); + m_part.AggregateInnerPerms(); + m_inventorySerial++; } /// @@ -703,23 +855,24 @@ namespace OpenSim.Region.Framework.Scenes public TaskInventoryItem GetInventoryItem(UUID itemId) { TaskInventoryItem item; - - lock (m_items) - m_items.TryGetValue(itemId, out item); - + m_items.LockItemsForRead(true); + m_items.TryGetValue(itemId, out item); + m_items.LockItemsForRead(false); return item; } public TaskInventoryItem GetInventoryItem(string name) { - lock (m_items) + m_items.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in m_items.Values) + if (item.Name == name) { - if (item.Name == name) - return item; + m_items.LockItemsForRead(false); + return item; } } + m_items.LockItemsForRead(false); return null; } @@ -728,41 +881,45 @@ namespace OpenSim.Region.Framework.Scenes { List items = new List(); - lock (m_items) + m_items.LockItemsForRead(true); + + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in m_items.Values) - { - if (item.Name == name) - items.Add(item); - } + if (item.Name == name) + items.Add(item); } + m_items.LockItemsForRead(false); + return items; } - public bool GetRezReadySceneObjects(TaskInventoryItem item, out List objlist, out List veclist) + public bool GetRezReadySceneObjects(TaskInventoryItem item, out List objlist, out List veclist, out Vector3 bbox, out float offsetHeight) { AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); if (null == rezAsset) { m_log.WarnFormat( - "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}", + "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}", item.AssetID, item.Name, m_part.Name); objlist = null; veclist = null; + bbox = Vector3.Zero; + offsetHeight = 0; return false; } - Vector3 bbox; - float offsetHeight; - - m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight); + bool single = m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight); for (int i = 0; i < objlist.Count; i++) { SceneObjectGroup group = objlist[i]; - +/* + group.RootPart.AttachPoint = group.RootPart.Shape.State; + group.RootPart.AttachedPos = group.AbsolutePosition; + group.RootPart.AttachRotation = group.GroupRotation; +*/ group.ResetIDs(); SceneObjectPart rootPart = group.GetPart(group.UUID); @@ -771,12 +928,14 @@ namespace OpenSim.Region.Framework.Scenes // in the serialization, transfer the correct name from the inventory to the // object itself before we rez. // Only do these for the first object if we are rezzing a coalescence. - if (i == 0) + // nahh dont mess with coalescence objects, + // the name in inventory can be change for inventory purpuses only + if (objlist.Count == 1) { rootPart.Name = item.Name; rootPart.Description = item.Description; } - +/* reverted to old code till part.ApplyPermissionsOnRez is better reviewed/fixed group.SetGroup(m_part.GroupID, null); foreach (SceneObjectPart part in group.Parts) @@ -792,13 +951,55 @@ namespace OpenSim.Region.Framework.Scenes part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene); } +*/ +// old code start + SceneObjectPart[] partList = group.Parts; + group.SetGroup(m_part.GroupID, null); + + if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & (uint)PermissionMask.Slam) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) + { + if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions()) + { + foreach (SceneObjectPart part in partList) + { + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) + part.EveryoneMask = item.EveryonePermissions; + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) + part.NextOwnerMask = item.NextPermissions; + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) + part.GroupMask = item.GroupPermissions; + } + + group.ApplyNextOwnerPermissions(); + } + } + + foreach (SceneObjectPart part in partList) + { + if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & (uint)PermissionMask.Slam) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) + { + if(part.GroupID != part.OwnerID) + part.LastOwnerID = part.OwnerID; + part.OwnerID = item.OwnerID; + part.Inventory.ChangeInventoryOwner(item.OwnerID); + } + + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) + part.EveryoneMask = item.EveryonePermissions; + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) + part.NextOwnerMask = item.NextPermissions; + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) + part.GroupMask = item.GroupPermissions; + } +// old code end rootPart.TrimPermissions(); + group.InvalidateDeepEffectivePerms(); } return true; } - + /// /// Update an existing inventory item. /// @@ -817,11 +1018,12 @@ namespace OpenSim.Region.Framework.Scenes public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) { - TaskInventoryItem it = GetInventoryItem(item.ItemID); - if (it != null) + m_items.LockItemsForWrite(true); + + if (m_items.ContainsKey(item.ItemID)) { // m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); - + item.ParentID = m_part.UUID; item.ParentPartID = m_part.UUID; @@ -830,24 +1032,26 @@ namespace OpenSim.Region.Framework.Scenes if (item.GroupPermissions != (uint)PermissionMask.None) item.GroupID = m_part.GroupID; + if(item.OwnerID == UUID.Zero) // viewer to internal enconding of group owned + item.OwnerID = item.GroupID; + if (item.AssetID == UUID.Zero) - item.AssetID = it.AssetID; + item.AssetID = m_items[item.ItemID].AssetID; - lock (m_items) - { - m_items[item.ItemID] = item; - m_inventorySerial++; - } - + m_items[item.ItemID] = item; + + m_inventorySerial++; if (fireScriptEvents) m_part.TriggerScriptChangedEvent(Changed.INVENTORY); - + if (considerChanged) { + m_part.ParentGroup.InvalidateDeepEffectivePerms(); HasInventoryChanged = true; m_part.ParentGroup.HasGroupChanged = true; } - + m_items.LockItemsForWrite(false); + return true; } else @@ -855,11 +1059,12 @@ namespace OpenSim.Region.Framework.Scenes m_log.ErrorFormat( "[PRIM INVENTORY]: " + "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", - item.ItemID, m_part.Name, m_part.UUID, + item.ItemID, m_part.Name, m_part.UUID, m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); } - return false; + m_items.LockItemsForWrite(false); + return false; } /// @@ -870,160 +1075,194 @@ namespace OpenSim.Region.Framework.Scenes /// in this prim's inventory. public int RemoveInventoryItem(UUID itemID) { - TaskInventoryItem item = GetInventoryItem(itemID); - if (item != null) + m_items.LockItemsForRead(true); + + if (m_items.ContainsKey(itemID)) { int type = m_items[itemID].InvType; - if (type == 10) // Script + m_items.LockItemsForRead(false); + if (type == (int)InventoryType.LSL) // Script { - // route it through here, to handle script cleanup tasks - RemoveScriptInstance(itemID, false); + m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); } + m_items.LockItemsForWrite(true); m_items.Remove(itemID); + m_items.LockItemsForWrite(false); + + m_part.ParentGroup.InvalidateDeepEffectivePerms(); + m_inventorySerial++; m_part.TriggerScriptChangedEvent(Changed.INVENTORY); HasInventoryChanged = true; m_part.ParentGroup.HasGroupChanged = true; - if (!ContainsScripts()) + int scriptcount = 0; + m_items.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_items.Values) + { + if (item.Type == (int)InventoryType.LSL) + { + scriptcount++; + } + } + m_items.LockItemsForRead(false); + + + if (scriptcount <= 0) + { m_part.RemFlag(PrimFlags.Scripted); + } m_part.ScheduleFullUpdate(); return type; - } else { + m_items.LockItemsForRead(false); m_log.ErrorFormat( "[PRIM INVENTORY]: " + - "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", - itemID, m_part.Name, m_part.UUID, - m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); + "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory", + itemID, m_part.Name, m_part.UUID); } return -1; } - private bool CreateInventoryFile() - { -// m_log.DebugFormat( -// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}", -// m_part.Name, m_part.UUID, m_part.LocalId, m_inventorySerial); - if (m_inventoryFileName == String.Empty || - m_inventoryFileNameSerial < m_inventorySerial) + /// + /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client + /// + /// + public void RequestInventoryFile(IClientAPI client, IXfer xferManager) + { + lock (m_inventoryFileLock) { - // Something changed, we need to create a new file - m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; - m_inventoryFileNameSerial = m_inventorySerial; + bool changed = false; - InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); + m_items.LockItemsForRead(true); - lock (m_items) + if (m_inventorySerial == 0) // No inventory { - foreach (TaskInventoryItem item in m_items.Values) - { -// m_log.DebugFormat( -// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}", -// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId); + m_items.LockItemsForRead(false); + client.SendTaskInventory(m_part.UUID, 0, new byte[0]); + return; + } - UUID ownerID = item.OwnerID; - uint everyoneMask = 0; - uint baseMask = item.BasePermissions; - uint ownerMask = item.CurrentPermissions; - uint groupMask = item.GroupPermissions; + if (m_items.Count == 0) // No inventory + { + m_items.LockItemsForRead(false); + client.SendTaskInventory(m_part.UUID, 0, new byte[0]); + return; + } - invString.AddItemStart(); - invString.AddNameValueLine("item_id", item.ItemID.ToString()); - invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); + if (m_inventoryFileNameSerial != m_inventorySerial) + { + m_inventoryFileNameSerial = m_inventorySerial; + changed = true; + } - invString.AddPermissionsStart(); + m_items.LockItemsForRead(false); - invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); - invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); - invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); - invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); - invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); + if (m_inventoryFileData.Length < 2) + changed = true; - invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); - invString.AddNameValueLine("owner_id", ownerID.ToString()); + bool includeAssets = false; + if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId)) + includeAssets = true; - invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); + if (m_inventoryPrivileged != includeAssets) + changed = true; - invString.AddNameValueLine("group_id", item.GroupID.ToString()); - invString.AddSectionEnd(); + if (!changed) + { + xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); + client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial, + m_inventoryFileNameBytes); - invString.AddNameValueLine("asset_id", item.AssetID.ToString()); - invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type)); - invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType)); - invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); + return; + } - invString.AddSaleStart(); - invString.AddNameValueLine("sale_type", "not"); - invString.AddNameValueLine("sale_price", "0"); - invString.AddSectionEnd(); + m_inventoryPrivileged = includeAssets; - invString.AddNameValueLine("name", item.Name + "|"); - invString.AddNameValueLine("desc", item.Description + "|"); + InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); - invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); - invString.AddSectionEnd(); - } - } + m_items.LockItemsForRead(true); - m_inventoryFileData = Utils.StringToBytes(invString.BuildString); + foreach (TaskInventoryItem item in m_items.Values) + { + UUID ownerID = item.OwnerID; + UUID groupID = item.GroupID; + uint everyoneMask = item.EveryonePermissions; + uint baseMask = item.BasePermissions; + uint ownerMask = item.CurrentPermissions; + uint groupMask = item.GroupPermissions; - return true; - } + invString.AddItemStart(); + invString.AddNameValueLine("item_id", item.ItemID.ToString()); + invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); - // No need to recreate, the existing file is fine - return false; - } + invString.AddPermissionsStart(); - /// - /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client - /// - /// - public void RequestInventoryFile(IClientAPI client, IXfer xferManager) - { - lock (m_items) - { - // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing - // a new script if any previous deletion has left the prim inventory empty. - if (m_items.Count == 0) // No inventory - { -// m_log.DebugFormat( -// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items", -// m_part.Name, m_part.LocalId, m_part.UUID, client.Name); + invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); + invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); + invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); + invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); + invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); - client.SendTaskInventory(m_part.UUID, 0, new byte[0]); - return; + invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); + + invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); + + invString.AddNameValueLine("group_id",groupID.ToString()); + if(groupID != UUID.Zero && ownerID == groupID) + { + invString.AddNameValueLine("owner_id", UUID.Zero.ToString()); + invString.AddNameValueLine("group_owned","1"); + } + else + { + invString.AddNameValueLine("owner_id", ownerID.ToString()); + invString.AddNameValueLine("group_owned","0"); + } + + invString.AddSectionEnd(); + + if (includeAssets) + invString.AddNameValueLine("asset_id", item.AssetID.ToString()); + else + invString.AddNameValueLine("asset_id", UUID.Zero.ToString()); + invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type)); + invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType)); + invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); + + invString.AddSaleStart(); + invString.AddNameValueLine("sale_type", "not"); + invString.AddNameValueLine("sale_price", "0"); + invString.AddSectionEnd(); + + invString.AddNameValueLine("name", item.Name + "|"); + invString.AddNameValueLine("desc", item.Description + "|"); + + invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); + invString.AddSectionEnd(); } - CreateInventoryFile(); - - // In principle, we should only do the rest if the inventory changed; - // by sending m_inventorySerial to the client, it ought to know - // that nothing changed and that it doesn't need to request the file. - // Unfortunately, it doesn't look like the client optimizes this; - // the client seems to always come back and request the Xfer, - // no matter what value m_inventorySerial has. - // FIXME: Could probably be > 0 here rather than > 2 + m_items.LockItemsForRead(false); + + m_inventoryFileData = Utils.StringToBytes(invString.GetString()); + if (m_inventoryFileData.Length > 2) { - // Add the file for Xfer - // m_log.DebugFormat( - // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}", - // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId); - + m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; + m_inventoryFileNameBytes = Util.StringToBytes256(m_inventoryFileName); xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); + client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial,m_inventoryFileNameBytes); + return; } - - // Tell the client we're ready to Xfer the file - client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, - Util.StringToBytes256(m_inventoryFileName)); + + client.SendTaskInventory(m_part.UUID, 0, new byte[0]); } } @@ -1033,67 +1272,80 @@ namespace OpenSim.Region.Framework.Scenes /// public void ProcessInventoryBackup(ISimulationDataService datastore) { - if (HasInventoryChanged) - { +// Removed this because linking will cause an immediate delete of the new +// child prim from the database and the subsequent storing of the prim sees +// the inventory of it as unchanged and doesn't store it at all. The overhead +// of storing prim inventory needlessly is much less than the aggravation +// of prim inventory loss. +// if (HasInventoryChanged) +// { + m_items.LockItemsForRead(true); + ICollection itemsvalues = m_items.Values; HasInventoryChanged = false; - List items = GetInventoryItems(); - datastore.StorePrimInventory(m_part.UUID, items); - - } + m_items.LockItemsForRead(false); + try + { + datastore.StorePrimInventory(m_part.UUID, itemsvalues); + } + catch {} +// } } public class InventoryStringBuilder { - public string BuildString = String.Empty; + private StringBuilder BuildString = new StringBuilder(1024); public InventoryStringBuilder(UUID folderID, UUID parentID) { - BuildString += "\tinv_object\t0\n\t{\n"; + BuildString.Append("\tinv_object\t0\n\t{\n"); AddNameValueLine("obj_id", folderID.ToString()); AddNameValueLine("parent_id", parentID.ToString()); AddNameValueLine("type", "category"); - AddNameValueLine("name", "Contents|"); - AddSectionEnd(); + AddNameValueLine("name", "Contents|\n\t}"); } public void AddItemStart() { - BuildString += "\tinv_item\t0\n"; - AddSectionStart(); + BuildString.Append("\tinv_item\t0\n\t{\n"); } public void AddPermissionsStart() { - BuildString += "\tpermissions 0\n"; - AddSectionStart(); + BuildString.Append("\tpermissions 0\n\t{\n"); } public void AddSaleStart() { - BuildString += "\tsale_info\t0\n"; - AddSectionStart(); + BuildString.Append("\tsale_info\t0\n\t{\n"); } protected void AddSectionStart() { - BuildString += "\t{\n"; + BuildString.Append("\t{\n"); } public void AddSectionEnd() { - BuildString += "\t}\n"; + BuildString.Append("\t}\n"); } public void AddLine(string addLine) { - BuildString += addLine; + BuildString.Append(addLine); } public void AddNameValueLine(string name, string value) { - BuildString += "\t\t"; - BuildString += name + "\t"; - BuildString += value + "\n"; + BuildString.Append("\t\t"); + BuildString.Append(name); + BuildString.Append("\t"); + BuildString.Append(value); + BuildString.Append("\n"); + } + + public String GetString() + { + return BuildString.ToString(); } public void Close() @@ -1101,71 +1353,74 @@ namespace OpenSim.Region.Framework.Scenes } } + public void AggregateInnerPerms(ref uint owner, ref uint group, ref uint everyone) + { + foreach (TaskInventoryItem item in m_items.Values) + { + if(item.InvType == (sbyte)InventoryType.Landmark) + continue; + owner &= item.CurrentPermissions; + group &= item.GroupPermissions; + everyone &= item.EveryonePermissions; + } + } + public uint MaskEffectivePermissions() { + // used to propagate permissions restrictions outwards + // Modify does not propagate outwards. uint mask=0x7fffffff; - - lock (m_items) + + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in m_items.Values) - { - if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) - mask &= ~((uint)PermissionMask.Copy >> 13); - if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) - mask &= ~((uint)PermissionMask.Transfer >> 13); - if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) - mask &= ~((uint)PermissionMask.Modify >> 13); - - if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) - mask &= ~(uint)PermissionMask.Copy; - if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) - mask &= ~(uint)PermissionMask.Transfer; - if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0) - mask &= ~(uint)PermissionMask.Modify; - } + if(item.InvType == (sbyte)InventoryType.Landmark) + continue; + + // apply current to normal permission bits + uint newperms = item.CurrentPermissions; + + if ((newperms & (uint)PermissionMask.Copy) == 0) + mask &= ~(uint)PermissionMask.Copy; + if ((newperms & (uint)PermissionMask.Transfer) == 0) + mask &= ~(uint)PermissionMask.Transfer; + if ((newperms & (uint)PermissionMask.Export) == 0) + mask &= ~((uint)PermissionMask.Export); + + // apply next owner restricted by current to folded bits + newperms &= item.NextPermissions; + + if ((newperms & (uint)PermissionMask.Copy) == 0) + mask &= ~((uint)PermissionMask.FoldedCopy); + if ((newperms & (uint)PermissionMask.Transfer) == 0) + mask &= ~((uint)PermissionMask.FoldedTransfer); + if ((newperms & (uint)PermissionMask.Export) == 0) + mask &= ~((uint)PermissionMask.FoldedExport); + } - return mask; } public void ApplyNextOwnerPermissions() { - lock (m_items) + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in m_items.Values) - { -// m_log.DebugFormat ( -// "[SCENE OBJECT PART INVENTORY]: Applying next permissions {0} to {1} in {2} with current {3}, base {4}, everyone {5}", -// item.NextPermissions, item.Name, m_part.Name, item.CurrentPermissions, item.BasePermissions, item.EveryonePermissions); - - if (item.InvType == (int)InventoryType.Object) - { - uint perms = item.CurrentPermissions; - PermissionsUtil.ApplyFoldedPermissions(perms, ref perms); - item.CurrentPermissions = perms; - } - - item.CurrentPermissions &= item.NextPermissions; - item.BasePermissions &= item.NextPermissions; - item.EveryonePermissions &= item.NextPermissions; - item.OwnerChanged = true; - item.PermsMask = 0; - item.PermsGranter = UUID.Zero; - } + item.CurrentPermissions &= item.NextPermissions; + item.BasePermissions &= item.NextPermissions; + item.EveryonePermissions &= item.NextPermissions; + item.OwnerChanged = true; + item.PermsMask = 0; + item.PermsGranter = UUID.Zero; } } public void ApplyGodPermissions(uint perms) { - lock (m_items) + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in m_items.Values) - { - item.CurrentPermissions = perms; - item.BasePermissions = perms; - } + item.CurrentPermissions = perms; + item.BasePermissions = perms; } - + m_inventorySerial++; HasInventoryChanged = true; } @@ -1176,14 +1431,11 @@ namespace OpenSim.Region.Framework.Scenes /// public bool ContainsScripts() { - lock (m_items) + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in m_items.Values) + if (item.InvType == (int)InventoryType.LSL) { - if (item.InvType == (int)InventoryType.LSL) - { - return true; - } + return true; } } @@ -1197,17 +1449,13 @@ namespace OpenSim.Region.Framework.Scenes public int ScriptCount() { int count = 0; - lock (m_items) + m_items.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in m_items.Values) - { - if (item.InvType == (int)InventoryType.LSL) - { - count++; - } - } + if (item.InvType == (int)InventoryType.LSL) + count++; } - + m_items.LockItemsForRead(false); return count; } /// @@ -1230,9 +1478,7 @@ namespace OpenSim.Region.Framework.Scenes if (engine != null) { if (engine.GetScriptState(item.ItemID)) - { count++; - } } } } @@ -1241,50 +1487,52 @@ namespace OpenSim.Region.Framework.Scenes public List GetInventoryList() { - List ret = new List(); + m_items.LockItemsForRead(true); - lock (m_items) - { - foreach (TaskInventoryItem item in m_items.Values) - ret.Add(item.ItemID); - } + List ret = new List(m_items.Count); + foreach (TaskInventoryItem item in m_items.Values) + ret.Add(item.ItemID); + m_items.LockItemsForRead(false); return ret; } public List GetInventoryItems() { - List ret = new List(); - - lock (m_items) - ret = new List(m_items.Values); + m_items.LockItemsForRead(true); + List ret = new List(m_items.Values); + m_items.LockItemsForRead(false); return ret; } public List GetInventoryItems(InventoryType type) { - List ret = new List(); + m_items.LockItemsForRead(true); - lock (m_items) - { - foreach (TaskInventoryItem item in m_items.Values) - if (item.InvType == (int)type) - ret.Add(item); - } + List ret = new List(m_items.Count); + foreach (TaskInventoryItem item in m_items.Values) + if (item.InvType == (int)type) + ret.Add(item); + m_items.LockItemsForRead(false); return ret; } - + public Dictionary GetScriptStates() { - Dictionary ret = new Dictionary(); - + return GetScriptStates(false); + } + + public Dictionary GetScriptStates(bool oldIDs) + { + Dictionary ret = new Dictionary(); + if (m_part.ParentGroup.Scene == null) // Group not in a scene return ret; - + IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); - + if (engines.Length == 0) // No engine at all return ret; @@ -1303,17 +1551,24 @@ namespace OpenSim.Region.Framework.Scenes string n = e.GetXMLState(item.ItemID); if (n != String.Empty) { - if (!ret.ContainsKey(item.ItemID)) - ret[item.ItemID] = n; + if (oldIDs) + { + if (!ret.ContainsKey(item.OldItemID)) + ret[item.OldItemID] = n; + } + else + { + if (!ret.ContainsKey(item.ItemID)) + ret[item.ItemID] = n; + } break; } } } } - return ret; } - + public void ResumeScripts() { IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); -- cgit v1.1