HG Friends: allow the establishment of HG friendships without requiring co-presence in the same sim. Using avatar picker, users can now search for names such as "first.last@grid.com:9000", find them, and request friendship. Friendship requests are stored if target user is offline. TESTED ON STANDALONE ONLY.

0.7.4.1
Diva Canto 2012-03-20 17:14:19 -07:00
parent d1256536b5
commit d08ad6459a
14 changed files with 2791 additions and 2191 deletions

File diff suppressed because it is too large Load Diff

View File

@ -550,7 +550,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
UUID principalID = new UUID(im.fromAgentID);
UUID friendID = new UUID(im.toAgentID);
m_log.DebugFormat("[FRIENDS]: {0} ({1}) offered friendship to {2}", principalID, im.fromAgentName, friendID);
m_log.DebugFormat("[FRIENDS]: {0} ({1}) offered friendship to {2} ({3})", principalID, client.FirstName + client.LastName, friendID, im.fromAgentName);
// Check that the friendship doesn't exist yet
FriendInfo[] finfos = GetFriends(principalID);
if (finfos != null)
{
FriendInfo f = GetFriend(finfos, friendID);
if (f != null)
{
client.SendAgentAlertMessage("This person is already your friend. Please delete it first if you want to reestablish the friendship.", false);
return;
}
}
// This user wants to be friends with the other user.
// Let's add the relation backwards, in case the other is not online
@ -561,7 +573,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
}
}
private void ForwardFriendshipOffer(UUID agentID, UUID friendID, GridInstantMessage im)
protected virtual bool ForwardFriendshipOffer(UUID agentID, UUID friendID, GridInstantMessage im)
{
// !!!!!!!! This is a hack so that we don't have to keep state (transactionID/imSessionID)
// We stick this agent's ID as imSession, so that it's directly available on the receiving end
@ -570,7 +582,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
// Try the local sim
if (LocalFriendshipOffered(friendID, im))
return;
{
m_log.DebugFormat("[XXX]: LocalFriendshipOffered successes");
return true;
}
// The prospective friend is not here [as root]. Let's forward.
PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
@ -581,9 +596,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
{
GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
m_FriendsSimConnector.FriendshipOffered(region, agentID, friendID, im.message);
return true;
}
}
// If the prospective friend is not online, he'll get the message upon login.
return false;
}
protected virtual string GetFriendshipRequesterName(UUID agentID)
@ -592,7 +609,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
return (account == null) ? "Unknown" : account.FirstName + " " + account.LastName;
}
private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
protected virtual void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
{
m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", client.AgentId, friendID);
@ -603,7 +620,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
{
StoreFriendships(client.AgentId, friendID);
// Update the local cache
// Update the local cache.
RecacheFriends(client);
//
@ -756,7 +773,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
#region Local
public bool LocalFriendshipOffered(UUID toID, GridInstantMessage im)
public virtual bool LocalFriendshipOffered(UUID toID, GridInstantMessage im)
{
IClientAPI friendClient = LocateClientObject(toID);
if (friendClient != null)
@ -912,7 +929,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
return FriendsService.GetFriends(client.AgentId);
}
private void RecacheFriends(IClientAPI client)
protected void RecacheFriends(IClientAPI client)
{
// FIXME: Ideally, we want to avoid doing this here since it sits the EventManager.OnMakeRootAgent event
// is on the critical path for transferring an avatar from one region to another.

View File

@ -61,6 +61,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
}
}
protected HGFriendsServicesConnector m_HGFriendsConnector = new HGFriendsServicesConnector();
#region ISharedRegionModule
public override string Name
{
@ -94,6 +96,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
#endregion
protected override void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
{
// Update the local cache. Yes, we need to do it right here
// because the HGFriendsService placed something on the DB
// from under the sim
base.OnApproveFriendRequest(client, agentID, friendID, callingCardFolders);
}
protected override bool CacheFriends(IClientAPI client)
{
// m_log.DebugFormat("[HGFRIENDS MODULE]: Entered CacheFriends for {0}", client.Name);
@ -183,91 +193,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
// m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting GetOnlineFriends for {0}", userID);
}
//protected override void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
//{
// // Let's single out the UUIs
// List<string> localFriends = new List<string>();
// List<string> foreignFriends = new List<string>();
// string tmp = string.Empty;
// foreach (string s in friendList)
// {
// UUID id;
// if (UUID.TryParse(s, out id))
// localFriends.Add(s);
// else if (Util.ParseUniversalUserIdentifier(s, out id, out tmp, out tmp, out tmp, out tmp))
// {
// foreignFriends.Add(s);
// // add it here too, who knows maybe the foreign friends happens to be on this grid
// localFriends.Add(id.ToString());
// }
// }
// // OK, see who's present on this grid
// List<string> toBeRemoved = new List<string>();
// PresenceInfo[] presence = PresenceService.GetAgents(localFriends.ToArray());
// foreach (PresenceInfo pi in presence)
// {
// UUID presenceID;
// if (UUID.TryParse(pi.UserID, out presenceID))
// {
// online.Add(presenceID);
// foreach (string s in foreignFriends)
// if (s.StartsWith(pi.UserID))
// toBeRemoved.Add(s);
// }
// }
// foreach (string s in toBeRemoved)
// foreignFriends.Remove(s);
// // OK, let's send this up the stack, and leave a closure here
// // collecting online friends in other grids
// Util.FireAndForget(delegate { CollectOnlineFriendsElsewhere(userID, foreignFriends); });
//}
//private void CollectOnlineFriendsElsewhere(UUID userID, List<string> foreignFriends)
//{
// // let's divide the friends on a per-domain basis
// Dictionary<string, List<string>> friendsPerDomain = new Dictionary<string, List<string>>();
// foreach (string friend in foreignFriends)
// {
// UUID friendID;
// if (!UUID.TryParse(friend, out friendID))
// {
// // it's a foreign friend
// string url = string.Empty, tmp = string.Empty;
// if (Util.ParseUniversalUserIdentifier(friend, out friendID, out url, out tmp, out tmp, out tmp))
// {
// if (!friendsPerDomain.ContainsKey(url))
// friendsPerDomain[url] = new List<string>();
// friendsPerDomain[url].Add(friend);
// }
// }
// }
// // Now, call those worlds
// foreach (KeyValuePair<string, List<string>> kvp in friendsPerDomain)
// {
// List<string> ids = new List<string>();
// foreach (string f in kvp.Value)
// ids.Add(f);
// UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key);
// List<UUID> online = uConn.GetOnlineFriends(userID, ids);
// // Finally send the notifications to the user
// // this whole process may take a while, so let's check at every
// // iteration that the user is still here
// IClientAPI client = LocateClientObject(userID);
// if (client != null)
// client.SendAgentOnline(online.ToArray());
// else
// break;
// }
//}
protected override void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
{
// m_log.DebugFormat("[HGFRIENDS MODULE]: Entering StatusNotify for {0}", userID);
@ -335,12 +260,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
return true;
// fid is not a UUID...
string url = string.Empty, tmp = string.Empty;
if (Util.ParseUniversalUserIdentifier(fid, out agentID, out url, out first, out last, out tmp))
string url = string.Empty, tmp = string.Empty, f = string.Empty, l = string.Empty;
m_log.DebugFormat("[YYY]: FID {0}", fid);
if (Util.ParseUniversalUserIdentifier(fid, out agentID, out url, out f, out l, out tmp))
{
IUserManagement userMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
userMan.AddUser(agentID, first, last, url);
m_log.DebugFormat("[YYY]: Adding user {0} {1} {2}", f, l, url);
m_uMan.AddUser(agentID, f, l, url);
string name = m_uMan.GetUserName(agentID);
string[] parts = name.Trim().Split(new char[] {' '});
if (parts.Length == 2)
{
first = parts[0];
last = parts[1];
}
else
{
first = f;
last = l;
}
return true;
}
return false;
@ -348,13 +286,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
protected override string GetFriendshipRequesterName(UUID agentID)
{
// For the time being we assume that HG friendship requests can only happen
// when avies are on the same region.
IClientAPI client = LocateClientObject(agentID);
if (client != null)
return client.FirstName + " " + client.LastName;
else
return base.GetFriendshipRequesterName(agentID);
return m_uMan.GetUserName(agentID);
}
protected override string FriendshipMessage(string friendID)
@ -392,10 +324,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
if (agentClientCircuit != null)
{
string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
//[XXX] string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
finfos = FriendsService.GetFriends(agentUUI);
m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI);
finfos = FriendsService.GetFriends(client.AgentId.ToString());
m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, client.AgentId.ToString());
}
// m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting GetFriendsFromService for {0}", client.Name);
@ -454,16 +386,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
friendIsLocal = UserManagementModule.IsLocalGridUser(friendID);
}
// Are they both local users?
if (agentIsLocal && friendIsLocal)
// Is the requester a local user?
if (agentIsLocal)
{
// local grid users
m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local");
m_log.DebugFormat("[HGFRIENDS MODULE]: Friendship requester is local. Storing backwards.");
base.StoreBackwards(friendID, agentID);
return;
}
// no provision for this temporary friendship state
// no provision for this temporary friendship state when user is not local
//FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0);
}
@ -501,12 +434,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode);
agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
agentFriendService = agentClientCircuit.ServiceURLs["FriendsServerURI"].ToString();
RecacheFriends(agentClient);
}
if (friendClient != null)
{
friendClientCircuit = ((Scene)(friendClient.Scene)).AuthenticateHandler.GetAgentCircuitData(friendClient.CircuitCode);
friendUUI = Util.ProduceUserUniversalIdentifier(friendClientCircuit);
friendFriendService = friendClientCircuit.ServiceURLs["FriendsServerURI"].ToString();
RecacheFriends(friendClient);
}
m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}",
@ -515,14 +450,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
// Generate a random 8-character hex number that will sign this friendship
string secret = UUID.Random().ToString().Substring(0, 8);
string theFriendUUID = friendUUI + ";" + secret;
string agentUUID = agentUUI + ";" + secret;
if (agentIsLocal) // agent is local, 'friend' is foreigner
{
// This may happen when the agent returned home, in which case the friend is not there
// We need to look for its information in the friends list itself
FriendInfo[] finfos = null;
bool confirming = false;
if (friendUUI == string.Empty)
{
FriendInfo[] finfos = GetFriends(agentID);
finfos = GetFriends(agentID);
foreach (FriendInfo finfo in finfos)
{
if (finfo.TheirFlags == -1)
@ -530,29 +469,57 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
if (finfo.Friend.StartsWith(friendID.ToString()))
{
friendUUI = finfo.Friend;
theFriendUUID = friendUUI;
UUID utmp = UUID.Zero; String url = String.Empty; String first = String.Empty, last = String.Empty, tmp = String.Empty;
// If it's confirming the friendship, we already have the full UUI with the secret
if (Util.ParseUniversalUserIdentifier(theFriendUUID, out utmp, out url, out first, out last, out secret))
{
agentUUID = agentUUI + ";" + secret;
m_uMan.AddUser(utmp, first, last, url);
}
confirming = true;
break;
}
}
}
}
if (!confirming)
{
friendUUI = m_uMan.GetUserUUI(friendID);
theFriendUUID = friendUUI + ";" + secret;
}
// If it's confirming the friendship, we already have the full friendUUI with the secret
string theFriendUUID = confirming ? friendUUI : friendUUI + ";" + secret;
friendFriendService = m_uMan.GetUserServerURL(friendID, "FriendsServerURI");
// m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}",
// agentUUI, friendUUI, agentFriendService, friendFriendService);
}
// Delete any previous friendship relations
DeletePreviousRelations(agentID, friendID);
// store in the local friends service a reference to the foreign friend
FriendsService.StoreFriend(agentID.ToString(), theFriendUUID, 1);
// and also the converse
FriendsService.StoreFriend(theFriendUUID, agentID.ToString(), 1);
if (!confirming && friendClientCircuit != null)
{
//if (!confirming)
//{
// store in the foreign friends service a reference to the local agent
HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID);
friendsConn.NewFriendship(friendID, agentUUI + ";" + secret);
}
HGFriendsServicesConnector friendsConn = null;
if (friendClientCircuit != null) // the friend is here, validate session
friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID);
else // the friend is not here, he initiated the request in his home world
friendsConn = new HGFriendsServicesConnector(friendFriendService);
friendsConn.NewFriendship(friendID, agentUUID);
//}
}
else if (friendIsLocal) // 'friend' is local, agent is foreigner
{
// Delete any previous friendship relations
DeletePreviousRelations(agentID, friendID);
// store in the local friends service a reference to the foreign agent
FriendsService.StoreFriend(friendID.ToString(), agentUUI + ";" + secret, 1);
// and also the converse
@ -582,6 +549,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
// my brain hurts now
}
private void DeletePreviousRelations(UUID a1, UUID a2)
{
// Delete any previous friendship relations
FriendInfo[] finfos = null;
FriendInfo f = null;
finfos = GetFriends(a1);
if (finfos != null)
{
f = GetFriend(finfos, a2);
if (f != null)
{
FriendsService.Delete(a1, f.Friend);
// and also the converse
FriendsService.Delete(f.Friend, a1.ToString());
}
}
finfos = GetFriends(a2);
if (finfos != null)
{
f = GetFriend(finfos, a1);
if (f != null)
{
FriendsService.Delete(a2, f.Friend);
// and also the converse
FriendsService.Delete(f.Friend, a2.ToString());
}
}
}
protected override bool DeleteFriendship(UUID agentID, UUID exfriendID)
{
Boolean agentIsLocal = true;
@ -684,5 +681,74 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
friendConn.DeleteFriendship(foreignUser, localUser, secret);
}
}
protected override bool ForwardFriendshipOffer(UUID agentID, UUID friendID, GridInstantMessage im)
{
if (base.ForwardFriendshipOffer(agentID, friendID, im))
return true;
// OK, that didn't work, so let's try to find this user somewhere
if (!m_uMan.IsLocalGridUser(friendID))
{
string friendsURL = m_uMan.GetUserServerURL(friendID, "FriendsServerURI");
if (friendsURL != string.Empty)
{
m_log.DebugFormat("[HGFRIENDS MODULE]: Forwading friendship from {0} to {1} @ {2}", agentID, friendID, friendsURL);
GridRegion region = new GridRegion();
region.ServerURI = friendsURL;
string name = im.fromAgentName;
if (m_uMan.IsLocalGridUser(agentID))
{
IClientAPI agentClient = LocateClientObject(agentID);
AgentCircuitData agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode);
string agentHomeService = string.Empty;
try
{
agentHomeService = agentClientCircuit.ServiceURLs["HomeURI"].ToString();
string lastname = "@" + new Uri(agentHomeService).Authority;
string firstname = im.fromAgentName.Replace(" ", ".");
name = firstname + lastname;
}
catch (KeyNotFoundException)
{
m_log.DebugFormat("[HGFRIENDS MODULE]: Key HomeURI not found for user {0}", agentID);
return false;
}
catch (NullReferenceException)
{
m_log.DebugFormat("[HGFRIENDS MODULE]: Null HomeUri for local user {0}", agentID);
return false;
}
catch (UriFormatException)
{
m_log.DebugFormat("[HGFRIENDS MODULE]: Malformed HomeUri {0} for local user {1}", agentHomeService, agentID);
return false;
}
}
m_HGFriendsConnector.FriendshipOffered(region, agentID, friendID, im.message, name);
return true;
}
}
return false;
}
public override bool LocalFriendshipOffered(UUID toID, GridInstantMessage im)
{
if (base.LocalFriendshipOffered(toID, im))
{
if (im.fromAgentName.Contains("@"))
{
string[] parts = im.fromAgentName.Split(new char[] { '@' });
if (parts.Length == 2)
m_uMan.AddUser(new UUID(im.fromAgentID), parts[0], "http://" + parts[1]);
}
return true;
}
return false;
}
}
}

