diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs
index f6b99dc20a..efbe0db3d1 100644
--- a/OpenSim/Framework/Servers/VersionInfo.cs
+++ b/OpenSim/Framework/Servers/VersionInfo.cs
@@ -29,7 +29,7 @@ namespace OpenSim
{
public class VersionInfo
{
- private const string VERSION_NUMBER = "0.8.0.1";
+ private const string VERSION_NUMBER = "0.8.0.2";
private const Flavour VERSION_FLAVOUR = Flavour.Post_Fixes;
public enum Flavour
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 3489873836..5cc56065dd 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -1227,16 +1227,21 @@ namespace OpenSim.Region.Framework.Scenes
agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move);
if (taskItem.InvType == (int)InventoryType.Object)
{
- uint perms = taskItem.CurrentPermissions;
+ // Bake the new base permissions from folded permissions
+ // The folded perms are in the lowest 3 bits of the current perms
+ // We use base permissions here to avoid baking the "Locked" status
+ // into the item as it is passed.
+ uint perms = taskItem.BasePermissions & taskItem.NextPermissions;
PermissionsUtil.ApplyFoldedPermissions(taskItem.CurrentPermissions, ref perms);
+ // Avoid the "lock trap" - move must always be enabled but the above may remove it
+ // Add it back here.
agentItem.BasePermissions = perms | (uint)PermissionMask.Move;
- agentItem.CurrentPermissions = agentItem.BasePermissions;
- }
- else
- {
- agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions;
+ // Newly given items cannot be "locked" on rez. Make sure by
+ // setting current equal to base.
}
+ agentItem.CurrentPermissions = agentItem.BasePermissions;
+
agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
agentItem.NextPermissions = taskItem.NextPermissions;
agentItem.EveryOnePermissions = taskItem.EveryonePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move);
@@ -1935,8 +1940,11 @@ namespace OpenSim.Region.Framework.Scenes
/// Rez a script into a prim's inventory from another prim
///
///
- ///
- ///
+ ///
+ ///
+ ///
+ ///
+ ///
public void RezScriptFromPrim(UUID srcId, SceneObjectPart srcPart, UUID destId, int pin, int running, int start_param)
{
TaskInventoryItem srcTaskItem = srcPart.Inventory.GetInventoryItem(srcId);
@@ -1956,12 +1964,11 @@ namespace OpenSim.Region.Framework.Scenes
if (destPart == null)
{
m_log.ErrorFormat(
- "[PRIM INVENTORY]: " +
- "Could not find script for ID {0}",
- destId);
+ "[PRIM INVENTORY]: Could not find part {0} to insert script item {1} from {2} {3} in {4}",
+ destId, srcId, srcPart.Name, srcPart.UUID, Name);
return;
}
-
+
// Must own the object, and have modify rights
if (srcPart.OwnerID != destPart.OwnerID)
{
@@ -1969,12 +1976,14 @@ namespace OpenSim.Region.Framework.Scenes
if ((destPart.GroupID == UUID.Zero) || (destPart.GroupID != srcPart.GroupID) ||
((destPart.GroupMask & (uint)PermissionMask.Modify) == 0))
return;
- } else {
+ }
+ else
+ {
if ((destPart.OwnerMask & (uint)PermissionMask.Modify) == 0)
return;
}
- if (destPart.ScriptAccessPin != pin)
+ if (destPart.ScriptAccessPin == 0 || destPart.ScriptAccessPin != pin)
{
m_log.WarnFormat(
"[PRIM INVENTORY]: " +
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index a950700597..50e4804ef0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -120,6 +120,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected IUrlModule m_UrlModule = null;
protected Dictionary m_userInfoCache = new Dictionary();
protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
+ protected string m_internalObjectHost = "lsl.opensim.local";
+ protected bool m_restrictEmail = false;
protected ISoundModule m_SoundModule = null;
//An array of HTTP/1.1 headers that are not allowed to be used
@@ -193,11 +195,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (seConfigSource != null)
{
+ IConfig lslConfig = seConfigSource.Configs["LL-Functions"];
+ if (lslConfig != null)
+ {
+ m_restrictEmail = lslConfig.GetBoolean("RestrictEmail", m_restrictEmail);
+ }
+
IConfig smtpConfig = seConfigSource.Configs["SMTP"];
if (smtpConfig != null)
{
// there's an smtp config, so load in the snooze time.
EMAIL_PAUSE_TIME = smtpConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME);
+
+ m_internalObjectHost = smtpConfig.GetString("internal_object_host", m_internalObjectHost);
}
}
}
@@ -3387,6 +3397,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return;
}
+ //Restrict email destination to the avatars registered email address?
+ //The restriction only applies if the destination address is not local.
+ if (m_restrictEmail == true && address.Contains(m_internalObjectHost) == false)
+ {
+ UserAccount account =
+ World.UserAccountService.GetUserAccount(
+ World.RegionInfo.ScopeID,
+ m_host.OwnerID);
+
+ if (account == null)
+ {
+ Error("llEmail", "Can't find user account for '" + m_host.OwnerID.ToString() + "'");
+ return;
+ }
+
+ if (String.IsNullOrEmpty(account.Email))
+ {
+ Error("llEmail", "User account has not registered an email address.");
+ return;
+ }
+
+ address = account.Email;
+ }
+
emailModule.SendEmail(m_host.UUID, address, subject, message);
ScriptSleep(EMAIL_PAUSE_TIME * 1000);
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
index 6dd6c170b7..1ad0a9994b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
@@ -45,6 +45,7 @@ using OpenSim.Region.ScriptEngine.Shared.Instance;
using OpenSim.Services.Interfaces;
using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock;
+using PermissionMask = OpenSim.Framework.PermissionMask;
namespace OpenSim.Region.ScriptEngine.Shared.Tests
{
@@ -167,5 +168,123 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
Assert.That(copiedItems[0].Name, Is.EqualTo(inventoryItemName));
}
}
+
+ ///
+ /// Test giving inventory from an object to an avatar that is not the object's owner.
+ ///
+ [Test]
+ public void TestLlGiveInventoryO2DifferentAvatar()
+ {
+ TestHelpers.InMethod();
+ // TestHelpers.EnableLogging();
+
+ UUID user1Id = TestHelpers.ParseTail(0x1);
+ UUID user2Id = TestHelpers.ParseTail(0x2);
+ string inventoryItemName = "item1";
+
+ SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, user1Id, "so1", 0x10);
+ m_scene.AddSceneObject(so1);
+ LSL_Api api = new LSL_Api();
+ api.Initialize(m_engine, so1.RootPart, null, null);
+
+ // Create an object embedded inside the first
+ UUID itemId = TestHelpers.ParseTail(0x20);
+ TaskInventoryHelpers.AddSceneObject(m_scene, so1.RootPart, inventoryItemName, itemId, user1Id);
+
+ UserAccountHelpers.CreateUserWithInventory(m_scene, user2Id);
+
+ api.llGiveInventory(user2Id.ToString(), inventoryItemName);
+
+ InventoryItemBase receivedItem
+ = UserInventoryHelpers.GetInventoryItem(
+ m_scene.InventoryService, user2Id, string.Format("Objects/{0}", inventoryItemName));
+
+ Assert.IsNotNull(receivedItem);
+ }
+
+ ///
+ /// Test giving inventory from an object to an avatar that is not the object's owner and where the next
+ /// permissions do not include mod.
+ ///
+ [Test]
+ public void TestLlGiveInventoryO2DifferentAvatarNoMod()
+ {
+ TestHelpers.InMethod();
+// TestHelpers.EnableLogging();
+
+ UUID user1Id = TestHelpers.ParseTail(0x1);
+ UUID user2Id = TestHelpers.ParseTail(0x2);
+ string inventoryItemName = "item1";
+
+ SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, user1Id, "so1", 0x10);
+ m_scene.AddSceneObject(so1);
+ LSL_Api api = new LSL_Api();
+ api.Initialize(m_engine, so1.RootPart, null, null);
+
+ // Create an object embedded inside the first
+ UUID itemId = TestHelpers.ParseTail(0x20);
+ TaskInventoryItem tii
+ = TaskInventoryHelpers.AddSceneObject(m_scene, so1.RootPart, inventoryItemName, itemId, user1Id);
+ tii.NextPermissions &= ~((uint)PermissionMask.Modify);
+
+ UserAccountHelpers.CreateUserWithInventory(m_scene, user2Id);
+
+ api.llGiveInventory(user2Id.ToString(), inventoryItemName);
+
+ InventoryItemBase receivedItem
+ = UserInventoryHelpers.GetInventoryItem(
+ m_scene.InventoryService, user2Id, string.Format("Objects/{0}", inventoryItemName));
+
+ Assert.IsNotNull(receivedItem);
+ Assert.AreEqual(0, receivedItem.CurrentPermissions & (uint)PermissionMask.Modify);
+ }
+
+ [Test]
+ public void TestLlRemoteLoadScriptPin()
+ {
+ TestHelpers.InMethod();
+// TestHelpers.EnableLogging();
+
+ UUID user1Id = TestHelpers.ParseTail(0x1);
+ UUID user2Id = TestHelpers.ParseTail(0x2);
+
+ SceneObjectGroup sourceSo = SceneHelpers.AddSceneObject(m_scene, 1, user1Id, "sourceSo", 0x10);
+ m_scene.AddSceneObject(sourceSo);
+ LSL_Api api = new LSL_Api();
+ api.Initialize(m_engine, sourceSo.RootPart, null, null);
+ TaskInventoryHelpers.AddScript(m_scene, sourceSo.RootPart, "script", "Hello World");
+
+ SceneObjectGroup targetSo = SceneHelpers.AddSceneObject(m_scene, 1, user1Id, "targetSo", 0x20);
+ SceneObjectGroup otherOwnedTargetSo
+ = SceneHelpers.AddSceneObject(m_scene, 1, user2Id, "otherOwnedTargetSo", 0x30);
+
+ // Test that we cannot load a script when the target pin has never been set (i.e. it is zero)
+ api.llRemoteLoadScriptPin(targetSo.UUID.ToString(), "script", 0, 0, 0);
+ Assert.IsNull(targetSo.RootPart.Inventory.GetInventoryItem("script"));
+
+ // Test that we cannot load a script when the given pin does not match the target
+ targetSo.RootPart.ScriptAccessPin = 5;
+ api.llRemoteLoadScriptPin(targetSo.UUID.ToString(), "script", 3, 0, 0);
+ Assert.IsNull(targetSo.RootPart.Inventory.GetInventoryItem("script"));
+
+ // Test that we cannot load into a prim with a different owner
+ otherOwnedTargetSo.RootPart.ScriptAccessPin = 3;
+ api.llRemoteLoadScriptPin(otherOwnedTargetSo.UUID.ToString(), "script", 3, 0, 0);
+ Assert.IsNull(otherOwnedTargetSo.RootPart.Inventory.GetInventoryItem("script"));
+
+ // Test that we can load a script when given pin and dest pin match.
+ targetSo.RootPart.ScriptAccessPin = 3;
+ api.llRemoteLoadScriptPin(targetSo.UUID.ToString(), "script", 3, 0, 0);
+ TaskInventoryItem insertedItem = targetSo.RootPart.Inventory.GetInventoryItem("script");
+ Assert.IsNotNull(insertedItem);
+
+ // Test that we can no longer load if access pin is unset
+ targetSo.RootPart.Inventory.RemoveInventoryItem(insertedItem.ItemID);
+ Assert.IsNull(targetSo.RootPart.Inventory.GetInventoryItem("script"));
+
+ targetSo.RootPart.ScriptAccessPin = 0;
+ api.llRemoteLoadScriptPin(otherOwnedTargetSo.UUID.ToString(), "script", 3, 0, 0);
+ Assert.IsNull(otherOwnedTargetSo.RootPart.Inventory.GetInventoryItem("script"));
+ }
}
}
\ No newline at end of file
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index 3780e59a6d..b23c7131e1 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -1321,6 +1321,11 @@
; If false then gods cannot execute these functions either.
AllowGodFunctions = false
+ ; Restrict the email address used by llEmail to the address associated with the avatars user account?
+ ; If true then llEmail will only send email to the address in the user account of the avatar who owns the object containing the script.
+ ; If false then email may be sent to any valid email address.
+ RestrictEmail = false
+
; Maximum number of llListen events we allow over the entire region.
; Set this to 0 to have no limit imposed
max_listens_per_region = 1000