From 7375f3c273b19a1713016bb286d79799caf0aa64 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 21 Jun 2009 18:07:19 +0000 Subject: [PATCH] Backporting group permissions to stable. --- OpenSim/Data/MSSQL/MSSQLAssetData.cs | 2 +- .../World/Permissions/PermissionsModule.cs | 288 +++++++++++++----- .../Interfaces/IDynamicTextureManager.cs | 2 + .../Framework/Scenes/Scene.Inventory.cs | 69 ++++- .../Framework/Scenes/Scene.Permissions.cs | 17 ++ 5 files changed, 285 insertions(+), 93 deletions(-) diff --git a/OpenSim/Data/MSSQL/MSSQLAssetData.cs b/OpenSim/Data/MSSQL/MSSQLAssetData.cs index 927b02b751..cd517a3b0e 100644 --- a/OpenSim/Data/MSSQL/MSSQLAssetData.cs +++ b/OpenSim/Data/MSSQL/MSSQLAssetData.cs @@ -38,7 +38,7 @@ namespace OpenSim.Data.MSSQL /// /// A MSSQL Interface for the Asset server /// - internal class MSSQLAssetData : AssetDataBase + public class MSSQLAssetData : AssetDataBase { private const string _migrationStore = "AssetStore"; diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 1987bb9a34..992077efa4 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -36,6 +36,56 @@ using OpenSim.Framework.Communications.Cache; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +// Temporary fix of wrong GroupPowers constants in OpenMetaverse library +enum GroupPowers : long + { + None = 0, + LandEjectAndFreeze = 1, + Invite = 2, + ReturnGroupSet = 2, + Eject = 4, + ReturnNonGroup = 4, + ChangeOptions = 8, + LandGardening = 8, + CreateRole = 16, + DeedObject = 16, + ModerateChat = 32, + DeleteRole = 32, + RoleProperties = 64, + ObjectManipulate = 64, + ObjectSetForSale = 128, + AssignMemberLimited = 128, + AssignMember = 256, + Accountable = 256, + RemoveMember = 512, + SendNotices = 1024, + ChangeActions = 1024, + ChangeIdentity = 2048, + ReceiveNotices = 2048, + StartProposal = 4096, + LandDeed = 4096, + VoteOnProposal = 8192, + LandRelease = 8192, + LandSetSale = 16384, + LandDivideJoin = 32768, + ReturnGroupOwned = 65536, + JoinChat = 65536, + FindPlaces = 131072, + LandChangeIdentity = 262144, + SetLandingPoint = 524288, + ChangeMedia = 1048576, + LandEdit = 2097152, + LandOptions = 4194304, + AllowEditLand = 8388608, + AllowFly = 16777216, + AllowRez = 33554432, + AllowLandmark = 67108864, + AllowVoiceChat = 134217728, + AllowSetHome = 268435456, + LandManageAllowed = 536870912, + LandManageBanned = 1073741824 + } + namespace OpenSim.Region.CoreModules.World.Permissions { public class PermissionsModule : IRegionModule @@ -62,7 +112,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions All, Administrators }; - + #endregion #region Bypass Permissions / Debug Permissions Stuff @@ -129,6 +179,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions m_scene.Permissions.OnAbandonParcel += CanAbandonParcel; m_scene.Permissions.OnReclaimParcel += CanReclaimParcel; m_scene.Permissions.OnDeedParcel += CanDeedParcel; + m_scene.Permissions.OnDeedObject += CanDeedObject; m_scene.Permissions.OnIsGod += IsGod; m_scene.Permissions.OnDuplicateObject += CanDuplicateObject; m_scene.Permissions.OnDeleteObject += CanDeleteObject; //MAYBE FULLY IMPLEMENTED @@ -288,7 +339,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (m_debugPermissions) m_log.Debug("[PERMISSIONS]: " + permissionCalled + " was called from " + m_scene.RegionInfo.RegionName); } - + + // Checks if the given group is active and if the user is a group member + // with the powers requested (powers = 0 for no powers check) + protected bool IsGroupMember(UUID groupID, UUID userID, ulong powers) + { + IClientAPI client = m_scene.GetScenePresence(userID).ControllingClient; + + return ((groupID == client.ActiveGroupId) && (client.ActiveGroupPowers != 0) && + ((powers == 0) || ((client.ActiveGroupPowers & powers) == powers))); + } + /// /// Parse a user set configuration setting /// @@ -331,6 +392,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions /// protected bool IsAdministrator(UUID user) { + if (user == UUID.Zero) return false; + if (m_scene.RegionInfo.MasterAvatarAssignedUUID != UUID.Zero) { if (m_RegionOwnerIsGod && (m_scene.RegionInfo.MasterAvatarAssignedUUID == user)) @@ -351,10 +414,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (profile.UserProfile.GodLevel >= 200) return true; } - //else - //{ - // m_log.ErrorFormat("[PERMISSIONS]: Could not find user {0} for administrator check", user); - //} } return false; @@ -362,6 +421,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions protected bool IsEstateManager(UUID user) { + if (user == UUID.Zero) return false; + return m_scene.RegionInfo.EstateSettings.IsEstateManager(user); } #endregion @@ -433,57 +494,39 @@ namespace OpenSim.Region.CoreModules.World.Permissions objectOwnerMask |= (uint)PrimFlags.ObjectYouOwner | (uint)PrimFlags.ObjectAnyOwner | (uint)PrimFlags.ObjectOwnerModify; // Customize the GroupMask - // uint objectGroupMask = ApplyObjectModifyMasks(task.GroupMask, objflags); + uint objectGroupMask = ApplyObjectModifyMasks(task.GroupMask, objflags); // Customize the EveryoneMask uint objectEveryoneMask = ApplyObjectModifyMasks(task.EveryoneMask, objflags); - - // Hack to allow collaboration until Groups and Group Permissions are implemented - if ((objectEveryoneMask & (uint)PrimFlags.ObjectMove) != 0) - objectEveryoneMask |= (uint)PrimFlags.ObjectModify; - if (m_bypassPermissions) return objectOwnerMask; - + // Object owners should be able to edit their own content if (user == objectOwner) - { return objectOwnerMask; - } - - //// Users should be able to edit what is over their land. - //ILandObject parcel = m_scene.LandChannel.GetLandObject(task.AbsolutePosition.X, task.AbsolutePosition.Y); - //if (parcel != null && parcel.landData.OwnerID == user && m_ParcelOwnerIsGod) - // return objectOwnerMask; - - //// Admin objects should not be editable by the above - //if (IsAdministrator(objectOwner)) - // return objectEveryoneMask; // Estate users should be able to edit anything in the sim - if (IsEstateManager(user) && m_RegionOwnerIsGod && (!IsAdministrator(objectOwner))) + if (IsEstateManager(user) && m_RegionOwnerIsGod && !IsAdministrator(objectOwner)) return objectOwnerMask; // Admin should be able to edit anything in the sim (including admin objects) if (IsAdministrator(user)) return objectOwnerMask; - + // Users should be able to edit what is over their land. ILandObject parcel = m_scene.LandChannel.GetLandObject(task.AbsolutePosition.X, task.AbsolutePosition.Y); if (parcel != null && parcel.landData.OwnerID == user && m_ParcelOwnerIsGod) { - uint responseMask = objectOwnerMask; - // Admin objects should not be editable by the above - if (IsAdministrator(objectOwner)) - { - responseMask = objectEveryoneMask; - } - - return responseMask; + if (!IsAdministrator(objectOwner)) + return objectOwnerMask; } + // Group permissions + if ( ( task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0) ) + return objectGroupMask; + return objectEveryoneMask; } @@ -567,6 +610,13 @@ namespace OpenSim.Region.CoreModules.World.Permissions permission = false; } + // Group members should be able to edit group objects + if ( (group.GroupID != UUID.Zero) && ((m_scene.GetSceneObjectPart(objId).GroupMask & (uint)PermissionMask.Modify) != 0) && IsGroupMember(group.GroupID, currentUser, 0) ) + { + // Return immediately, so that the administrator can shares group objects + return true; + } + // Users should be able to edit what is over their land. ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y); if ((parcel != null) && (parcel.landData.OwnerID == currentUser)) @@ -633,7 +683,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return permission; } - protected bool GenericParcelPermission(UUID user, ILandObject parcel) + protected bool GenericParcelPermission(UUID user, ILandObject parcel, ulong groupPowers) { bool permission = false; @@ -642,9 +692,9 @@ namespace OpenSim.Region.CoreModules.World.Permissions permission = true; } - if (parcel.landData.IsGroupOwned) + if( ( parcel.landData.GroupID != UUID.Zero) && IsGroupMember(parcel.landData.GroupID, user, groupPowers) ) { - // TODO: Need to do some extra checks here. Requires group code. + permission = true; } if (IsEstateManager(user)) @@ -659,12 +709,39 @@ namespace OpenSim.Region.CoreModules.World.Permissions return permission; } + + protected bool GenericParcelOwnerPermission(UUID user, ILandObject parcel, ulong groupPowers) + { + bool permission = false; - protected bool GenericParcelPermission(UUID user, Vector3 pos) + if (parcel.landData.OwnerID == user) + { + permission = true; + } + + if( parcel.landData.IsGroupOwned && IsGroupMember(parcel.landData.GroupID, user, groupPowers) ) + { + permission = true; + } + + if (IsEstateManager(user)) + { + permission = true; + } + + if (IsAdministrator(user)) + { + permission = true; + } + + return permission; + } + + protected bool GenericParcelPermission(UUID user, Vector3 pos, ulong groupPowers) { ILandObject parcel = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); if (parcel == null) return false; - return GenericParcelPermission(user, parcel); + return GenericParcelPermission(user, parcel, groupPowers); } #endregion @@ -673,8 +750,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - - return GenericParcelPermission(user, parcel); + + return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandRelease); } private bool CanReclaimParcel(UUID user, ILandObject parcel, Scene scene) @@ -682,7 +759,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericParcelPermission(user, parcel); + return GenericParcelOwnerPermission(user, parcel, 0); } private bool CanDeedParcel(UUID user, ILandObject parcel, Scene scene) @@ -696,10 +773,24 @@ namespace OpenSim.Region.CoreModules.World.Permissions ScenePresence sp = scene.GetScenePresence(user); IClientAPI client = sp.ControllingClient; - if ((client.GetGroupPowers(parcel.landData.GroupID) & (long)GroupPowers.LandDeed) == 0) + if ((client.GetGroupPowers(parcel.landData.GroupID) & (ulong)GroupPowers.LandDeed) == 0) return false; - return GenericParcelPermission(user, parcel); + return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandDeed); + } + + private bool CanDeedObject(UUID user, UUID group, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + ScenePresence sp = scene.GetScenePresence(user); + IClientAPI client = sp.ControllingClient; + + if((client.GetGroupPowers(group) & (ulong)GroupPowers.DeedObject) == 0) + return false; + + return true; } private bool IsGod(UUID user, Scene scene) @@ -720,17 +811,23 @@ namespace OpenSim.Region.CoreModules.World.Permissions //They can't even edit the object return false; } - + SceneObjectPart part = scene.GetSceneObjectPart(objectID); if (part == null) return false; - if ((part.OwnerMask & PERM_COPY) == 0) - return false; + if (part.OwnerID == owner) + return ((part.OwnerMask & PERM_COPY) != 0); - if ((part.ParentGroup.GetEffectivePermissions() & PERM_COPY) == 0) - return false; + if (part.GroupID != UUID.Zero) + { + if ((part.OwnerID == part.GroupID) && ((owner != part.LastOwnerID) || ((part.GroupMask & PERM_TRANS) == 0))) + return false; + if ((part.GroupMask & PERM_COPY) == 0) + return false; + } + //If they can rez, they can duplicate return CanRezObject(objectCount, owner, objectPosition, scene); } @@ -767,11 +864,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions part = m_scene.GetSceneObjectPart(objectID); } - // TODO: add group support! - // - if (part.OwnerID != editorID) - return false; - return GenericObjectPermission(editorID, objectID, false); } @@ -780,7 +872,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericParcelPermission(user, parcel); + return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandDivideJoin); } /// @@ -861,10 +953,19 @@ namespace OpenSim.Region.CoreModules.World.Permissions return false; if (part.OwnerID != user) - return false; + { + if (part.GroupID == UUID.Zero) + return false; - if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) + if( !IsGroupMember(part.GroupID, user, 0) ) + return false; + + if ((part.GroupMask & (uint)PermissionMask.Modify) == 0) + return false; + } else { + if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) return false; + } TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard); @@ -872,7 +973,13 @@ namespace OpenSim.Region.CoreModules.World.Permissions return false; if (ti.OwnerID != user) + { + if (ti.GroupID == UUID.Zero) + return false; + + if( !IsGroupMember(ti.GroupID, user, 0) ) return false; + } // Require full perms if ((ti.CurrentPermissions & @@ -1044,8 +1151,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions return true; } - //TODO: check for group rights - if (!m_scene.Entities.ContainsKey(objectID)) { return false; @@ -1058,7 +1163,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions } - if (GenericParcelPermission(task.OwnerID, newPoint)) + if (GenericParcelPermission(task.OwnerID, newPoint, 0)) { return true; } @@ -1089,14 +1194,13 @@ namespace OpenSim.Region.CoreModules.World.Permissions (int)Parcel.ParcelFlags.CreateObjects) permission = true; - //TODO: check for group rights - if (IsAdministrator(owner)) { permission = true; } - if (GenericParcelPermission(owner, objectPosition)) + // Powers are zero, because GroupPowers.AllowRez is not a precondition for rezzing objects + if (GenericParcelPermission(owner, objectPosition, 0)) { permission = true; } @@ -1126,7 +1230,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericParcelPermission(user, parcel); + return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandSetSale); } private bool CanTakeObject(UUID objectID, UUID stealer, Scene scene) @@ -1142,7 +1246,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - bool permission = GenericObjectPermission(userID, objectID,false); + bool permission = GenericObjectPermission(userID, objectID, false); if (!permission) { if (!m_scene.Entities.ContainsKey(objectID)) @@ -1209,7 +1313,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return true; // Land owner can terraform too - if (parcel != null && GenericParcelPermission(user, parcel)) + if (parcel != null && GenericParcelPermission(user, parcel, (ulong)GroupPowers.AllowEditLand)) return true; return false; @@ -1276,20 +1380,35 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (part == null) return false; - + if (part.OwnerID != user) + { + if (part.GroupID == UUID.Zero) return false; - if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) - return false; + if( !IsGroupMember(part.GroupID, user, 0) ) + return false; + + if ((part.GroupMask & (uint)PermissionMask.Modify) == 0) + return false; + } else { + if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) + return false; + } TaskInventoryItem ti = part.Inventory.GetInventoryItem(script); if (ti == null) return false; - + if (ti.OwnerID != user) - return false; + { + if (ti.GroupID == UUID.Zero) + return false; + + if( !IsGroupMember(ti.GroupID, user, 0) ) + return false; + } // Require full perms if ((ti.CurrentPermissions & @@ -1354,9 +1473,15 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (part == null) return false; - + if (part.OwnerID != user) - return false; + { + if (part.GroupID == UUID.Zero) + return false; + + if( !IsGroupMember(part.GroupID, user, 0) ) + return false; + } if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) return false; @@ -1367,7 +1492,13 @@ namespace OpenSim.Region.CoreModules.World.Permissions return false; if (ti.OwnerID != user) - return false; + { + if (ti.GroupID == UUID.Zero) + return false; + + if( !IsGroupMember(ti.GroupID, user, 0) ) + return false; + } // Notecards are always readable unless no copy // @@ -1380,7 +1511,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return true; } - #endregion + #endregion private bool CanLinkObject(UUID userID, UUID objectID) { @@ -1549,7 +1680,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (parcel.landData.OwnerID != client.AgentId) return false; } - break; + return GenericParcelOwnerPermission(client.AgentId, parcel, (ulong)GroupPowers.ReturnGroupOwned); case (uint)ObjectReturnType.Group: if (parcel.landData.OwnerID != client.AgentId) { @@ -1573,16 +1704,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions return true; } } - break; + return GenericParcelOwnerPermission(client.AgentId, parcel, (ulong)GroupPowers.ReturnGroupSet); case (uint)ObjectReturnType.Other: if ((powers & (long)GroupPowers.ReturnNonGroup) != 0) return true; + return GenericParcelOwnerPermission(client.AgentId, parcel, (ulong)GroupPowers.ReturnNonGroup); break; case (uint)ObjectReturnType.List: break; } - return GenericParcelPermission(client.AgentId, parcel); + return GenericParcelPermission(client.AgentId, parcel, 0); } } } diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs index 9b29209a48..74d80d5ffd 100644 --- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs +++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs @@ -30,8 +30,10 @@ using OpenMetaverse; namespace OpenSim.Region.Framework.Interfaces { + public interface IDynamicTextureManager { + void RegisterRender(string handleType, IDynamicTextureRender render); void ReturnData(UUID id, byte[] data); diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 696974ac15..9f23595943 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1528,10 +1528,14 @@ namespace OpenSim.Region.Framework.Scenes return; if (part.OwnerID != remoteClient.AgentId) - return; - - if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) - return; + { + // Group permissions + if ( (part.GroupID == UUID.Zero) || (remoteClient.GetGroupPowers(part.GroupID) == 0) || ((part.GroupMask & (uint)PermissionMask.Modify) == 0) ) + return; + } else { + if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) + return; + } if (!Permissions.CanCreateObjectInventory( itemBase.InvType, part.UUID, remoteClient.AgentId)) @@ -1600,13 +1604,18 @@ namespace OpenSim.Region.Framework.Scenes destId); return; } - + // Must own the object, and have modify rights if (srcPart.OwnerID != destPart.OwnerID) - return; - - if ((destPart.OwnerMask & (uint)PermissionMask.Modify) == 0) - return; + { + // Group permissions + if ( (destPart.GroupID == UUID.Zero) || (destPart.GroupID != srcPart.GroupID) || + ((destPart.GroupMask & (uint)PermissionMask.Modify) == 0) ) + return; + } else { + if ((destPart.OwnerMask & (uint)PermissionMask.Modify) == 0) + return; + } if (destPart.ScriptAccessPin != pin) { @@ -2675,16 +2684,48 @@ namespace OpenSim.Region.Framework.Scenes void ObjectOwner(IClientAPI remoteClient, UUID ownerID, UUID groupID, List localIDs) { if (!Permissions.IsGod(remoteClient.AgentId)) - return; + { + if (ownerID != UUID.Zero) + return; + + if (!Permissions.CanDeedObject(remoteClient.AgentId, groupID)) + return; + } + + List groups = new List(); foreach (uint localID in localIDs) { SceneObjectPart part = GetSceneObjectPart(localID); - if (part != null && part.ParentGroup != null) + if (!groups.Contains(part.ParentGroup)) + groups.Add(part.ParentGroup); + } + + foreach (SceneObjectGroup sog in groups) + { + if (ownerID != null) { - part.ParentGroup.SetOwnerId(ownerID); - part.Inventory.ChangeInventoryOwner(ownerID); - part.ParentGroup.SetGroup(groupID, remoteClient); + sog.SetOwnerId(ownerID); + sog.SetGroup(groupID, remoteClient); + + foreach (SceneObjectPart child in sog.Children.Values) + child.Inventory.ChangeInventoryOwner(ownerID); + } + else + { + if (!Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)) + continue; + + if (sog.GroupID != groupID) + continue; + + foreach (SceneObjectPart child in sog.Children.Values) + { + child.LastOwnerID = child.OwnerID; + child.Inventory.ChangeInventoryOwner(groupID); + } + + sog.SetOwnerId(groupID); } } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs index b6f3feed37..faddcb0f6e 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs @@ -68,6 +68,7 @@ namespace OpenSim.Region.Framework.Scenes public delegate bool AbandonParcelHandler(UUID user, ILandObject parcel, Scene scene); public delegate bool ReclaimParcelHandler(UUID user, ILandObject parcel, Scene scene); public delegate bool DeedParcelHandler(UUID user, ILandObject parcel, Scene scene); + public delegate bool DeedObjectHandler(UUID user, UUID group, Scene scene); public delegate bool BuyLandHandler(UUID user, ILandObject parcel, Scene scene); public delegate bool LinkObjectHandler(UUID user, UUID objectID); public delegate bool DelinkObjectHandler(UUID user, UUID objectID); @@ -125,6 +126,7 @@ namespace OpenSim.Region.Framework.Scenes public event AbandonParcelHandler OnAbandonParcel; public event ReclaimParcelHandler OnReclaimParcel; public event DeedParcelHandler OnDeedParcel; + public event DeedObjectHandler OnDeedObject; public event BuyLandHandler OnBuyLand; public event LinkObjectHandler OnLinkObject; public event DelinkObjectHandler OnDelinkObject; @@ -715,6 +717,21 @@ namespace OpenSim.Region.Framework.Scenes return true; } + public bool CanDeedObject(UUID user, UUID group) + { + DeedObjectHandler handler = OnDeedObject; + if (handler != null) + { + Delegate[] list = handler.GetInvocationList(); + foreach (DeedObjectHandler h in list) + { + if (h(user, group, m_scene) == false) + return false; + } + } + return true; + } + public bool CanBuyLand(UUID user, ILandObject parcel) { BuyLandHandler handler = OnBuyLand;