View File

@ -71,43 +71,52 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
protected override void AddAdditionalUsers(UUID avatarID, string query, List<UserData> users)
{
string[] words = query.Split(new char[] { ' ' });
for (int i = 0; i < words.Length; i++)
if (query.Contains("@")) // First.Last@foo.com, maybe?
{
if (words[i].Length < 3)
string[] words = query.Split(new char[] { '@' });
if (words.Length != 2)
{
if (i != words.Length - 1)
Array.Copy(words, i + 1, words, i, words.Length - i - 1);
Array.Resize(ref words, words.Length - 1);
m_log.DebugFormat("[USER MANAGEMENT MODULE]: Malformed address {0}", query);
return;
}
}
if (words.Length == 0 || words.Length > 2)
return;
words[0] = words[0].Trim(); // it has at least 1
words[1] = words[1].Trim();
if (words.Length == 2) // First.Last @foo.com, maybe?
{
bool found = false;
if (words[0] == String.Empty) // query was @foo.com?
{
foreach (UserData d in m_UserCache.Values)
{
if (d.LastName.ToLower().StartsWith("@" + words[1].ToLower()))
users.Add(d);
}
// We're done
return;
}
// words.Length == 2 and words[0] != string.empty
// first.last@foo.com ?
foreach (UserData d in m_UserCache.Values)
{
if (d.LastName.StartsWith("@") &&
if (d.LastName.StartsWith("@") &&
d.FirstName.ToLower().Equals(words[0].ToLower()) &&
d.LastName.ToLower().Equals(words[1].ToLower()))
d.LastName.ToLower().Equals("@" + words[1].ToLower()))
{
users.Add(d);
found = true;
break;
// It's cached. We're done
return;
}
}
if (!found && words[1].StartsWith("@") && words[0].Contains(".")) // This is it! Let's ask the other world
// This is it! Let's ask the other world
if (words[0].Contains("."))
{
string[] names = words[0].Split(new char[] { '.' });
if (names.Length >= 2)
{
string uriStr = "http://" + words[1].Substring(1); // remove the @
string uriStr = "http://" + words[1];
// Let's check that the last name is a valid address
try
{
@ -115,6 +124,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
}
catch (UriFormatException)
{
m_log.DebugFormat("[USER MANAGEMENT MODULE]: Malformed address {0}", uriStr);
return;
}
@ -125,26 +135,26 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
UserData ud = new UserData();
ud.Id = userID;
ud.FirstName = words[0];
ud.LastName = words[1];
ud.LastName = "@" + words[1];
users.Add(ud);
AddUser(userID, ud.FirstName, ud.LastName, uriStr);
m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0} {1} found", words[0], words[1]);
AddUser(userID, names[0], names[1], uriStr);
m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} found", words[0], words[1]);
}
else
m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0} {1} not found", words[0], words[1]);
m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} not found", words[0], words[1]);
}
}
}
else
{
foreach (UserData d in m_UserCache.Values)
{
if (d.LastName.StartsWith("@") &&
(d.FirstName.ToLower().StartsWith(query.ToLower()) ||
d.LastName.ToLower().StartsWith(query.ToLower())))
users.Add(d);
}
}
//else
//{
// foreach (UserData d in m_UserCache.Values)
// {
// if (d.LastName.StartsWith("@") &&
// (d.FirstName.ToLower().StartsWith(query.ToLower()) ||
// d.LastName.ToLower().StartsWith(query.ToLower())))
// users.Add(d);
// }
//}
}
}

