From 58c53c41de2cae0bb041a2e8121792e136d1edb2 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 21 May 2011 16:48:00 -0700 Subject: [PATCH] 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. --- OpenSim/Data/IFriendsData.cs | 1 + OpenSim/Data/MSSQL/MSSQLFriendsData.cs | 6 + OpenSim/Data/MySQL/MySQLFriendsData.cs | 5 + OpenSim/Data/Null/NullFriendsData.cs | 7 +- OpenSim/Data/SQLite/SQLiteFriendsData.cs | 7 +- .../Avatar/Friends/FriendsModule.cs | 105 ++++--- .../Avatar/Friends/HGFriendsModule.cs | 259 ++++++------------ .../World/Permissions/PermissionsModule.cs | 43 +-- .../Framework/Interfaces/IFriendsModule.cs | 2 +- .../Friends/FriendsServerPostHandler.cs | 23 +- .../Hypergrid/HGFriendsServerPostHandler.cs | 116 +++++--- .../Friends/FriendsServiceConnector.cs | 17 +- .../Hypergrid/HGFriendsServiceConnector.cs | 37 +-- .../SimianFriendsServiceConnector.cs | 18 +- OpenSim/Services/Friends/FriendsService.cs | 26 ++ .../HypergridService/HGFriendsService.cs | 4 +- .../Services/Interfaces/IFriendsService.cs | 1 + 17 files changed, 376 insertions(+), 301 deletions(-) diff --git a/OpenSim/Data/IFriendsData.cs b/OpenSim/Data/IFriendsData.cs index 4da567e56b..52e7f1419a 100644 --- a/OpenSim/Data/IFriendsData.cs +++ b/OpenSim/Data/IFriendsData.cs @@ -47,5 +47,6 @@ namespace OpenSim.Data bool Store(FriendsData data); bool Delete(UUID ownerID, string friend); FriendsData[] GetFriends(UUID principalID); + FriendsData[] GetFriends(string principalID); } } diff --git a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs index af4fd9ba55..ba1b085ef6 100644 --- a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs +++ b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs @@ -67,6 +67,11 @@ namespace OpenSim.Data.MSSQL } public FriendsData[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + + public FriendsData[] GetFriends(string principalID) { using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand()) @@ -79,5 +84,6 @@ namespace OpenSim.Data.MSSQL return DoQuery(cmd); } } + } } diff --git a/OpenSim/Data/MySQL/MySQLFriendsData.cs b/OpenSim/Data/MySQL/MySQLFriendsData.cs index 663fad6603..69fac9d3f1 100644 --- a/OpenSim/Data/MySQL/MySQLFriendsData.cs +++ b/OpenSim/Data/MySQL/MySQLFriendsData.cs @@ -56,6 +56,11 @@ namespace OpenSim.Data.MySQL } public FriendsData[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + + public FriendsData[] GetFriends(string principalID) { MySqlCommand cmd = new MySqlCommand(); diff --git a/OpenSim/Data/Null/NullFriendsData.cs b/OpenSim/Data/Null/NullFriendsData.cs index 0c69bb1700..2bfdc7a72d 100644 --- a/OpenSim/Data/Null/NullFriendsData.cs +++ b/OpenSim/Data/Null/NullFriendsData.cs @@ -42,6 +42,11 @@ namespace OpenSim.Data.Null { } + public FriendsData[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + /// /// Tries to implement the Get [] semantics, but it cuts corners. /// Specifically, it gets all friendships even if they weren't accepted yet. @@ -49,7 +54,7 @@ namespace OpenSim.Data.Null /// /// /// - public FriendsData[] GetFriends(UUID userID) + public FriendsData[] GetFriends(string userID) { List lst = m_Data.FindAll(delegate (FriendsData fdata) { diff --git a/OpenSim/Data/SQLite/SQLiteFriendsData.cs b/OpenSim/Data/SQLite/SQLiteFriendsData.cs index 4bfd228364..d925412dba 100644 --- a/OpenSim/Data/SQLite/SQLiteFriendsData.cs +++ b/OpenSim/Data/SQLite/SQLiteFriendsData.cs @@ -46,7 +46,12 @@ namespace OpenSim.Data.SQLite { } - public FriendsData[] GetFriends(UUID userID) + public FriendsData[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + + public FriendsData[] GetFriends(string userID) { SqliteCommand cmd = new SqliteCommand(); diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 21cd924583..4879d20800 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 m_Scenes = new List(); @@ -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(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) - 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; + m_log.DebugFormat("[XXX]: agent {0} has no friends", requester); + return; } + // Let's find the friend in this user's friend list + 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 645ecdc011..abffb94b69 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 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 outstanding = new List(); - // 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 GetOnlineFriends(UUID userID) - //{ - // List friendList = new List(); - // List online = new List(); - - // 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 170c35f814..d7324c6c55 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; + 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); diff --git a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs index 0ff7deeb30..d4a6857188 100644 --- a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs @@ -34,6 +34,6 @@ namespace OpenSim.Region.Framework.Interfaces public interface IFriendsModule { uint GetFriendPerms(UUID PrincipalID, UUID FriendID); - void SendFriendsOnlineIfNeeded(IClientAPI client); + bool SendFriendsOnlineIfNeeded(IClientAPI client); } } diff --git a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs index 64002e1ada..71c3c73349 100644 --- a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs @@ -82,6 +82,9 @@ namespace OpenSim.Server.Handlers.Friends case "getfriends": return GetFriends(request); + case "getfriends_string": + return GetFriendsString(request); + case "storefriend": return StoreFriend(request); @@ -111,7 +114,25 @@ namespace OpenSim.Server.Handlers.Friends m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to get friends"); FriendInfo[] finfos = m_FriendsService.GetFriends(principalID); - //m_log.DebugFormat("[FRIENDS HANDLER]: neighbours for region {0}: {1}", regionID, rinfos.Count); + + return PackageFriends(finfos); + } + + byte[] GetFriendsString(Dictionary request) + { + string principalID = string.Empty; + if (request.ContainsKey("PRINCIPALID")) + principalID = request["PRINCIPALID"].ToString(); + else + m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to get friends"); + + FriendInfo[] finfos = m_FriendsService.GetFriends(principalID); + + return PackageFriends(finfos); + } + + private byte[] PackageFriends(FriendInfo[] finfos) + { Dictionary result = new Dictionary(); if ((finfos == null) || ((finfos != null) && (finfos.Length == 0))) diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs index 13d150265a..dde7875321 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs @@ -82,8 +82,8 @@ namespace OpenSim.Server.Handlers.Hypergrid switch (method) { - case "getfriends": - return GetFriends(request); + case "getfriendperms": + return GetFriendPerms(request); case "newfriendship": return NewFriendship(request); @@ -102,58 +102,45 @@ namespace OpenSim.Server.Handlers.Hypergrid #region Method-specific handlers - byte[] GetFriends(Dictionary request) + byte[] GetFriendPerms(Dictionary request) { + if (!VerifyServiceKey(request)) + return FailureResult(); + UUID principalID = UUID.Zero; if (request.ContainsKey("PRINCIPALID")) UUID.TryParse(request["PRINCIPALID"].ToString(), out principalID); - else - m_log.WarnFormat("[HGFRIENDS HANDLER]: no principalID in request to get friends"); - - FriendInfo[] finfos = m_FriendsService.GetFriends(principalID); - //m_log.DebugFormat("[FRIENDS HANDLER]: neighbours for region {0}: {1}", regionID, rinfos.Count); - - Dictionary result = new Dictionary(); - if ((finfos == null) || ((finfos != null) && (finfos.Length == 0))) - result["result"] = "null"; else { - int i = 0; - foreach (FriendInfo finfo in finfos) - { - Dictionary rinfoDict = finfo.ToKeyValuePairs(); - result["friend" + i] = rinfoDict; - i++; - } + m_log.WarnFormat("[HGFRIENDS HANDLER]: no principalID in request to get friend perms"); + return FailureResult(); } - string xmlString = ServerUtils.BuildXmlResponse(result); - //m_log.DebugFormat("[FRIENDS HANDLER]: resp string: {0}", xmlString); - UTF8Encoding encoding = new UTF8Encoding(); - return encoding.GetBytes(xmlString); + UUID friendID = UUID.Zero; + if (request.ContainsKey("FRIENDID")) + UUID.TryParse(request["FRIENDID"].ToString(), out friendID); + else + { + m_log.WarnFormat("[HGFRIENDS HANDLER]: no friendID in request to get friend perms"); + return FailureResult(); + } + string perms = "0"; + FriendInfo[] friendsInfo = m_FriendsService.GetFriends(principalID); + foreach (FriendInfo finfo in friendsInfo) + { + if (finfo.Friend.StartsWith(friendID.ToString())) + return SuccessResult(finfo.TheirFlags.ToString()); + } + + return FailureResult("Friend not found"); } byte[] NewFriendship(Dictionary request) { - if (!request.ContainsKey("KEY") || !request.ContainsKey("SESSIONID")) - { - m_log.WarnFormat("[HGFRIENDS HANDLER]: ignoring request without Key or SessionID"); + if (!VerifyServiceKey(request)) return FailureResult(); - } - string serviceKey = request["KEY"].ToString(); - string sessionStr = request["SESSIONID"].ToString(); - UUID sessionID; - UUID.TryParse(sessionStr, out sessionID); - - if (!m_UserAgentService.VerifyAgent(sessionID, serviceKey)) - { - m_log.WarnFormat("[HGFRIENDS HANDLER]: Key {0} for session {1} did not match existing key. Ignoring request", serviceKey, sessionID); - return FailureResult(); - } - - m_log.DebugFormat("[XXX] Verification ok"); // OK, can proceed FriendInfo friend = new FriendInfo(request); @@ -172,6 +159,29 @@ namespace OpenSim.Server.Handlers.Hypergrid #region Misc + private bool VerifyServiceKey(Dictionary request) + { + if (!request.ContainsKey("KEY") || !request.ContainsKey("SESSIONID")) + { + m_log.WarnFormat("[HGFRIENDS HANDLER]: ignoring request without Key or SessionID"); + return false; + } + + string serviceKey = request["KEY"].ToString(); + string sessionStr = request["SESSIONID"].ToString(); + UUID sessionID; + UUID.TryParse(sessionStr, out sessionID); + + if (!m_UserAgentService.VerifyAgent(sessionID, serviceKey)) + { + m_log.WarnFormat("[HGFRIENDS HANDLER]: Key {0} for session {1} did not match existing key. Ignoring request", serviceKey, sessionID); + return false; + } + + m_log.DebugFormat("[XXX] Verification ok"); + return true; + } + private byte[] SuccessResult() { XmlDocument doc = new XmlDocument(); @@ -194,6 +204,34 @@ namespace OpenSim.Server.Handlers.Hypergrid return DocToBytes(doc); } + private byte[] SuccessResult(string value) + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "Result", ""); + result.AppendChild(doc.CreateTextNode("Success")); + + rootElement.AppendChild(result); + + XmlElement message = doc.CreateElement("", "Value", ""); + message.AppendChild(doc.CreateTextNode(value)); + + rootElement.AppendChild(message); + + return DocToBytes(doc); + } + + private byte[] FailureResult() { return FailureResult(String.Empty); diff --git a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs index 52b80e1ffd..d1afea22ed 100644 --- a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs @@ -84,7 +84,7 @@ namespace OpenSim.Services.Connectors.Friends #region IFriendsService - + public FriendInfo[] GetFriends(UUID PrincipalID) { Dictionary sendData = new Dictionary(); @@ -92,6 +92,21 @@ namespace OpenSim.Services.Connectors.Friends sendData["PRINCIPALID"] = PrincipalID.ToString(); sendData["METHOD"] = "getfriends"; + return GetFriends(sendData, PrincipalID.ToString()); + } + + public FriendInfo[] GetFriends(string PrincipalID) + { + Dictionary sendData = new Dictionary(); + + sendData["PRINCIPALID"] = PrincipalID; + sendData["METHOD"] = "getfriends_string"; + + return GetFriends(sendData, PrincipalID); + } + + protected FriendInfo[] GetFriends(Dictionary sendData, string PrincipalID) + { string reqString = ServerUtils.BuildQueryString(sendData); try diff --git a/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs index 76f5f190a9..f8238897bf 100644 --- a/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs @@ -63,12 +63,13 @@ namespace OpenSim.Services.Connectors.Hypergrid #region IFriendsService - public FriendInfo[] GetFriends(UUID PrincipalID) + public uint GetFriendPerms(UUID PrincipalID, UUID friendID) { Dictionary sendData = new Dictionary(); sendData["PRINCIPALID"] = PrincipalID.ToString(); - sendData["METHOD"] = "getfriends"; + sendData["FRIENDID"] = friendID.ToString(); + sendData["METHOD"] = "getfriendperms"; sendData["KEY"] = m_ServiceKey; sendData["SESSIONID"] = m_SessionID.ToString(); @@ -83,34 +84,14 @@ namespace OpenSim.Services.Connectors.Hypergrid { Dictionary replyData = ServerUtils.ParseXmlResponse(reply); - if (replyData != null) + if ((replyData != null) && replyData.ContainsKey("Value") && (replyData["Value"] != null)) { - if (replyData.ContainsKey("result") && (replyData["result"].ToString().ToLower() == "null")) - { - return new FriendInfo[0]; - } - - List finfos = new List(); - Dictionary.ValueCollection finfosList = replyData.Values; - //m_log.DebugFormat("[FRIENDS CONNECTOR]: get neighbours returned {0} elements", rinfosList.Count); - foreach (object f in finfosList) - { - if (f is Dictionary) - { - FriendInfo finfo = new FriendInfo((Dictionary)f); - finfos.Add(finfo); - } - else - m_log.DebugFormat("[HGFRIENDS CONNECTOR]: GetFriends {0} received invalid response type {1}", - PrincipalID, f.GetType()); - } - - // Success - return finfos.ToArray(); + uint perms = 0; + uint.TryParse(replyData["Value"].ToString(), out perms); + return perms; } - else - m_log.DebugFormat("[HGFRIENDS CONNECTOR]: GetFriends {0} received null response", + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: GetFriendPerms {0} received null response", PrincipalID); } @@ -120,7 +101,7 @@ namespace OpenSim.Services.Connectors.Hypergrid m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message); } - return new FriendInfo[0]; + return 0; } diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs index f61ab2956d..b1c34dd39b 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs @@ -77,6 +77,11 @@ namespace OpenSim.Services.Connectors.SimianGrid #region IFriendsService public FriendInfo[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + + public FriendInfo[] GetFriends(string principalID) { if (String.IsNullOrEmpty(m_serverUrl)) return new FriendInfo[0]; @@ -95,7 +100,14 @@ namespace OpenSim.Services.Connectors.SimianGrid UUID friendID = friendEntry["Key"].AsUUID(); FriendInfo friend = new FriendInfo(); - friend.PrincipalID = principalID; + if (!UUID.TryParse(principalID, out friend.PrincipalID)) + { + string tmp = string.Empty; + if (!Util.ParseUniversalUserIdentifier(principalID, out friend.PrincipalID, out tmp, out tmp, out tmp)) + // bad record. ignore this entry + continue; + } + friend.Friend = friendID.ToString(); friend.MyFlags = friendEntry["Value"].AsInteger(); friend.TheirFlags = -1; @@ -174,7 +186,7 @@ namespace OpenSim.Services.Connectors.SimianGrid #endregion IFriendsService - private OSDArray GetFriended(UUID ownerID) + private OSDArray GetFriended(string ownerID) { NameValueCollection requestArgs = new NameValueCollection { @@ -195,7 +207,7 @@ namespace OpenSim.Services.Connectors.SimianGrid } } - private OSDArray GetFriendedBy(UUID ownerID) + private OSDArray GetFriendedBy(string ownerID) { NameValueCollection requestArgs = new NameValueCollection { diff --git a/OpenSim/Services/Friends/FriendsService.cs b/OpenSim/Services/Friends/FriendsService.cs index 039dc0bceb..4664cb30c0 100644 --- a/OpenSim/Services/Friends/FriendsService.cs +++ b/OpenSim/Services/Friends/FriendsService.cs @@ -63,6 +63,32 @@ namespace OpenSim.Services.Friends return info.ToArray(); } + public virtual FriendInfo[] GetFriends(string PrincipalID) + { + FriendsData[] data = m_Database.GetFriends(PrincipalID); + List info = new List(); + + foreach (FriendsData d in data) + { + FriendInfo i = new FriendInfo(); + + if (!UUID.TryParse(d.PrincipalID, out i.PrincipalID)) + { + string tmp = string.Empty; + if (!Util.ParseUniversalUserIdentifier(d.PrincipalID, out i.PrincipalID, out tmp, out tmp, out tmp)) + // bad record. ignore this entry + continue; + } + i.Friend = d.Friend; + i.MyFlags = Convert.ToInt32(d.Data["Flags"]); + i.TheirFlags = Convert.ToInt32(d.Data["TheirFlags"]); + + info.Add(i); + } + + return info.ToArray(); + } + public virtual bool StoreFriend(string PrincipalID, string Friend, int flags) { FriendsData d = new FriendsData(); diff --git a/OpenSim/Services/HypergridService/HGFriendsService.cs b/OpenSim/Services/HypergridService/HGFriendsService.cs index fa4ec5d7ec..3ffe88973a 100644 --- a/OpenSim/Services/HypergridService/HGFriendsService.cs +++ b/OpenSim/Services/HypergridService/HGFriendsService.cs @@ -62,7 +62,7 @@ namespace OpenSim.Services.HypergridService UUID userID; if (UUID.TryParse(PrincipalID, out userID)) { - FriendsData[] friendsData = m_Database.GetFriends(userID); + FriendsData[] friendsData = m_Database.GetFriends(userID.ToString()); List fList = new List(friendsData); if (fList.Find(delegate(FriendsData fdata) { @@ -70,6 +70,8 @@ namespace OpenSim.Services.HypergridService }) != null) return false; } + else + return false; FriendsData d = new FriendsData(); d.PrincipalID = PrincipalID; diff --git a/OpenSim/Services/Interfaces/IFriendsService.cs b/OpenSim/Services/Interfaces/IFriendsService.cs index 05e85f2318..0a8efad11a 100644 --- a/OpenSim/Services/Interfaces/IFriendsService.cs +++ b/OpenSim/Services/Interfaces/IFriendsService.cs @@ -74,6 +74,7 @@ namespace OpenSim.Services.Interfaces public interface IFriendsService { FriendInfo[] GetFriends(UUID PrincipalID); + FriendInfo[] GetFriends(string PrincipalID); bool StoreFriend(string PrincipalID, string Friend, int flags); bool Delete(UUID PrincipalID, string Friend); }