From 58c53c41de2cae0bb041a2e8121792e136d1edb2 Mon Sep 17 00:00:00 2001
From: Diva Canto
Date: Sat, 21 May 2011 16:48:00 -0700
Subject: Fixed permissions bug related to friends in PermissionsModule. Added
 FriendsData[] GetFriends(string principalID) to IFriendsData and FriendInfo[]
 GetFriends(string PrincipalID) to IFriendsService. Refactored some more in
 the FriendsModule. Made client get notification of local friends permissions
 upon HGLogin. HG Friends object permissions work.

---
 .../CoreModules/Avatar/Friends/FriendsModule.cs    | 103 +++++---
 .../CoreModules/Avatar/Friends/HGFriendsModule.cs  | 259 +++++++--------------
 .../World/Permissions/PermissionsModule.cs         |  41 ++--
 3 files changed, 180 insertions(+), 223 deletions(-)

(limited to 'OpenSim/Region/CoreModules')

diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 21cd924..4879d20 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
             }
         }
 
-        private static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0];
+        protected static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0];
         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
 
         protected List<Scene> m_Scenes = new List<Scene>();
@@ -187,6 +187,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
         {
             if (!m_Enabled)
                 return;
+            m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name);
 
             m_Scenes.Add(scene);
             scene.RegisterModuleInterface<IFriendsModule>(this);
@@ -221,13 +222,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
 
         #endregion
 
-        public uint GetFriendPerms(UUID principalID, UUID friendID)
+        public virtual uint GetFriendPerms(UUID principalID, UUID friendID)
         {
             FriendInfo[] friends = GetFriends(principalID);
-            foreach (FriendInfo fi in friends)
+            FriendInfo finfo = GetFriend(friends, friendID);
+            if (finfo != null)
             {
-                if (fi.Friend == friendID.ToString())
-                    return (uint)fi.TheirFlags;
+                return (uint)finfo.TheirFlags;
             }
 
             return 0;
@@ -241,14 +242,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
             client.OnTerminateFriendship += OnTerminateFriendship;
             client.OnGrantUserRights += OnGrantUserRights;
 
-            Util.FireAndForget(delegate { FetchFriendslist(client.AgentId); });
+            Util.FireAndForget(delegate { FetchFriendslist(client); });
         }
 
         /// Fetch the friends list or increment the refcount for the existing 
         /// friends list
         /// Returns true if the list was fetched, false if it wasn't
-        protected virtual bool FetchFriendslist(UUID agentID)
+        protected virtual bool FetchFriendslist(IClientAPI client)
         {
+            UUID agentID = client.AgentId;
             lock (m_Friends)
             {
                 UserFriendData friendsData;
@@ -261,7 +263,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
                 {
                     friendsData = new UserFriendData();
                     friendsData.PrincipalID = agentID;
-                    friendsData.Friends = FriendsService.GetFriends(agentID);
+                    friendsData.Friends = GetFriendsFromService(client);
                     friendsData.Refcount = 1;
 
                     m_Friends[agentID] = friendsData;
@@ -270,6 +272,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
             }
         }
 
+        protected virtual FriendInfo[] GetFriendsFromService(IClientAPI client)
+        {
+            return FriendsService.GetFriends(client.AgentId);
+        }
+
         private void OnClientClosed(UUID agentID, Scene scene)
         {
             ScenePresence sp = scene.GetScenePresence(agentID);
@@ -293,8 +300,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
 
         private void OnMakeRootAgent(ScenePresence sp)
         {
-            UUID agentID = sp.ControllingClient.AgentId;
-            UpdateFriendsCache(agentID);
+            UpdateFriendsCache(sp.ControllingClient);
         }
 
         private void OnClientLogin(IClientAPI client)
@@ -309,7 +315,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
                 m_NeedsListOfFriends.Add(agentID);
         }
 
-        public void SendFriendsOnlineIfNeeded(IClientAPI client)
+        public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client)
         {
             UUID agentID = client.AgentId;
 
@@ -317,7 +323,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
             lock (m_NeedsListOfFriends)
             {
                 if (!m_NeedsListOfFriends.Remove(agentID))
-                    return;
+                    return false;
             }
 
             // Send the friends online
@@ -366,6 +372,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
                 // Finally
                 LocalFriendshipOffered(agentID, im);
             }