View File

@ -299,7 +299,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
public string GetUserName(UUID uuid)
{
//m_log.DebugFormat("[XXX] GetUserName {0}", uuid);
string[] names = GetUserNames(uuid);
if (names.Length == 2)
{
@ -340,9 +339,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
if (userdata.HomeURL != null && userdata.HomeURL != string.Empty)
{
m_log.DebugFormat(
"[USER MANAGEMENT MODULE]: Did not find url type {0} so requesting urls from '{1}' for {2}",
serverType, userdata.HomeURL, userID);
//m_log.DebugFormat(
// "[USER MANAGEMENT MODULE]: Did not find url type {0} so requesting urls from '{1}' for {2}",
// serverType, userdata.HomeURL, userID);
UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL);
userdata.ServerURLs = uConn.GetServerURLs(userID);
@ -401,11 +400,15 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
public void AddUser(UUID uuid, string first, string last, string homeURL)
{
// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL);
AddUser(uuid, homeURL + ";" + first + " " + last);
}
public void AddUser (UUID id, string creatorData)
{
//m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData);
UserData oldUser;
//lock the whole block - prevent concurrent update
lock (m_UserCache)
@ -431,9 +434,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
return;
}
}
// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData);
UserAccount account = m_Scenes [0].UserAccountService.GetUserAccount (m_Scenes [0].RegionInfo.ScopeID, id);
UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount (m_Scenes [0].RegionInfo.ScopeID, id);
if (account != null)
{
@ -482,9 +484,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
lock (m_UserCache)
m_UserCache[user.Id] = user;
// m_log.DebugFormat(
// "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}",
// user.Id, user.FirstName, user.LastName, user.HomeURL);
//m_log.DebugFormat(
// "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}",
// user.Id, user.FirstName, user.LastName, user.HomeURL);
}
public bool IsLocalGridUser(UUID uuid)

View File

@ -48,8 +48,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
private static bool m_Enabled = false;
private IConfigSource m_Config;
bool m_Registered = false;
GatekeeperServiceInConnector m_HypergridHandler;
private bool m_Registered = false;
private string m_LocalServiceDll = String.Empty;
private GatekeeperServiceInConnector m_HypergridHandler;
private UserAgentServerConnector m_UASHandler;
#region IRegionModule interface
@ -63,6 +65,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
if (m_Enabled)
{
m_log.Info("[HGGRID IN CONNECTOR]: Hypergrid Service In Connector enabled");
IConfig fconfig = config.Configs["FriendsService"];
if (fconfig != null)
{
m_LocalServiceDll = fconfig.GetString("LocalServiceModule", m_LocalServiceDll);
if (m_LocalServiceDll == String.Empty)
m_log.WarnFormat("[HGGRID IN CONNECTOR]: Friends LocalServiceModule config missing");
}
}
}
@ -91,7 +100,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
{
if (!m_Enabled)
return;
}
public void RemoveRegion(Scene scene)
@ -112,14 +120,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
m_log.Info("[HypergridService]: Starting...");
ISimulationService simService = scene.RequestModuleInterface<ISimulationService>();
IFriendsSimConnector friendsConn = scene.RequestModuleInterface<IFriendsSimConnector>();
Object[] args = new Object[] { m_Config };
IFriendsService friendsService = ServerUtils.LoadPlugin<IFriendsService>(m_LocalServiceDll, args);
m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService);
IFriendsSimConnector friendsConn = scene.RequestModuleInterface<IFriendsSimConnector>();
new UserAgentServerConnector(m_Config, MainServer.Instance, friendsConn);
m_UASHandler = new UserAgentServerConnector(m_Config, MainServer.Instance, friendsConn);
new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService");
new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService");
new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService", friendsConn);
}
scene.RegisterModuleInterface<IGatekeeperService>(m_HypergridHandler.GateKeeper);
scene.RegisterModuleInterface<IUserAgentService>(m_UASHandler.HomeUsersService);
}
#endregion

