diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 1267993d1f..eedba9d2fa 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -1112,7 +1112,7 @@ namespace OpenSim.Framework /// void SendKillObject(List localID); - void SendPartFullUpdate(ISceneEntity ent, uint? parentID); +// void SendPartFullUpdate(ISceneEntity ent, uint? parentID); void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs); void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index df3466815b..8ba1ba399d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4126,14 +4126,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Vector3 mycamera = Vector3.Zero; Vector3 mypos = Vector3.Zero; ScenePresence mysp = (ScenePresence)SceneAgent; - if(mysp != null && !mysp.IsDeleted) + + // we should have a presence + if(mysp == null) + return; + + if(doCulling) { cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f; // mycamera = mysp.CameraPosition; mypos = mysp.AbsolutePosition; } - else - doCulling = false; while (maxUpdatesBytes > 0) { @@ -4330,7 +4333,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (update.Entity is ScenePresence) ablock = CreateAvatarUpdateBlock((ScenePresence)update.Entity); else - ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId); + ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, mysp); objectUpdateBlocks.Add(ablock); objectUpdates.Value.Add(update); maxUpdatesBytes -= ablock.Length; @@ -4462,6 +4465,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } // hack.. dont use +/* public void SendPartFullUpdate(ISceneEntity ent, uint? parentID) { if (ent is SceneObjectPart) @@ -4472,7 +4476,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP packet.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; - ObjectUpdatePacket.ObjectDataBlock blk = CreatePrimUpdateBlock(part, this.m_agentId); + ObjectUpdatePacket.ObjectDataBlock blk = CreatePrimUpdateBlock(part, mysp); if (parentID.HasValue) { blk.ParentID = parentID.Value; @@ -4488,7 +4492,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // updatesThisCall, Name, SceneAgent.IsChildAgent ? "child" : "root", Scene.Name); // } - +*/ public void ReprioritizeUpdates() { lock (m_entityUpdates.SyncRoot) @@ -5726,7 +5730,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP return update; } - protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID) +// protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID) + protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, ScenePresence sp) { byte[] objectData = new byte[60]; data.RelativePosition.ToBytes(objectData, 0); @@ -5826,12 +5831,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region PrimFlags - PrimFlags flags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(recipientID, data.UUID); + PrimFlags flags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(sp, data.UUID); // Don't send the CreateSelected flag to everyone flags &= ~PrimFlags.CreateSelected; - if (recipientID == data.OwnerID) + if (sp.UUID == data.OwnerID) { if (data.CreateSelected) { diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 75d90f363f..094da2b66a 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -479,7 +479,32 @@ namespace OpenSim.Region.CoreModules.World.Permissions return false; } +/* + private bool CheckGroupPowers(ScenePresence sp, UUID groupID, ulong powersMask) + { + if(sp == null || sp.ControllingClient == null) + return false; + + ulong grpPowers = sp.ControllingClient.GetGroupPowers(groupID); + return (grpPowers & powersMask) != 0; + } + + private bool CheckActiveGroupPowers(ScenePresence sp, UUID groupID, ulong powersMask) + { + if(sp == null || sp.ControllingClient == null) + return false; + + if(sp.ControllingClient.ActiveGroupId != groupID) + return false; + // activeGroupPowers only get current selected role powers, at least with xmlgroups. + // lets get any role avoiding the extra burden of user also having to change role + // ulong grpPowers = sp.ControllingClient.ActiveGroupPowers(groupID); + ulong grpPowers = sp.ControllingClient.GetGroupPowers(groupID); + + return (grpPowers & powersMask) != 0; + } +*/ /// /// Parse a user set configuration setting /// @@ -605,73 +630,150 @@ namespace OpenSim.Region.CoreModules.World.Permissions } #region Object Permissions +#pragma warning disable 0612 + const uint DEFAULT_FLAGS = (uint)~( + PrimFlags.ObjectCopy | // Tells client you can copy the object + PrimFlags.ObjectModify | // tells client you can modify the object + PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) + PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it + PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object + PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object + PrimFlags.ObjectOwnerModify // Tells client that you're the owner of the object + ); - public uint GenerateClientFlags(UUID user, UUID objID) + const uint NOT_DEFAULT_FLAGS = (uint)~( + PrimFlags.ObjectCopy | // Tells client you can copy the object + PrimFlags.ObjectModify | // tells client you can modify the object + PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) + PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it + PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object + PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object + PrimFlags.ObjectOwnerModify // Tells client that you're the owner of the object + ); +#pragma warning restore 0612 + + const uint EXTRAOWNERMASK = (uint)( + PrimFlags.ObjectYouOwner | + PrimFlags.ObjectAnyOwner + ); + + const uint EXTRAGODMASK = (uint)( + PrimFlags.ObjectYouOwner | + PrimFlags.ObjectAnyOwner | + PrimFlags.ObjectOwnerModify | + PrimFlags.ObjectModify | + PrimFlags.ObjectMove + ); + + public uint GenerateClientFlags(ScenePresence sp, uint curEffectivePerms, UUID objID) { - // Here's the way this works, - // ObjectFlags and Permission flags are two different enumerations - // ObjectFlags, however, tells the client to change what it will allow the user to do. - // So, that means that all of the permissions type ObjectFlags are /temporary/ and only - // supposed to be set when customizing the objectflags for the client. - - // These temporary objectflags get computed and added in this function based on the - // Permission mask that's appropriate! - // Outside of this method, they should never be added to objectflags! - // -teravus + if(sp == null || curEffectivePerms == 0) + return (uint)0; SceneObjectPart task = m_scene.GetSceneObjectPart(objID); // this shouldn't ever happen.. return no permissions/objectflags. if (task == null) return (uint)0; - - uint objflags = task.GetEffectiveObjectFlags(); - UUID objectOwner = task.OwnerID; - - + // Remove any of the objectFlags that are temporary. These will get added back if appropriate - // in the next bit of code + uint objflags = curEffectivePerms & NOT_DEFAULT_FLAGS ; - // libomv will moan about PrimFlags.ObjectYouOfficer being - // deprecated -#pragma warning disable 0612 - objflags &= (uint) - ~(PrimFlags.ObjectCopy | // Tells client you can copy the object - PrimFlags.ObjectModify | // tells client you can modify the object - PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) - PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it - PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object - PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object - PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object - PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set - ); -#pragma warning restore 0612 + uint returnMask; - // Creating the three ObjectFlags options for this method to choose from. - // Customize the OwnerMask - uint objectOwnerMask = ApplyObjectModifyMasks(task.OwnerMask, objflags); - objectOwnerMask |= (uint)PrimFlags.ObjectYouOwner | (uint)PrimFlags.ObjectAnyOwner | (uint)PrimFlags.ObjectOwnerModify; - - // Customize the GroupMask - uint objectGroupMask = ApplyObjectModifyMasks(task.GroupMask, objflags); - - // Customize the EveryoneMask - uint objectEveryoneMask = ApplyObjectModifyMasks(task.EveryoneMask, objflags); - if (objectOwner != UUID.Zero) - objectEveryoneMask |= (uint)PrimFlags.ObjectAnyOwner; - - PermissionClass permissionClass = GetPermissionClass(user, task); - - switch (permissionClass) + // gods have owner rights with Modify and Move always on + if(sp.IsGod) { - case PermissionClass.Owner: - return objectOwnerMask; - case PermissionClass.Group: - return objectGroupMask | objectEveryoneMask; - case PermissionClass.Everyone: - default: - return objectEveryoneMask; + returnMask = ApplyObjectModifyMasks(task.OwnerMask, objflags); + returnMask |= EXTRAGODMASK; + return returnMask; } + + //bypass option == owner rights + if (m_bypassPermissions) + { + returnMask = ApplyObjectModifyMasks(task.OwnerMask, objflags); + returnMask |= EXTRAOWNERMASK; + if((returnMask & (uint)PrimFlags.ObjectModify) != 0) + returnMask |= (uint)PrimFlags.ObjectOwnerModify; + return returnMask; + } + + UUID taskOwnerID = task.OwnerID; + UUID spID = sp.UUID; + + // owner + if (spID == taskOwnerID) + { + returnMask = ApplyObjectModifyMasks(task.OwnerMask, objflags); + returnMask |= EXTRAOWNERMASK; + if((returnMask & (uint)PrimFlags.ObjectModify) != 0) + returnMask |= (uint)PrimFlags.ObjectOwnerModify; + return returnMask; + } + + // if not god or owner, do attachments as everyone + if(task.ParentGroup.IsAttachment) + { + returnMask = ApplyObjectModifyMasks(task.EveryoneMask, objflags); + if (taskOwnerID != UUID.Zero) + returnMask |= (uint)PrimFlags.ObjectAnyOwner; + return returnMask; + } + + // if friends with rights then owner + if (IsFriendWithPerms(spID, taskOwnerID)) + { + returnMask = ApplyObjectModifyMasks(task.OwnerMask, objflags); + returnMask |= EXTRAOWNERMASK; + if((returnMask & (uint)PrimFlags.ObjectModify) != 0) + returnMask |= (uint)PrimFlags.ObjectOwnerModify; + return returnMask; + } + + // group owned or shared ? + UUID taskGroupID = task.GroupID; + IClientAPI client = sp.ControllingClient; + if(taskGroupID != UUID.Zero && client != null && client.IsGroupMember(taskGroupID)) + { + if(taskGroupID == taskOwnerID) + { + // object is owned by group, owner rights and group role powers do apply + if((client.GetGroupPowers(taskGroupID) & (ulong)GroupPowers.ObjectManipulate) != 0) + // instead forcing active group can be safeguard againts casual mistakes ?? + //if(CheckActiveGroupPowers(sp, task.GroupID, (ulong)GroupPowers.ObjectManipulate)) + { + returnMask = ApplyObjectModifyMasks(task.OwnerMask, objflags); + returnMask |= + (uint)PrimFlags.ObjectGroupOwned | + (uint)PrimFlags.ObjectAnyOwner; + if((returnMask & (uint)PrimFlags.ObjectModify) != 0) + returnMask |= (uint)PrimFlags.ObjectOwnerModify; + return returnMask; + } + else + { + // no special rights + returnMask = ApplyObjectModifyMasks(task.EveryoneMask, objflags); + returnMask |= (uint)PrimFlags.ObjectAnyOwner; + return returnMask; + } + } + else + { + // group sharing + returnMask = ApplyObjectModifyMasks(task.GroupMask, objflags); + if (taskOwnerID != UUID.Zero) + returnMask |= (uint)PrimFlags.ObjectAnyOwner; + return returnMask; + } + } + + // fallback is everyone rights + returnMask = ApplyObjectModifyMasks(task.EveryoneMask, objflags); + if (taskOwnerID != UUID.Zero) + returnMask |= (uint)PrimFlags.ObjectAnyOwner; + return returnMask; } private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask) @@ -702,6 +804,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return objectFlagsMask; } + // OARs need this method that handles offline users public PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj) { if (obj == null) @@ -715,31 +818,19 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (user == objectOwner) return PermissionClass.Owner; - if (IsFriendWithPerms(user, objectOwner) && !obj.ParentGroup.IsAttachment) - return PermissionClass.Owner; - - // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set - if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner)) - return PermissionClass.Owner; - // Admin should be able to edit anything in the sim (including admin objects) if (IsAdministrator(user)) return PermissionClass.Owner; -/* to review later - // Users should be able to edit what is over their land. - Vector3 taskPos = obj.AbsolutePosition; - ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y); - if (parcel != null && parcel.LandData.OwnerID == user && m_ParcelOwnerIsGod) + if(!obj.ParentGroup.IsAttachment) { - // Admin objects should not be editable by the above - if (!IsAdministrator(objectOwner)) + if (IsFriendWithPerms(user, objectOwner) ) return PermissionClass.Owner; + + // Group permissions + if (obj.GroupID != UUID.Zero && IsGroupMember(obj.GroupID, user, 0)) + return PermissionClass.Group; } -*/ - // Group permissions - if ((obj.GroupID != UUID.Zero) && IsGroupMember(obj.GroupID, user, 0)) - return PermissionClass.Group; return PermissionClass.Everyone; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs index 893b38c152..e045c437de 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs @@ -37,7 +37,7 @@ using OpenSim.Region.Framework.Interfaces; namespace OpenSim.Region.Framework.Scenes { #region Delegates - public delegate uint GenerateClientFlagsHandler(UUID userID, UUID objectID); + public delegate uint GenerateClientFlagsHandler(ScenePresence sp, uint curEffectivePerms, UUID objectID); public delegate void SetBypassPermissionsHandler(bool value); public delegate bool BypassPermissionsHandler(); public delegate bool PropagatePermissionsHandler(); @@ -167,7 +167,7 @@ namespace OpenSim.Region.Framework.Scenes #region Object Permission Checks - public uint GenerateClientFlags(UUID userID, UUID objectID) + public uint GenerateClientFlags(ScenePresence sp, UUID objectID) { // libomv will moan about PrimFlags.ObjectYouOfficer being // obsolete... @@ -179,8 +179,7 @@ namespace OpenSim.Region.Framework.Scenes PrimFlags.ObjectTransfer | PrimFlags.ObjectYouOwner | PrimFlags.ObjectAnyOwner | - PrimFlags.ObjectOwnerModify | - PrimFlags.ObjectYouOfficer; + PrimFlags.ObjectOwnerModify; #pragma warning restore 0612 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); @@ -196,7 +195,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handlerGenerateClientFlags.GetInvocationList(); foreach (GenerateClientFlagsHandler check in list) { - perms &= check(userID, objectID); + perms &= check(sp, perms, objectID); } } return perms; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 5928764a24..bf991c691d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2233,7 +2233,8 @@ namespace OpenSim.Region.Framework.Scenes { if (part.OwnerID != userId) { - part.LastOwnerID = part.OwnerID; + if(part.GroupID != part.OwnerID) + part.LastOwnerID = part.OwnerID; part.OwnerID = userId; } });