+
+            return true;
         }
 
         protected virtual string FriendshipMessage(string friendID)
@@ -579,7 +587,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
             StoreFriendships(agentID, friendID);
 
             // Update the local cache
-            UpdateFriendsCache(agentID);
+            UpdateFriendsCache(client);
 
             //
             // Notify the friend
@@ -647,7 +655,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
             DeleteFriendship(agentID, exfriendID);
 
             // Update local cache
-            UpdateFriendsCache(agentID);
+            UpdateFriendsCache(client);
 
             client.SendTerminateFriend(exfriendID);
 
@@ -679,23 +687,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
 
         private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights)
         {
+            m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target);
+
             FriendInfo[] friends = GetFriends(remoteClient.AgentId);
             if (friends.Length == 0)
+            {
+                m_log.DebugFormat("[XXX]: agent {0} has no friends", requester);
                 return;
+            }
 
-            m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target);
             // Let's find the friend in this user's friend list
-            FriendInfo friend = null;
-            foreach (FriendInfo fi in friends)
-            {
-                if (fi.Friend == target.ToString())
-                    friend = fi;
-            }
+            FriendInfo friend = GetFriend(friends, target);
 
             if (friend != null) // Found it
             {
                 // Store it on the DB
-                FriendsService.StoreFriend(requester.ToString(), target.ToString(), rights);
+                if (!SimpleStore(requester, target, rights))
+                {
+                    remoteClient.SendAlertMessage("Unable to grant rights.");
+                    return;
+                }
 
                 // Store it in the local cache
                 int myFlags = friend.MyFlags;
@@ -725,6 +736,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
                     }
                 }
             }
+            else
+                m_log.DebugFormat("[FRIENDS MODULE]: friend {0} not found for {1}", target, requester);
+        }
+
+        protected virtual bool SimpleStore(UUID agentID, UUID friendID, int rights)
+        {
+            FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), rights);
+            return true;
+        }
+
+        protected virtual FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
+        {
+            foreach (FriendInfo fi in friends)
+            {
+                if (fi.Friend == friendID.ToString())
+                    return fi;
+            }
+            return null;
         }
 
         #region Local
@@ -753,7 +782,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
                 friendClient.SendInstantMessage(im);
 
                 // Update the local cache
-                UpdateFriendsCache(friendID);
+                UpdateFriendsCache(friendClient);
 
                 // we're done
                 return true;
@@ -786,7 +815,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
                 // the friend in this sim as root agent
                 friendClient.SendTerminateFriend(exfriendID);
                 // update local cache
-                UpdateFriendsCache(exfriendID);
+                UpdateFriendsCache(friendClient);
                 // we're done
                 return true;
             }
@@ -816,15 +845,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
                 }
 
                 // Update local cache
-                lock (m_Friends)
-                {
-                    FriendInfo[] friends = GetFriends(friendID);
-                    foreach (FriendInfo finfo in friends)
-                    {
-                        if (finfo.Friend == userID.ToString())
-                            finfo.TheirFlags = rights;
-                    }
-                }
+                UpdateLocalCache(userID, friendID, rights);
 
                 return true;
             }
@@ -866,13 +887,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
             return EMPTY_FRIENDS;
         }
 