View File

@ -36,36 +36,42 @@ namespace OpenSim.Server.Handlers.Hypergrid
{
public class HGFriendsServerConnector : ServiceConnector
{
private IFriendsService m_FriendsService;
private IUserAgentService m_UserAgentService;
private IHGFriendsService m_TheService;
private string m_ConfigName = "HGFriendsService";
// Called from Robust
public HGFriendsServerConnector(IConfigSource config, IHttpServer server, string configName) :
base(config, server, configName)
this(config, server, configName, null)
{
if (configName != string.Empty)
}
// Called from standalone configurations
public HGFriendsServerConnector(IConfigSource config, IHttpServer server, string configName, IFriendsSimConnector localConn)
: base(config, server, configName)
{
if (configName != string.Empty)
m_ConfigName = configName;
Object[] args = new Object[] { config, m_ConfigName, localConn };
IConfig serverConfig = config.Configs[m_ConfigName];
if (serverConfig == null)
throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
string theService = serverConfig.GetString("LocalServiceModule",
String.Empty);
if (theService == String.Empty)
throw new Exception("No LocalServiceModule in config file");
Object[] args = new Object[] { config };
m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(theService, args);
m_TheService = ServerUtils.LoadPlugin<IHGFriendsService>(theService, args);
theService = serverConfig.GetString("UserAgentService", string.Empty);
if (theService == String.Empty)
throw new Exception("No UserAgentService in " + m_ConfigName);
m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(theService, new Object[] { config, localConn });
m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(theService, args);
server.AddStreamHandler(new HGFriendsServerPostHandler(m_FriendsService, m_UserAgentService));
server.AddStreamHandler(new HGFriendsServerPostHandler(m_TheService, m_UserAgentService, localConn));
}
}
}

