diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 1744fb3754..1f49a015da 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -111,7 +111,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return; if (!m_scene.Permissions.CanTakeObject(part.UUID, remoteClient.AgentId)) + { + remoteClient.SendAgentAlertMessage( + "You don't have sufficient permissions to attach this object", false); + return; + } // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should // be removed when that functionality is implemented in opensim @@ -141,76 +146,66 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments { Vector3 attachPos = group.AbsolutePosition; - if (m_scene.Permissions.CanTakeObject(group.UUID, remoteClient.AgentId)) + // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should + // be removed when that functionality is implemented in opensim + AttachmentPt &= 0x7f; + + // If the attachment point isn't the same as the one previously used + // set it's offset position = 0 so that it appears on the attachment point + // and not in a weird location somewhere unknown. + if (AttachmentPt != 0 && AttachmentPt != (uint)group.GetAttachmentPoint()) { - // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should - // be removed when that functionality is implemented in opensim - AttachmentPt &= 0x7f; - - // If the attachment point isn't the same as the one previously used - // set it's offset position = 0 so that it appears on the attachment point - // and not in a weird location somewhere unknown. - if (AttachmentPt != 0 && AttachmentPt != (uint)group.GetAttachmentPoint()) - { - attachPos = Vector3.Zero; - } + attachPos = Vector3.Zero; + } - // AttachmentPt 0 means the client chose to 'wear' the attachment. - if (AttachmentPt == 0) - { - // Check object for stored attachment point - AttachmentPt = (uint)group.GetAttachmentPoint(); - } + // AttachmentPt 0 means the client chose to 'wear' the attachment. + if (AttachmentPt == 0) + { + // Check object for stored attachment point + AttachmentPt = (uint)group.GetAttachmentPoint(); + } - // if we still didn't find a suitable attachment point....... - if (AttachmentPt == 0) - { - // Stick it on left hand with Zero Offset from the attachment point. - AttachmentPt = (uint)AttachmentPoint.LeftHand; - attachPos = Vector3.Zero; - } + // if we still didn't find a suitable attachment point....... + if (AttachmentPt == 0) + { + // Stick it on left hand with Zero Offset from the attachment point. + AttachmentPt = (uint)AttachmentPoint.LeftHand; + attachPos = Vector3.Zero; + } - group.SetAttachmentPoint((byte)AttachmentPt); - group.AbsolutePosition = attachPos; + group.SetAttachmentPoint((byte)AttachmentPt); + group.AbsolutePosition = attachPos; - // Remove any previous attachments - ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); - UUID itemID = UUID.Zero; - if (sp != null) + // Remove any previous attachments + ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); + UUID itemID = UUID.Zero; + if (sp != null) + { + foreach (SceneObjectGroup grp in sp.Attachments) { - foreach (SceneObjectGroup grp in sp.Attachments) + if (grp.GetAttachmentPoint() == (byte)AttachmentPt) { - if (grp.GetAttachmentPoint() == (byte)AttachmentPt) - { - itemID = grp.GetFromItemID(); - break; - } + itemID = grp.GetFromItemID(); + break; } - if (itemID != UUID.Zero) - DetachSingleAttachmentToInv(itemID, remoteClient); } + if (itemID != UUID.Zero) + DetachSingleAttachmentToInv(itemID, remoteClient); + } - if (group.GetFromItemID() == UUID.Zero) - { - m_scene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemID); - } - else - { - itemID = group.GetFromItemID(); - } - - ShowAttachInUserInventory(remoteClient, AttachmentPt, itemID, group); - - AttachToAgent(sp, group, AttachmentPt, attachPos, silent); + if (group.GetFromItemID() == UUID.Zero) + { + m_scene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemID); } else { - remoteClient.SendAgentAlertMessage( - "You don't have sufficient permissions to attach this object", false); - - return false; + itemID = group.GetFromItemID(); } + ShowAttachInUserInventory(remoteClient, AttachmentPt, itemID, group); + + AttachToAgent(sp, group, AttachmentPt, attachPos, silent); + return true; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index a29b7f1337..06f8ac1ca5 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1733,7 +1733,12 @@ namespace OpenSim.Region.Framework.Scenes // Autoreturn has a null client. Nothing else does. So // allow only returns if (action != DeRezAction.Return) + { + m_log.WarnFormat( + "[AGENT INVENTORY]: Ignoring attempt to {0} {1} {2} without a client", + action, grp.Name, grp.UUID); return; + } permissionToTakeCopy = false; } @@ -1741,13 +1746,13 @@ namespace OpenSim.Region.Framework.Scenes { if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) permissionToTakeCopy = false; + if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) permissionToTake = false; - + if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) permissionToDelete = false; } - } // Handle god perms diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs index 06890a02e1..d67638ad1f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs @@ -27,13 +27,15 @@ using System; using System.Collections.Generic; +using System.Reflection; using System.Text; +using log4net; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; namespace OpenSim.Region.Framework.Scenes -{ +{ #region Delegates public delegate uint GenerateClientFlagsHandler(UUID userID, UUID objectID); public delegate void SetBypassPermissionsHandler(bool value); @@ -88,6 +90,8 @@ namespace OpenSim.Region.Framework.Scenes public class ScenePermissions { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Scene m_scene; public ScenePermissions(Scene scene) @@ -242,6 +246,8 @@ namespace OpenSim.Region.Framework.Scenes #region DELETE OBJECT public bool CanDeleteObject(UUID objectID, UUID deleter) { + bool result = true; + DeleteObjectHandler handler = OnDeleteObject; if (handler != null) { @@ -249,10 +255,18 @@ namespace OpenSim.Region.Framework.Scenes foreach (DeleteObjectHandler h in list) { if (h(objectID, deleter, m_scene) == false) - return false; + { + result = false; + break; + } } } - return true; + +// m_log.DebugFormat( +// "[SCENE PERMISSIONS]: CanDeleteObject() fired for object {0}, deleter {1}, result {2}", +// objectID, deleter, result); + + return result; } #endregion @@ -260,6 +274,8 @@ namespace OpenSim.Region.Framework.Scenes #region TAKE OBJECT public bool CanTakeObject(UUID objectID, UUID AvatarTakingUUID) { + bool result = true; + TakeObjectHandler handler = OnTakeObject; if (handler != null) { @@ -267,10 +283,18 @@ namespace OpenSim.Region.Framework.Scenes foreach (TakeObjectHandler h in list) { if (h(objectID, AvatarTakingUUID, m_scene) == false) - return false; + { + result = false; + break; + } } } - return true; + +// m_log.DebugFormat( +// "[SCENE PERMISSIONS]: CanTakeObject() fired for object {0}, taker {1}, result {2}", +// objectID, AvatarTakingUUID, result); + + return result; } #endregion @@ -278,6 +302,8 @@ namespace OpenSim.Region.Framework.Scenes #region TAKE COPY OBJECT public bool CanTakeCopyObject(UUID objectID, UUID userID) { + bool result = true; + TakeCopyObjectHandler handler = OnTakeCopyObject; if (handler != null) { @@ -285,10 +311,18 @@ namespace OpenSim.Region.Framework.Scenes foreach (TakeCopyObjectHandler h in list) { if (h(objectID, userID, m_scene) == false) - return false; + { + result = false; + break; + } } } - return true; + +// m_log.DebugFormat( +// "[SCENE PERMISSIONS]: CanTakeCopyObject() fired for object {0}, user {1}, result {2}", +// objectID, userID, result); + + return result; } #endregion @@ -383,6 +417,8 @@ namespace OpenSim.Region.Framework.Scenes #region RETURN OBJECT public bool CanReturnObjects(ILandObject land, UUID user, List objects) { + bool result = true; + ReturnObjectsHandler handler = OnReturnObjects; if (handler != null) { @@ -390,10 +426,18 @@ namespace OpenSim.Region.Framework.Scenes foreach (ReturnObjectsHandler h in list) { if (h(land, user, objects, m_scene) == false) - return false; + { + result = false; + break; + } } } - return true; + +// m_log.DebugFormat( +// "[SCENE PERMISSIONS]: CanReturnObjects() fired for user {0} for {1} objects on {2}, result {3}", +// user, objects.Count, land.LandData.Name, result); + + return result; } #endregion diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserTests.cs new file mode 100644 index 0000000000..b3b99f4922 --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserTests.cs @@ -0,0 +1,129 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using Nini.Config; +using NUnit.Framework; +using NUnit.Framework.SyntaxHelpers; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.CoreModules.World.Permissions; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; +using OpenSim.Tests.Common.Setup; + +namespace OpenSim.Region.Framework.Scenes.Tests +{ + /// + /// Tests manipulation of scene objects by users. + /// + /// + /// This is at a level above the SceneObjectBasicTests, which act on the scene directly. + /// FIXME: These tests are very incomplete - they only test for a few conditions. + [TestFixture] + public class SceneObjectUserTests + { + /// + /// Test deleting an object from a scene. + /// + [Test] + public void TestDeRezSceneObject() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); + + TestScene scene = SceneSetupHelpers.SetupScene(); + IConfigSource configSource = new IniConfigSource(); + IConfig config = configSource.AddConfig("Startup"); + config.Set("serverside_object_permissions", true); + SceneSetupHelpers.SetupSceneModules(scene, configSource, new object[] { new PermissionsModule() }); + TestClient client = SceneSetupHelpers.AddRootAgent(scene, userId); + + // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. + AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; + sogd.Enabled = false; + + SceneObjectPart part + = new SceneObjectPart(userId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero); + part.Name = "obj1"; + scene.AddNewSceneObject(new SceneObjectGroup(part), false); + List localIds = new List(); + localIds.Add(part.LocalId); + + scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero); + sogd.InventoryDeQueueAndDelete(); + + SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); + Assert.That(retrievedPart, Is.Null); + } + + /// + /// Test deleting an object from a scene where the deleter is not the owner + /// + /// + /// This test assumes that the deleter is not a god. + [Test] + public void TestDeRezSceneObjectNotOwner() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); + UUID objectOwnerId = UUID.Parse("20000000-0000-0000-0000-000000000001"); + + TestScene scene = SceneSetupHelpers.SetupScene(); + IConfigSource configSource = new IniConfigSource(); + IConfig config = configSource.AddConfig("Startup"); + config.Set("serverside_object_permissions", true); + SceneSetupHelpers.SetupSceneModules(scene, configSource, new object[] { new PermissionsModule() }); + TestClient client = SceneSetupHelpers.AddRootAgent(scene, userId); + + // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. + AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; + sogd.Enabled = false; + + SceneObjectPart part + = new SceneObjectPart(objectOwnerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero); + part.Name = "obj1"; + scene.AddNewSceneObject(new SceneObjectGroup(part), false); + List localIds = new List(); + localIds.Add(part.LocalId); + + scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero); + sogd.InventoryDeQueueAndDelete(); + + SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); + Assert.That(retrievedPart.UUID, Is.EqualTo(part.UUID)); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs index ab5968c37c..ef52363611 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs @@ -65,6 +65,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests [TestFixtureSetUp] public void Init() { + TestHelper.InMethod(); + scene = SceneSetupHelpers.SetupScene("Neighbour x", UUID.Random(), 1000, 1000); scene2 = SceneSetupHelpers.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000); scene3 = SceneSetupHelpers.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000);