From c8af20f966e005fb512869299d80be6b83cb70bf Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Mon, 9 Jul 2012 23:08:41 +0100
Subject: This script allows an object to be attached directly from prim
 inventory to another avatar in the scene. Very useful in serious
 game/environment scenarios where its only allowed for trusted creators.
 Threat level Severe

---
 .../Shared/Api/Implementation/OSSL_Api.cs          | 25 ++++++++--
 .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 18 +++++++-
 .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs   |  5 ++
 .../Shared/Tests/OSSL_ApiAttachmentTests.cs        | 53 ++++++++++++++++++++++
 4 files changed, 96 insertions(+), 5 deletions(-)

(limited to 'OpenSim')

diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 61394af..e90f577 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -3190,13 +3190,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
         {
             CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatarFromInventory");
 
+            m_host.AddScriptLPS(1);
+
+            ForceAttachToAvatarFromInventory(m_host.OwnerID, itemName, attachmentPoint);
+        }
+
+        public void osForceAttachToOtherAvatarFromInventory(string rawAvatarId, string itemName, int attachmentPoint)
+        {
+            CheckThreatLevel(ThreatLevel.Severe, "osForceAttachToOtherAvatarFromInventory");
+
+            m_host.AddScriptLPS(1);
+
+            UUID avatarId;
+
+            if (!UUID.TryParse(rawAvatarId, out avatarId))
+                return;
+
+            ForceAttachToAvatarFromInventory(avatarId, itemName, attachmentPoint);
+        }
+
+        public void ForceAttachToAvatarFromInventory(UUID avatarId, string itemName, int attachmentPoint)
+        {
             IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
 
             if (attachmentsModule == null)
                 return;
 
-            m_host.AddScriptLPS(1);
-
             InitLSL();
 
             TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName);
@@ -3219,7 +3238,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                 return;
             }
 
-            ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
+            ScenePresence sp = World.GetScenePresence(avatarId);
 
             if (sp == null)
                 return;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index d38709e..b5416c8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -101,19 +101,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
         // Attachment commands
 
         /// <summary>
-        /// Attach the object containing this script to the avatar that owns it without checking for PERMISSION_ATTACH
+        /// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH
         /// </summary>
         /// <param name='attachment'>The attachment point.  For example, ATTACH_CHEST</param>
         void osForceAttachToAvatar(int attachment);
 
         /// <summary>
-        /// Attach the inventory item in the object containing this script to the avatar that owns it without checking for PERMISSION_ATTACH
+        /// Attach an inventory item in the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH
         /// </summary>
+        /// <remarks>
+        /// Nothing happens if the owner is not in the region.
+        /// </remarks>
         /// <param name='itemName'>Tha name of the item.  If this is not found then a warning is said to the owner</param>
         /// <param name='attachment'>The attachment point.  For example, ATTACH_CHEST</param>
         void osForceAttachToAvatarFromInventory(string itemName, int attachment);
 
         /// <summary>
+        /// Attach an inventory item in the object containing this script to any avatar in the region without asking for PERMISSION_ATTACH
+        /// </summary>
+        /// <remarks>
+        /// Nothing happens if the avatar is not in the region.
+        /// </remarks>
+        /// <param name='rawAvatarId'>The UUID of the avatar to which to attach.  Nothing happens if this is not a UUID</para>
+        /// <param name='itemName'>The name of the item.  If this is not found then a warning is said to the owner</param>
+        /// <param name='attachment'>The attachment point.  For example, ATTACH_CHEST</param>
+        void osForceAttachToOtherAvatarFromInventory(string rawAvatarId, string itemName, int attachmentPoint);
+
+        /// <summary>
         /// Detach the object containing this script from the avatar it is attached to without checking for PERMISSION_ATTACH
         /// </summary>
         /// <remarks>Nothing happens if the object is not attached.</remarks>
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index 692bb0a..b40bdf0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -301,6 +301,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
             m_OSSL_Functions.osForceAttachToAvatarFromInventory(itemName, attachmentPoint);
         }
 
+        public void osForceAttachToOtherAvatarFromInventory(string rawAvatarId, string itemName, int attachmentPoint)
+        {
+            m_OSSL_Functions.osForceAttachToOtherAvatarFromInventory(rawAvatarId, itemName, attachmentPoint);
+        }
+
         public void osForceDetachFromAvatar()
         {
             m_OSSL_Functions.osForceDetachFromAvatar();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs
index 78db2c6..f5aa518 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs
@@ -174,5 +174,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
             List<AvatarAttachment> attachmentsInAppearance = sp.Appearance.GetAttachments();
             Assert.That(attachmentsInAppearance.Count, Is.EqualTo(0));
         }
+
+        [Test]
+        public void TestOsForceAttachToOtherAvatarFromInventory()
+        {
+            TestHelpers.InMethod();
+            TestHelpers.EnableLogging();
+
+            string taskInvObjItemName = "sphere";
+            UUID taskInvObjItemId = UUID.Parse("00000000-0000-0000-0000-100000000000");
+            AttachmentPoint attachPoint = AttachmentPoint.Chin;
+
+            UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(m_scene, "user", "one", 0x1, "pass");
+            UserAccount ua2 = UserAccountHelpers.CreateUserWithInventory(m_scene, "user", "two", 0x2, "pass");
+
+            ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, ua1);
+            SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
+            TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
+
+            new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem);
+            OSSL_Api osslApi = new OSSL_Api();
+            osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem);
+
+            // Create an object embedded inside the first
+            TaskInventoryHelpers.AddSceneObject(m_scene, inWorldObj.RootPart, taskInvObjItemName, taskInvObjItemId, ua1.PrincipalID);
+
+            ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, ua2);
+
+            osslApi.osForceAttachToOtherAvatarFromInventory(sp2.UUID.ToString(), taskInvObjItemName, (int)attachPoint);
+
+            // Check scene presence status
+            Assert.That(sp.HasAttachments(), Is.False);
+            List<SceneObjectGroup> attachments = sp.GetAttachments();
+            Assert.That(attachments.Count, Is.EqualTo(0));
+
+            Assert.That(sp2.HasAttachments(), Is.True);
+            List<SceneObjectGroup> attachments2 = sp2.GetAttachments();
+            Assert.That(attachments2.Count, Is.EqualTo(1));
+            SceneObjectGroup attSo = attachments2[0];
+            Assert.That(attSo.Name, Is.EqualTo(taskInvObjItemName));
+            Assert.That(attSo.OwnerID, Is.EqualTo(ua2.PrincipalID));
+            Assert.That(attSo.AttachmentPoint, Is.EqualTo((uint)attachPoint));
+            Assert.That(attSo.IsAttachment);
+            Assert.That(attSo.UsesPhysics, Is.False);
+            Assert.That(attSo.IsTemporary, Is.False);
+
+            // Check appearance status
+            List<AvatarAttachment> attachmentsInAppearance = sp.Appearance.GetAttachments();
+            Assert.That(attachmentsInAppearance.Count, Is.EqualTo(0));
+
+            List<AvatarAttachment> attachmentsInAppearance2 = sp2.Appearance.GetAttachments();
+            Assert.That(attachmentsInAppearance2.Count, Is.EqualTo(1));
+            Assert.That(sp2.Appearance.GetAttachpoint(attachmentsInAppearance2[0].ItemID), Is.EqualTo((uint)attachPoint));
+        }
     }
 }
\ No newline at end of file
-- 
cgit v1.1