View File

@ -39,6 +39,7 @@ using System.Collections.Generic;
using OpenSim.Server.Base;
using OpenSim.Services.Interfaces;
using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
using OpenSim.Framework;
using OpenSim.Framework.Servers.HttpServer;
using OpenMetaverse;
@ -49,15 +50,22 @@ namespace OpenSim.Server.Handlers.Hypergrid
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IFriendsService m_FriendsService;
private IUserAgentService m_UserAgentService;
private IFriendsSimConnector m_FriendsLocalSimConnector;
private IHGFriendsService m_TheService;
public HGFriendsServerPostHandler(IFriendsService service, IUserAgentService uservice) :
public HGFriendsServerPostHandler(IHGFriendsService service, IUserAgentService uas, IFriendsSimConnector friendsConn) :
base("POST", "/hgfriends")
{
m_FriendsService = service;
m_UserAgentService = uservice;
m_log.DebugFormat("[HGFRIENDS HANDLER]: HGFriendsServerPostHandler is On");
m_TheService = service;
m_UserAgentService = uas;
m_FriendsLocalSimConnector = friendsConn;
m_log.DebugFormat("[HGFRIENDS HANDLER]: HGFriendsServerPostHandler is On ({0})",
(m_FriendsLocalSimConnector == null ? "robust" : "standalone"));
if (m_TheService == null)
m_log.ErrorFormat("[HGFRIENDS HANDLER]: TheService is null!");
}
public override byte[] Handle(string path, Stream requestData,
@ -90,6 +98,26 @@ namespace OpenSim.Server.Handlers.Hypergrid
case "deletefriendship":
return DeleteFriendship(request);
/* Same as inter-sim */
case "friendship_offered":
return FriendshipOffered(request);
case "validate_friendship_offered":
return ValidateFriendshipOffered(request);
/*
case "friendship_approved":
return FriendshipApproved(request);
case "friendship_denied":
return FriendshipDenied(request);
case "friendship_terminated":
return FriendshipTerminated(request);
case "grant_rights":
return GrantRights(request);
*/
}
m_log.DebugFormat("[HGFRIENDS HANDLER]: unknown method {0} request {1}", method.Length, method);
}
@ -126,39 +154,20 @@ namespace OpenSim.Server.Handlers.Hypergrid
return FailureResult();
}
FriendInfo[] friendsInfo = m_FriendsService.GetFriends(principalID);
foreach (FriendInfo finfo in friendsInfo)
{
if (finfo.Friend.StartsWith(friendID.ToString()))
return SuccessResult(finfo.TheirFlags.ToString());
}
int perms = m_TheService.GetFriendPerms(principalID, friendID);
if (perms < 0)
return FailureResult("Friend not found");
return FailureResult("Friend not found");
return SuccessResult(perms.ToString());
}
byte[] NewFriendship(Dictionary<string, object> request)
{
if (!VerifyServiceKey(request))
return FailureResult();
bool verified = VerifyServiceKey(request);
// OK, can proceed
FriendInfo friend = new FriendInfo(request);
UUID friendID;
string tmp = string.Empty;
if (!Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out tmp, out tmp, out tmp, out tmp))
return FailureResult();
m_log.DebugFormat("[HGFRIENDS HANDLER]: New friendship {0} {1}", friend.PrincipalID, friend.Friend);
// If the friendship already exists, return fail
FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID);
foreach (FriendInfo finfo in finfos)
if (finfo.Friend.StartsWith(friendID.ToString()))
return FailureResult();
// the user needs to confirm when he gets home
bool success = m_FriendsService.StoreFriend(friend.PrincipalID.ToString(), friend.Friend, 0);
bool success = m_TheService.NewFriendship(friend, verified);
if (success)
return SuccessResult();
@ -174,25 +183,53 @@ namespace OpenSim.Server.Handlers.Hypergrid
secret = request["SECRET"].ToString();
if (secret == string.Empty)
return FailureResult();
return BoolResult(false);
FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID);
foreach (FriendInfo finfo in finfos)
{
// We check the secret here
if (finfo.Friend.StartsWith(friend.Friend) && finfo.Friend.EndsWith(secret))
{
m_log.DebugFormat("[HGFRIENDS HANDLER]: Delete friendship {0} {1}", friend.PrincipalID, friend.Friend);
m_FriendsService.Delete(friend.PrincipalID, finfo.Friend);
m_FriendsService.Delete(finfo.Friend, friend.PrincipalID.ToString());
bool success = m_TheService.DeleteFriendship(friend, secret);
return SuccessResult();
}
}
return FailureResult();
return BoolResult(success);
}
byte[] FriendshipOffered(Dictionary<string, object> request)
{
UUID fromID = UUID.Zero;
UUID toID = UUID.Zero;
string message = string.Empty;
string name = string.Empty;
m_log.DebugFormat("[HGFRIENDS HANDLER]: Friendship offered");
if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID"))
return BoolResult(false);
if (!UUID.TryParse(request["ToID"].ToString(), out toID))
return BoolResult(false);
message = request["Message"].ToString();
if (!UUID.TryParse(request["FromID"].ToString(), out fromID))
return BoolResult(false);
if (request.ContainsKey("FromName"))
name = request["FromName"].ToString();
bool success = m_TheService.FriendshipOffered(fromID, name, toID, message);
return BoolResult(success);
}
byte[] ValidateFriendshipOffered(Dictionary<string, object> request)
{
FriendInfo friend = new FriendInfo(request);
UUID friendID = UUID.Zero;
if (!UUID.TryParse(friend.Friend, out friendID))
return BoolResult(false);
bool success = m_TheService.ValidateFriendshipOffered(friend.PrincipalID, friendID);
return BoolResult(success);
}
#endregion
#region Misc
@ -205,10 +242,15 @@ namespace OpenSim.Server.Handlers.Hypergrid
return false;
}
if (request["KEY"] == null || request["SESSIONID"] == null)
return false;
string serviceKey = request["KEY"].ToString();
string sessionStr = request["SESSIONID"].ToString();
UUID sessionID;
UUID.TryParse(sessionStr, out sessionID);
if (!UUID.TryParse(sessionStr, out sessionID) || serviceKey == string.Empty)
return false;
if (!m_UserAgentService.VerifyAgent(sessionID, serviceKey))
{
@ -256,7 +298,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
doc.AppendChild(rootElement);
XmlElement result = doc.CreateElement("", "Result", "");
XmlElement result = doc.CreateElement("", "RESULT", "");
result.AppendChild(doc.CreateTextNode("Success"));
rootElement.AppendChild(result);
@ -289,7 +331,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
doc.AppendChild(rootElement);
XmlElement result = doc.CreateElement("", "Result", "");
XmlElement result = doc.CreateElement("", "RESULT", "");
result.AppendChild(doc.CreateTextNode("Failure"));
rootElement.AppendChild(result);
@ -302,6 +344,28 @@ namespace OpenSim.Server.Handlers.Hypergrid
return DocToBytes(doc);
}
private byte[] BoolResult(bool 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(value.ToString()));
rootElement.AppendChild(result);
return DocToBytes(doc);
}
private byte[] DocToBytes(XmlDocument doc)
{
MemoryStream ms = new MemoryStream();
@ -313,6 +377,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
return ms.ToArray();
}
#endregion
}
}