-        private void UpdateFriendsCache(UUID agentID)
+        private void UpdateFriendsCache(IClientAPI client)
         {
+            UUID agentID = client.AgentId;
             lock (m_Friends)
             {
                 UserFriendData friendsData;
                 if (m_Friends.TryGetValue(agentID, out friendsData))
-                    friendsData.Friends = FriendsService.GetFriends(agentID);
+                    friendsData.Friends = GetFriendsFromService(client);
+            }
+        }
+
+        protected void UpdateLocalCache(UUID userID, UUID friendID, int rights)
+        {
+            // Update local cache
+            lock (m_Friends)
+            {
+                FriendInfo[] friends = GetFriends(friendID);
+                FriendInfo finfo = GetFriend(friends, userID);
+                finfo.TheirFlags = rights;
             }
         }
     }
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
index 645ecdc..abffb94 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -58,129 +58,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
 
         #endregion
 
-        //public void SendFriendsOnlineIfNeeded(IClientAPI client)
-        //{
-        //    UUID agentID = client.AgentId;
-
-        //    // Check if the online friends list is needed
-        //    lock (m_NeedsListOfFriends)
-        //    {
-        //        if (!m_NeedsListOfFriends.Remove(agentID))
-        //            return;
-        //    }
-
-        //    // Send the friends online
-        //    List<UUID> online = GetOnlineFriends(agentID);
-        //    if (online.Count > 0)
-        //    {
-        //        m_log.DebugFormat("[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", client.AgentId, client.Scene.RegionInfo.RegionName, online.Count);
-        //        client.SendAgentOnline(online.ToArray());
-        //    }
-
-        //    // Send outstanding friendship offers
-        //    List<string> outstanding = new List<string>();
-        //    FriendInfo[] friends = GetFriends(agentID);
-        //    foreach (FriendInfo fi in friends)
-        //    {
-        //        if (fi.TheirFlags == -1)
-        //            outstanding.Add(fi.Friend);
-        //    }
-
-        //    GridInstantMessage im = new GridInstantMessage(client.Scene, UUID.Zero, String.Empty, agentID, (byte)InstantMessageDialog.FriendshipOffered,
-        //        "Will you be my friend?", true, Vector3.Zero);
-
-        //    foreach (string fid in outstanding)
-        //    {
-        //        UUID fromAgentID;
-        //        if (!UUID.TryParse(fid, out fromAgentID))
-        //            continue;
-
-        //        UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, fromAgentID);
-
-        //        PresenceInfo presence = null;
-        //        PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid });
-        //        if (presences != null && presences.Length > 0)
-        //            presence = presences[0];
-        //        if (presence != null)
-        //            im.offline = 0;
-
-        //        im.fromAgentID = fromAgentID.Guid;
-        //        im.fromAgentName = account.FirstName + " " + account.LastName;
-        //        im.offline = (byte)((presence == null) ? 1 : 0);
-        //        im.imSessionID = im.fromAgentID;
-
-        //        // Finally
-        //        LocalFriendshipOffered(agentID, im);
-        //    }
-        //}
-
-        //List<UUID> GetOnlineFriends(UUID userID)
-        //{
-        //    List<string> friendList = new List<string>();
-        //    List<UUID> online = new List<UUID>();
-
-        //    FriendInfo[] friends = GetFriends(userID);
-        //    foreach (FriendInfo fi in friends)
-        //    {
-        //        if (((fi.TheirFlags & 1) != 0) && (fi.TheirFlags != -1))
-        //            friendList.Add(fi.Friend);
-        //    }
-
-        //    if (friendList.Count > 0)
-        //    {
-        //        PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
-        //        foreach (PresenceInfo pi in presence)
-        //        {
-        //            UUID presenceID;
-        //            if (UUID.TryParse(pi.UserID, out presenceID))
-        //                online.Add(presenceID);
-        //        }
-        //    }
-
-        //    return online;
-        //}
-
-        //private void StatusNotify(FriendInfo friend, UUID userID, bool online)
-        //{
-        //    UUID friendID;
-        //    if (UUID.TryParse(friend.Friend, out friendID))
-        //    {
-        //        // Try local
-        //        if (LocalStatusNotification(userID, friendID, online))
-        //            return;
-
-        //        // The friend is not here [as root]. Let's forward.
-        //        PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
-        //        if (friendSessions != null && friendSessions.Length > 0)
-        //        {
-        //            PresenceInfo friendSession = null; 
-        //            foreach (PresenceInfo pinfo in friendSessions)
-        //                if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad
-        //                {
-        //                    friendSession = pinfo;
-        //                    break;
-        //                }
-
-        //            if (friendSession != null)
-        //            {
-        //                GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
-        //                //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
-        //                m_FriendsSimConnector.StatusNotify(region, userID, friendID, online);
-        //            }
-        //        }
-
-        //        // Friend is not online. Ignore.
-        //    }
-        //    else
-        //    {
-        //        m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend);
-        //    }
-        //}
-
-        protected override bool FetchFriendslist(UUID agentID)
+        protected override bool FetchFriendslist(IClientAPI client)
         {
-            if (base.FetchFriendslist(agentID))
+            if (base.FetchFriendslist(client))
             {
+                UUID agentID = client.AgentId;
                 // We need to preload the user management cache with the names
                 // of foreign friends, just like we do with SOPs' creators
                 foreach (FriendInfo finfo in m_Friends[agentID].Friends)
@@ -204,6 +86,39 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
             return false;
         }
 
+        public override bool SendFriendsOnlineIfNeeded(IClientAPI client)
+        {
+            if (base.SendFriendsOnlineIfNeeded(client))
+            {
+                UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, client.AgentId);
+                if (account == null) // foreign
+                {
+                    FriendInfo[] friends = GetFriends(client.AgentId);
+                    foreach (FriendInfo f in friends)
+                    {
+                        client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags);
+                    }
+                }
+            }
+            return false;
+        }
+
+        protected override FriendInfo[] GetFriendsFromService(IClientAPI client)
+        {
+            UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, client.AgentId);
+            if (account1 != null)
+                return base.GetFriendsFromService(client);
+
+            // Foreigner
+            AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
+            string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
+
+            FriendInfo[] finfos = FriendsService.GetFriends(agentUUI);
+            m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI);
+            return finfos;
+        }
+
+
         protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
         {
             first = "Unknown"; last = "User";
@@ -249,6 +164,45 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
             return "Please confirm this friendship you made while you were away.";
         }
 
+        protected override bool SimpleStore(UUID agentID, UUID friendID, int rights)
+        {
+            UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
+            UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID);
+            // Are they both local users?
+            if (account1 != null && account2 != null)
+            {
+                // local grid users
+                return base.SimpleStore(agentID, friendID, rights);
+            }
+
+            if (account1 != null)
+            {
+                FriendInfo[] finfos = GetFriends(agentID);
+                if (finfos.Length > 0)
+                {
+                    FriendInfo finfo = GetFriend(finfos, friendID);
+                    FriendsService.StoreFriend(agentID.ToString(), finfo.Friend, rights);
+                    return true;
+                }
+            }
+            if (account2 != null)
+            {
+                IClientAPI client = LocateClientObject(agentID);
+                if (client != null)
+                {
+                    AgentCircuitData acircuit = m_Scenes[0].AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
+                    if (acircuit != null)
+                    {
+                        FriendsService.StoreFriend(Util.ProduceUserUniversalIdentifier(acircuit), friendID.ToString(), rights);
+                        return true;
+                    }
+                }
+            }
+
+            return false;
+
+        }
+
         protected override void StoreBackwards(UUID friendID, UUID agentID)
         {
             UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
@@ -366,6 +320,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
             // my brain hurts now
         }
 
+        protected override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
+        {
+            foreach (FriendInfo fi in friends)
+            {
+                if (fi.Friend.StartsWith(friendID.ToString()))
+                    return fi;
+            }
+            return null;
+        }
+
         protected override void DeleteFriendship(UUID agentID, UUID exfriendID)
         {
             base.DeleteFriendship(agentID, exfriendID);
@@ -374,7 +338,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
             FriendInfo[] friends = GetFriends(agentID);
             foreach (FriendInfo finfo in friends)
             {
-                if (finfo.Friend != exfriendID.ToString() && finfo.Friend.EndsWith(exfriendID.ToString()))
+                if (finfo.Friend != exfriendID.ToString() && finfo.Friend.StartsWith(exfriendID.ToString()))
                 {
                     FriendsService.Delete(agentID, exfriendID.ToString());
                     // TODO: delete the friendship on the other side
@@ -383,56 +347,5 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
             }
         }
 
-        //private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights)
-        //{
-        //    FriendInfo[] friends = GetFriends(remoteClient.AgentId);
-        //    if (friends.Length == 0)
-        //        return;
-
-        //    m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target);
-        //    // Let's find the friend in this user's friend list
-        //    FriendInfo friend = null;
-        //    foreach (FriendInfo fi in friends)
-        //    {
-        //        if (fi.Friend == target.ToString())
-        //            friend = fi;
-        //    }
-
-        //    if (friend != null) // Found it
-        //    {
-        //        // Store it on the DB
-        //        FriendsService.StoreFriend(requester, target.ToString(), rights);
-
-        //        // Store it in the local cache
-        //        int myFlags = friend.MyFlags;
-        //        friend.MyFlags = rights;
-
-        //        // Always send this back to the original client
-        //        remoteClient.SendChangeUserRights(requester, target, rights);
-
-        //        //
-        //        // Notify the friend
-        //        //
-
-        //        // Try local
-        //        if (LocalGrantRights(requester, target, myFlags, rights))
-        //            return;
-
-        //        PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { target.ToString() });
-        //        if (friendSessions != null && friendSessions.Length > 0)
-        //        {
-        //            PresenceInfo friendSession = friendSessions[0];
-        //            if (friendSession != null)
-        //            {
-        //                GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
-        //                // TODO: You might want to send the delta to save the lookup
-        //                // on the other end!!
-        //                m_FriendsSimConnector.GrantRights(region, requester, target, myFlags, rights);
-        //            }
-        //        }
-        //    }
-        //}
-
-
     }
 }
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 170c35f..d7324c6 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -548,18 +548,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions
 
             // libomv will moan about PrimFlags.ObjectYouOfficer being
             // deprecated