View File

@ -52,6 +52,11 @@ namespace OpenSim.Server.Handlers.Hypergrid
// MethodBase.GetCurrentMethod().DeclaringType);
private IUserAgentService m_HomeUsersService;
public IUserAgentService HomeUsersService
{
get { return m_HomeUsersService; }
}
private string[] m_AuthorizedCallers;
private bool m_VerifyCallers = false;

View File

@ -43,7 +43,17 @@ namespace OpenSim.Services.Connectors.Friends
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected virtual string ServicePath()
{
return "friends";
}
public bool FriendshipOffered(GridRegion region, UUID userID, UUID friendID, string message)
{
return FriendshipOffered(region, userID, friendID, message, String.Empty);
}
public virtual bool FriendshipOffered(GridRegion region, UUID userID, UUID friendID, string message, string userName)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
//sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
@ -53,9 +63,10 @@ namespace OpenSim.Services.Connectors.Friends
sendData["FromID"] = userID.ToString();
sendData["ToID"] = friendID.ToString();
sendData["Message"] = message;
if (userName != String.Empty)
sendData["FromName"] = userName;
return Call(region, sendData);
}
public bool FriendshipApproved(GridRegion region, UUID userID, string userName, UUID friendID)
@ -138,8 +149,11 @@ namespace OpenSim.Services.Connectors.Friends
if (region == null)
return false;
m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: region: {0}", region.ExternalHostName + ":" + region.HttpPort);
string uri = "http://" + region.ExternalHostName + ":" + region.HttpPort + "/friends";
string path = ServicePath();
if (!region.ServerURI.EndsWith("/"))
path = "/" + path;
string uri = region.ServerURI + path;
m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: calling {0}", uri);
try
{

View File

@ -40,7 +40,7 @@ using OpenMetaverse;
namespace OpenSim.Services.Connectors.Hypergrid
{
public class HGFriendsServicesConnector
public class HGFriendsServicesConnector : FriendsSimConnector
{
private static readonly ILog m_log =
LogManager.GetLogger(
@ -66,6 +66,11 @@ namespace OpenSim.Services.Connectors.Hypergrid
m_SessionID = sessionID;
}
protected override string ServicePath()
{
return "hgfriends";
}
#region IFriendsService
public uint GetFriendPerms(UUID PrincipalID, UUID friendID)
@ -187,23 +192,69 @@ namespace OpenSim.Services.Connectors.Hypergrid
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null))
if (replyData.ContainsKey("RESULT"))
{
bool success = false;
Boolean.TryParse(replyData["Result"].ToString(), out success);
return success;
if (replyData["RESULT"].ToString().ToLower() == "true")
return true;
else
return false;
}
else
m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Delete {0} {1} received null response",
PrincipalID, Friend);
m_log.DebugFormat("[HGFRIENDS CONNECTOR]: reply data does not contain result field");
}
else
m_log.DebugFormat("[HGFRIENDS CONNECTOR]: DeleteFriend received null reply");
m_log.DebugFormat("[HGFRIENDS CONNECTOR]: received empty reply");
return false;
}
public bool ValidateFriendshipOffered(UUID fromID, UUID toID)
{
FriendInfo finfo = new FriendInfo();
finfo.PrincipalID = fromID;
finfo.Friend = toID.ToString();
Dictionary<string, object> sendData = finfo.ToKeyValuePairs();
sendData["METHOD"] = "validate_friendship_offered";
string reply = string.Empty;
string uri = m_ServerURI + "/hgfriends";
try
{
reply = SynchronousRestFormsRequester.MakeRequest("POST",
uri,
ServerUtils.BuildQueryString(sendData));
}
catch (Exception e)
{
m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server at {0}: {1}", uri, e.Message);
return false;
}
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
if (replyData.ContainsKey("RESULT"))
{
if (replyData["RESULT"].ToString().ToLower() == "true")
return true;
else
return false;
}
else
m_log.DebugFormat("[HGFRIENDS CONNECTOR]: reply data does not contain result field");
}
else
m_log.DebugFormat("[HGFRIENDS CONNECTOR]: received empty reply");
return false;
}
#endregion
}
}