-            #pragma warning disable 0612 
+#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
+                    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
+#pragma warning restore 0612
 
             // Creating the three ObjectFlags options for this method to choose from.
             // Customize the OwnerMask
@@ -576,22 +576,27 @@ namespace OpenSim.Region.CoreModules.World.Permissions
 
             if (m_bypassPermissions)
                 return objectOwnerMask;
-        
+
             // Object owners should be able to edit their own content
             if (user == objectOwner)
                 return objectOwnerMask;
-            
+
             if (IsFriendWithPerms(user, objectOwner))
+            {
                 return objectOwnerMask;
-
+            }
             // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
             if (m_RegionOwnerIsGod && IsEstateManager(user) && !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.
             Vector3 taskPos = task.AbsolutePosition;
             ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y);
@@ -599,13 +604,15 @@ namespace OpenSim.Region.CoreModules.World.Permissions
             {
                 // Admin objects should not be editable by the above
                 if (!IsAdministrator(objectOwner))
+                {
                     return objectOwnerMask;
+                }
             }
 
             // Group permissions
             if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0))
                 return objectGroupMask | objectEveryoneMask;
-        
+
             return objectEveryoneMask;
         }
 
@@ -673,7 +680,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions
             //
             // Nobody but the object owner can set permissions on an object
             //
-
             if (locked && (!IsAdministrator(currentUser)) && denyOnLocked)
             {
                 return false;
@@ -704,6 +710,11 @@ namespace OpenSim.Region.CoreModules.World.Permissions
                 // Return immediately, so that the administrator can shares group objects
                 return true;
             }
+
+            // Friends with benefits should be able to edit the objects too
+            if (IsFriendWithPerms(currentUser, objectOwner))
+                // Return immediately, so that the administrator can share objects with friends
+                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);
-- 
cgit v1.1