View File

@ -0,0 +1,301 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Net;
using System.Reflection;
using OpenSim.Framework;
using OpenSim.Services.Connectors.Friends;
using OpenSim.Services.Connectors.Hypergrid;
using OpenSim.Services.Interfaces;
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
using OpenSim.Server.Base;
using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
using OpenMetaverse;
using log4net;
using Nini.Config;
namespace OpenSim.Services.HypergridService
{
/// <summary>
/// W2W social networking
/// </summary>
public class HGFriendsService : IHGFriendsService
{
private static readonly ILog m_log =
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
static bool m_Initialized = false;
protected static IGridUserService m_GridUserService;
protected static IGridService m_GridService;
protected static IGatekeeperService m_GatekeeperService;
protected static IFriendsService m_FriendsService;
protected static IPresenceService m_PresenceService;
protected static IUserAccountService m_UserAccountService;
protected static IFriendsSimConnector m_FriendsLocalSimConnector; // standalone, points to HGFriendsModule
protected static FriendsSimConnector m_FriendsSimConnector; // grid
private static string m_ConfigName = "HGFriendsService";
public HGFriendsService(IConfigSource config, String configName, IFriendsSimConnector localSimConn)
{
if (m_FriendsLocalSimConnector == null)
m_FriendsLocalSimConnector = localSimConn;
if (!m_Initialized)
{
m_Initialized = true;
if (configName != String.Empty)
m_ConfigName = configName;
Object[] args = new Object[] { config };
IConfig serverConfig = config.Configs[m_ConfigName];
if (serverConfig == null)
throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
string theService = serverConfig.GetString("FriendsService", string.Empty);
if (theService == String.Empty)
throw new Exception("No FriendsService in config file " + m_ConfigName);
m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(theService, args);
theService = serverConfig.GetString("UserAccountService", string.Empty);
if (theService == String.Empty)
throw new Exception("No UserAccountService in " + m_ConfigName);
m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(theService, args);
theService = serverConfig.GetString("GridService", string.Empty);
if (theService == String.Empty)
throw new Exception("No GridService in " + m_ConfigName);
m_GridService = ServerUtils.LoadPlugin<IGridService>(theService, args);
theService = serverConfig.GetString("PresenceService", string.Empty);
if (theService == String.Empty)
throw new Exception("No PresenceService in " + m_ConfigName);
m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(theService, args);
m_FriendsSimConnector = new FriendsSimConnector();
m_log.DebugFormat("[HGFRIENDS SERVICE]: Starting...");
}
}
#region IHGFriendsService
public int GetFriendPerms(UUID userID, UUID friendID)
{
FriendInfo[] friendsInfo = m_FriendsService.GetFriends(userID);
foreach (FriendInfo finfo in friendsInfo)
{
if (finfo.Friend.StartsWith(friendID.ToString()))
return finfo.TheirFlags;
}
return -1;
}
public bool NewFriendship(FriendInfo friend, bool verified)
{
UUID friendID;
string tmp = string.Empty, url = String.Empty, first = String.Empty, last = String.Empty;
if (!Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out url, out first, out last, out tmp))
return false;
m_log.DebugFormat("[HGFRIENDS SERVICE]: New friendship {0} {1} ({2})", friend.PrincipalID, friend.Friend, verified);
// Does the friendship already exist?
FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID);
foreach (FriendInfo finfo in finfos)
{
if (finfo.Friend.StartsWith(friendID.ToString()))
return false;
}
// Verified user session. But the user needs to confirm friendship when he gets home
if (verified)
return m_FriendsService.StoreFriend(friend.PrincipalID.ToString(), friend.Friend, 0);
// Does the reverted friendship exist? meaning that this user initiated the request
finfos = m_FriendsService.GetFriends(friendID);
bool userInitiatedOffer = false;
foreach (FriendInfo finfo in finfos)
{
if (friend.Friend.StartsWith(finfo.PrincipalID.ToString()) && finfo.Friend.StartsWith(friend.PrincipalID.ToString()) && finfo.TheirFlags == -1)
{
userInitiatedOffer = true;
// Let's delete the existing friendship relations that was stored
m_FriendsService.Delete(friendID, finfo.Friend);
break;
}
}
if (userInitiatedOffer)
{
m_FriendsService.StoreFriend(friend.PrincipalID.ToString(), friend.Friend, 1);
m_FriendsService.StoreFriend(friend.Friend, friend.PrincipalID.ToString(), 1);
// notify the user
ForwardToSim("ApproveFriendshipRequest", friendID, Util.UniversalName(first, last, url), "", friend.PrincipalID, "");
return true;
}
return false;
}
public bool DeleteFriendship(FriendInfo friend, string secret)
{
FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID);
foreach (FriendInfo finfo in finfos)
{
// We check the secret here. Or if the friendship request was initiated here, and was declined
if (finfo.Friend.StartsWith(friend.Friend) && finfo.Friend.EndsWith(secret))
{
m_log.DebugFormat("[HGFRIENDS SERVICE]: Delete friendship {0} {1}", friend.PrincipalID, friend.Friend);
m_FriendsService.Delete(friend.PrincipalID, finfo.Friend);
m_FriendsService.Delete(finfo.Friend, friend.PrincipalID.ToString());
return true;
}
}
return false;
}
public bool FriendshipOffered(UUID fromID, string fromName, UUID toID, string message)
{
UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, toID);
if (account == null)
return false;
// OK, we have that user here.
// So let's send back the call, but start a thread to continue
// with the verification and the actual action.
Util.FireAndForget(delegate { ProcessFriendshipOffered(fromID, fromName, toID, message); });
return true;
}
public bool ValidateFriendshipOffered(UUID fromID, UUID toID)
{
FriendInfo[] finfos = m_FriendsService.GetFriends(toID.ToString());
foreach (FriendInfo fi in finfos)
{
if (fi.Friend.StartsWith(fromID.ToString()) && fi.TheirFlags == -1)
return true;
}
return false;
}
#endregion IHGFriendsService
#region Aux
private void ProcessFriendshipOffered(UUID fromID, String fromName, UUID toID, String message)
{
// Great, it's a genuine request. Let's proceed.
// But now we need to confirm that the requester is who he says he is
// before we act on the friendship request.
if (!fromName.Contains("@"))
return;
string[] parts = fromName.Split(new char[] {'@'});
if (parts.Length != 2)
return;
string uriStr = "http://" + parts[1];
try
{
new Uri(uriStr);
}
catch (UriFormatException)
{
return;
}
UserAgentServiceConnector uasConn = new UserAgentServiceConnector(uriStr);
Dictionary<string, object> servers = uasConn.GetServerURLs(fromID);
if (!servers.ContainsKey("FriendsServerURI"))
return;
HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(servers["FriendsServerURI"].ToString());
if (!friendsConn.ValidateFriendshipOffered(fromID, toID))
{
m_log.WarnFormat("[HGFRIENDS SERVICE]: Friendship request from {0} to {1} is invalid. Impersonations?", fromID, toID);
return;
}
string fromUUI = Util.UniversalIdentifier(fromID, parts[0], "@" + parts[1], uriStr);
// OK, we're good!
ForwardToSim("FriendshipOffered", fromID, fromName, fromUUI, toID, message);
}
private bool ForwardToSim(string op, UUID fromID, string name, String fromUUI, UUID toID, string message)
{
PresenceInfo session = null;
GridRegion region = null;
PresenceInfo[] sessions = m_PresenceService.GetAgents(new string[] { toID.ToString() });
if (sessions != null && sessions.Length > 0)
session = sessions[0];
if (session != null)
region = m_GridService.GetRegionByUUID(UUID.Zero, session.RegionID);
switch (op)
{
case "FriendshipOffered":
// Let's store backwards
string secret = UUID.Random().ToString().Substring(0, 8);
m_FriendsService.StoreFriend(toID.ToString(), fromUUI + ";" + secret, 0);
if (m_FriendsLocalSimConnector != null) // standalone
{
GridInstantMessage im = new GridInstantMessage(null, fromID, name, toID,
(byte)InstantMessageDialog.FriendshipOffered, message, false, Vector3.Zero);
// !! HACK
im.imSessionID = im.fromAgentID;
return m_FriendsLocalSimConnector.LocalFriendshipOffered(toID, im);
}
else if (region != null) // grid
return m_FriendsSimConnector.FriendshipOffered(region, fromID, toID, message, name);
break;
case "ApproveFriendshipRequest":
if (m_FriendsLocalSimConnector != null) // standalone
return m_FriendsLocalSimConnector.LocalFriendshipApproved(fromID, name, toID);
else if (region != null) //grid
return m_FriendsSimConnector.FriendshipApproved(region, fromID, name, toID);
break;
}
return false;
}
#endregion Aux
}
}

View File

@ -81,6 +81,17 @@ namespace OpenSim.Services.Interfaces
public interface IFriendsSimConnector
{
bool StatusNotify(UUID userID, UUID friendID, bool online);
bool LocalFriendshipOffered(UUID toID, GridInstantMessage im);
bool LocalFriendshipApproved(UUID userID, string userName, UUID friendID);
}
public interface IHGFriendsService
{
int GetFriendPerms(UUID userID, UUID friendID);
bool NewFriendship(FriendInfo finfo, bool verified);
bool DeleteFriendship(FriendInfo finfo, string secret);
bool FriendshipOffered(UUID from, string fromName, UUID to, string message);
bool ValidateFriendshipOffered(UUID fromID, UUID toID);
}
public interface IInstantMessageSimConnector

View File

@ -159,8 +159,12 @@
UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService"
[HGFriendsService]
LocalServiceModule = "OpenSim.Services.FriendsService.dll:FriendsService"
LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGFriendsService"
UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService"
FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService"
UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService"
GridService = "OpenSim.Services.GridService.dll:GridService"
PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService"
[HGInstantMessageService]
LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService"