OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
HGFriendsModule.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Reflection;
32 using System.Threading;
33 using log4net;
34 using Nini.Config;
35 using Nwc.XmlRpc;
36 using Mono.Addins;
37 using OpenMetaverse;
38 using OpenSim.Framework;
39 using OpenSim.Region.Framework.Interfaces;
40 using OpenSim.Region.Framework.Scenes;
41 using OpenSim.Services.Interfaces;
42 using OpenSim.Services.Connectors.Hypergrid;
46 
47 namespace OpenSim.Region.CoreModules.Avatar.Friends
48 {
49  [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HGFriendsModule")]
51  {
52  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 
54  private int m_levelHGFriends = 0;
55 
56  IUserManagement m_uMan;
57  public IUserManagement UserManagementModule
58  {
59  get
60  {
61  if (m_uMan == null)
62  m_uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
63  return m_uMan;
64  }
65  }
66 
67  protected HGFriendsServicesConnector m_HGFriendsConnector = new HGFriendsServicesConnector();
69 
70  #region ISharedRegionModule
71  public override string Name
72  {
73  get { return "HGFriendsModule"; }
74  }
75 
76  public override void AddRegion(Scene scene)
77  {
78  if (!m_Enabled)
79  return;
80 
81  base.AddRegion(scene);
82  scene.RegisterModuleInterface<IFriendsSimConnector>(this);
83  }
84 
85  public override void RegionLoaded(Scene scene)
86  {
87  if (!m_Enabled)
88  return;
89  if (m_StatusNotifier == null)
90  m_StatusNotifier = new HGStatusNotifier(this);
91  }
92 
93  protected override void InitModule(IConfigSource config)
94  {
95  base.InitModule(config);
96 
97  // Additionally to the base method
98  IConfig friendsConfig = config.Configs["HGFriendsModule"];
99  if (friendsConfig != null)
100  {
101  m_levelHGFriends = friendsConfig.GetInt("LevelHGFriends", 0);
102 
103  // TODO: read in all config variables pertaining to
104  // HG friendship permissions
105  }
106  }
107 
108  #endregion
109 
110  #region IFriendsSimConnector
111 
119  public bool StatusNotify(UUID friendID, UUID userID, bool online)
120  {
121  return LocalStatusNotification(friendID, userID, online);
122  }
123 
124  #endregion
125 
126  protected override void OnInstantMessage(IClientAPI client, GridInstantMessage im)
127  {
128  if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered)
129  {
130  // we got a friendship offer
131  UUID principalID = new UUID(im.fromAgentID);
132  UUID friendID = new UUID(im.toAgentID);
133 
134  // Check if friendID is foreigner and if principalID has the permission
135  // to request friendships with foreigners. If not, return immediately.
136  if (!UserManagementModule.IsLocalGridUser(friendID))
137  {
138  ScenePresence avatar = null;
139  ((Scene)client.Scene).TryGetScenePresence(principalID, out avatar);
140 
141  if (avatar == null)
142  return;
143 
144  if (avatar.UserLevel < m_levelHGFriends)
145  {
146  client.SendAgentAlertMessage("Unable to send friendship invitation to foreigner. Insufficient permissions.", false);
147  return;
148  }
149  }
150  }
151 
152  base.OnInstantMessage(client, im);
153  }
154 
155  protected override void OnApproveFriendRequest(IClientAPI client, UUID friendID, List<UUID> callingCardFolders)
156  {
157  // Update the local cache. Yes, we need to do it right here
158  // because the HGFriendsService placed something on the DB
159  // from under the sim
160  base.OnApproveFriendRequest(client, friendID, callingCardFolders);
161  }
162 
163  protected override bool CacheFriends(IClientAPI client)
164  {
165 // m_log.DebugFormat("[HGFRIENDS MODULE]: Entered CacheFriends for {0}", client.Name);
166 
167  if (base.CacheFriends(client))
168  {
169  UUID agentID = client.AgentId;
170  // we do this only for the root agent
171  if (m_Friends[agentID].Refcount == 1)
172  {
173  // We need to preload the user management cache with the names
174  // of foreign friends, just like we do with SOPs' creators
175  foreach (FriendInfo finfo in m_Friends[agentID].Friends)
176  {
177  if (finfo.TheirFlags != -1)
178  {
179  UUID id;
180  if (!UUID.TryParse(finfo.Friend, out id))
181  {
182  string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
183  if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last, out tmp))
184  {
185  IUserManagement uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
186  m_log.DebugFormat("[HGFRIENDS MODULE]: caching {0}", finfo.Friend);
187  uMan.AddUser(id, url + ";" + first + " " + last);
188  }
189  }
190  }
191  }
192 
193 // m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting CacheFriends for {0} since detected root agent", client.Name);
194  return true;
195  }
196  }
197 
198 // m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting CacheFriends for {0} since detected not root agent", client.Name);
199  return false;
200  }
201 
202  public override bool SendFriendsOnlineIfNeeded(IClientAPI client)
203  {
204 // m_log.DebugFormat("[HGFRIENDS MODULE]: Entering SendFriendsOnlineIfNeeded for {0}", client.Name);
205 
206  if (base.SendFriendsOnlineIfNeeded(client))
207  {
208  AgentCircuitData aCircuit = ((Scene)client.Scene).AuthenticateHandler.GetAgentCircuitData(client.AgentId);
209  if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0)
210  {
211  UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, client.AgentId);
212  if (account == null) // foreign
213  {
214  FriendInfo[] friends = GetFriendsFromCache(client.AgentId);
215  foreach (FriendInfo f in friends)
216  {
217  client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags);
218  }
219  }
220  }
221  }
222 
223 // m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting SendFriendsOnlineIfNeeded for {0}", client.Name);
224  return false;
225  }
226 
227  protected override void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
228  {
229 // m_log.DebugFormat("[HGFRIENDS MODULE]: Entering GetOnlineFriends for {0}", userID);
230 
231  List<string> fList = new List<string>();
232  foreach (string s in friendList)
233  {
234  if (s.Length < 36)
235  m_log.WarnFormat(
236  "[HGFRIENDS MODULE]: Ignoring friend {0} ({1} chars) for {2} since identifier too short",
237  s, s.Length, userID);
238  else
239  fList.Add(s.Substring(0, 36));
240  }
241 
242  // FIXME: also query the presence status of friends in other grids (like in HGStatusNotifier.Notify())
243 
244  PresenceInfo[] presence = PresenceService.GetAgents(fList.ToArray());
245  foreach (PresenceInfo pi in presence)
246  {
247  UUID presenceID;
248  if (UUID.TryParse(pi.UserID, out presenceID))
249  online.Add(presenceID);
250  }
251 
252 // m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting GetOnlineFriends for {0}", userID);
253  }
254 
255  protected override void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
256  {
257  //m_log.DebugFormat("[HGFRIENDS MODULE]: Entering StatusNotify for {0}", userID);
258 
259  // First, let's divide the friends on a per-domain basis
260  Dictionary<string, List<FriendInfo>> friendsPerDomain = new Dictionary<string, List<FriendInfo>>();
261  foreach (FriendInfo friend in friendList)
262  {
263  UUID friendID;
264  if (UUID.TryParse(friend.Friend, out friendID))
265  {
266  if (!friendsPerDomain.ContainsKey("local"))
267  friendsPerDomain["local"] = new List<FriendInfo>();
268  friendsPerDomain["local"].Add(friend);
269  }
270  else
271  {
272  // it's a foreign friend
273  string url = string.Empty, tmp = string.Empty;
274  if (Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out url, out tmp, out tmp, out tmp))
275  {
276  // Let's try our luck in the local sim. Who knows, maybe it's here
277  if (LocalStatusNotification(userID, friendID, online))
278  continue;
279 
280  if (!friendsPerDomain.ContainsKey(url))
281  friendsPerDomain[url] = new List<FriendInfo>();
282  friendsPerDomain[url].Add(friend);
283  }
284  }
285  }
286 
287  // For the local friends, just call the base method
288  // Let's do this first of all
289  if (friendsPerDomain.ContainsKey("local"))
290  base.StatusNotify(friendsPerDomain["local"], userID, online);
291 
292  m_StatusNotifier.Notify(userID, friendsPerDomain, online);
293 
294 // m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting StatusNotify for {0}", userID);
295  }
296 
297  protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
298  {
299  first = "Unknown"; last = "UserHGGAI";
300  if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last))
301  return true;
302 
303  // fid is not a UUID...
304  string url = string.Empty, tmp = string.Empty, f = string.Empty, l = string.Empty;
305  if (Util.ParseUniversalUserIdentifier(fid, out agentID, out url, out f, out l, out tmp))
306  {
307  if (!agentID.Equals(UUID.Zero))
308  {
309  m_uMan.AddUser(agentID, f, l, url);
310 
311  string name = m_uMan.GetUserName(agentID);
312  string[] parts = name.Trim().Split(new char[] { ' ' });
313  if (parts.Length == 2)
314  {
315  first = parts[0];
316  last = parts[1];
317  }
318  else
319  {
320  first = f;
321  last = l;
322  }
323  return true;
324  }
325  }
326  return false;
327  }
328 
329  protected override string GetFriendshipRequesterName(UUID agentID)
330  {
331  return m_uMan.GetUserName(agentID);
332  }
333 
334  protected override string FriendshipMessage(string friendID)
335  {
336  UUID id;
337  if (UUID.TryParse(friendID, out id))
338  return base.FriendshipMessage(friendID);
339 
340  return "Please confirm this friendship you made while you were away.";
341  }
342 
343  protected override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
344  {
345  foreach (FriendInfo fi in friends)
346  {
347  if (fi.Friend.StartsWith(friendID.ToString()))
348  return fi;
349  }
350  return null;
351  }
352 
353  public override FriendInfo[] GetFriendsFromService(IClientAPI client)
354  {
355  // m_log.DebugFormat("[HGFRIENDS MODULE]: Entering GetFriendsFromService for {0}", client.Name);
356  Boolean agentIsLocal = true;
357  if (UserManagementModule != null)
358  agentIsLocal = UserManagementModule.IsLocalGridUser(client.AgentId);
359 
360  if (agentIsLocal)
361  return base.GetFriendsFromService(client);
362 
363  FriendInfo[] finfos = new FriendInfo[0];
364  // Foreigner
365  AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
366  if (agentClientCircuit != null)
367  {
368  // Note that this is calling a different interface than base; this one calls with a string param!
369  finfos = FriendsService.GetFriends(client.AgentId.ToString());
370  m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, client.AgentId.ToString());
371  }
372 
373  // m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting GetFriendsFromService for {0}", client.Name);
374 
375  return finfos;
376  }
377 
378  protected override bool StoreRights(UUID agentID, UUID friendID, int rights)
379  {
380  Boolean agentIsLocal = true;
381  Boolean friendIsLocal = true;
382  if (UserManagementModule != null)
383  {
384  agentIsLocal = UserManagementModule.IsLocalGridUser(agentID);
385  friendIsLocal = UserManagementModule.IsLocalGridUser(friendID);
386  }
387 
388  // Are they both local users?
389  if (agentIsLocal && friendIsLocal)
390  {
391  // local grid users
392  return base.StoreRights(agentID, friendID, rights);
393  }
394 
395  if (agentIsLocal) // agent is local, friend is foreigner
396  {
397  FriendInfo[] finfos = GetFriendsFromCache(agentID);
398  FriendInfo finfo = GetFriend(finfos, friendID);
399  if (finfo != null)
400  {
401  FriendsService.StoreFriend(agentID.ToString(), finfo.Friend, rights);
402  return true;
403  }
404  }
405 
406  if (friendIsLocal) // agent is foreigner, friend is local
407  {
408  string agentUUI = GetUUI(friendID, agentID);
409  if (agentUUI != string.Empty)
410  {
411  FriendsService.StoreFriend(agentUUI, friendID.ToString(), rights);
412  return true;
413  }
414  }
415 
416  return false;
417  }
418 
419  protected override void StoreBackwards(UUID friendID, UUID agentID)
420  {
421  bool agentIsLocal = true;
422 // bool friendIsLocal = true;
423 
424  if (UserManagementModule != null)
425  {
426  agentIsLocal = UserManagementModule.IsLocalGridUser(agentID);
427 // friendIsLocal = UserManagementModule.IsLocalGridUser(friendID);
428  }
429 
430  // Is the requester a local user?
431  if (agentIsLocal)
432  {
433  // local grid users
434  m_log.DebugFormat("[HGFRIENDS MODULE]: Friendship requester is local. Storing backwards.");
435 
436  base.StoreBackwards(friendID, agentID);
437  return;
438  }
439 
440  // no provision for this temporary friendship state when user is not local
441  //FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0);
442  }
443 
444  protected override void StoreFriendships(UUID agentID, UUID friendID)
445  {
446  Boolean agentIsLocal = true;
447  Boolean friendIsLocal = true;
448  if (UserManagementModule != null)
449  {
450  agentIsLocal = UserManagementModule.IsLocalGridUser(agentID);
451  friendIsLocal = UserManagementModule.IsLocalGridUser(friendID);
452  }
453 
454  // Are they both local users?
455  if (agentIsLocal && friendIsLocal)
456  {
457  // local grid users
458  m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local");
459  base.StoreFriendships(agentID, friendID);
460  return;
461  }
462 
463  // ok, at least one of them is foreigner, let's get their data
464  IClientAPI agentClient = LocateClientObject(agentID);
465  IClientAPI friendClient = LocateClientObject(friendID);
466  AgentCircuitData agentClientCircuit = null;
467  AgentCircuitData friendClientCircuit = null;
468  string agentUUI = string.Empty;
469  string friendUUI = string.Empty;
470  string agentFriendService = string.Empty;
471  string friendFriendService = string.Empty;
472 
473  if (agentClient != null)
474  {
475  agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode);
476  agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
477  agentFriendService = agentClientCircuit.ServiceURLs["FriendsServerURI"].ToString();
478  RecacheFriends(agentClient);
479  }
480  if (friendClient != null)
481  {
482  friendClientCircuit = ((Scene)(friendClient.Scene)).AuthenticateHandler.GetAgentCircuitData(friendClient.CircuitCode);
483  friendUUI = Util.ProduceUserUniversalIdentifier(friendClientCircuit);
484  friendFriendService = friendClientCircuit.ServiceURLs["FriendsServerURI"].ToString();
485  RecacheFriends(friendClient);
486  }
487 
488  m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}",
489  agentUUI, friendUUI, agentFriendService, friendFriendService);
490 
491  // Generate a random 8-character hex number that will sign this friendship
492  string secret = UUID.Random().ToString().Substring(0, 8);
493 
494  string theFriendUUID = friendUUI + ";" + secret;
495  string agentUUID = agentUUI + ";" + secret;
496 
497  if (agentIsLocal) // agent is local, 'friend' is foreigner
498  {
499  // This may happen when the agent returned home, in which case the friend is not there
500  // We need to look for its information in the friends list itself
501  FriendInfo[] finfos = null;
502  bool confirming = false;
503  if (friendUUI == string.Empty)
504  {
505  finfos = GetFriendsFromCache(agentID);
506  foreach (FriendInfo finfo in finfos)
507  {
508  if (finfo.TheirFlags == -1)
509  {
510  if (finfo.Friend.StartsWith(friendID.ToString()))
511  {
512  friendUUI = finfo.Friend;
513  theFriendUUID = friendUUI;
514  UUID utmp = UUID.Zero;
515  string url = String.Empty;
516  string first = String.Empty;
517  string last = String.Empty;
518 
519  // If it's confirming the friendship, we already have the full UUI with the secret
520  if (Util.ParseUniversalUserIdentifier(theFriendUUID, out utmp, out url, out first, out last, out secret))
521  {
522  agentUUID = agentUUI + ";" + secret;
523  m_uMan.AddUser(utmp, first, last, url);
524  }
525  confirming = true;
526  break;
527  }
528  }
529  }
530  if (!confirming)
531  {
532  friendUUI = m_uMan.GetUserUUI(friendID);
533  theFriendUUID = friendUUI + ";" + secret;
534  }
535 
536  friendFriendService = m_uMan.GetUserServerURL(friendID, "FriendsServerURI");
537 
538  // m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}",
539  // agentUUI, friendUUI, agentFriendService, friendFriendService);
540 
541  }
542 
543  // Delete any previous friendship relations
544  DeletePreviousRelations(agentID, friendID);
545 
546  // store in the local friends service a reference to the foreign friend
547  FriendsService.StoreFriend(agentID.ToString(), theFriendUUID, 1);
548  // and also the converse
549  FriendsService.StoreFriend(theFriendUUID, agentID.ToString(), 1);
550 
551  //if (!confirming)
552  //{
553  // store in the foreign friends service a reference to the local agent
554  HGFriendsServicesConnector friendsConn = null;
555  if (friendClientCircuit != null) // the friend is here, validate session
556  friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID);
557  else // the friend is not here, he initiated the request in his home world
558  friendsConn = new HGFriendsServicesConnector(friendFriendService);
559 
560  friendsConn.NewFriendship(friendID, agentUUID);
561  //}
562  }
563  else if (friendIsLocal) // 'friend' is local, agent is foreigner
564  {
565  // Delete any previous friendship relations
566  DeletePreviousRelations(agentID, friendID);
567 
568  // store in the local friends service a reference to the foreign agent
569  FriendsService.StoreFriend(friendID.ToString(), agentUUI + ";" + secret, 1);
570  // and also the converse
571  FriendsService.StoreFriend(agentUUI + ";" + secret, friendID.ToString(), 1);
572 
573  if (agentClientCircuit != null)
574  {
575  // store in the foreign friends service a reference to the local agent
576  HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID);
577  friendsConn.NewFriendship(agentID, friendUUI + ";" + secret);
578  }
579  }
580  else // They're both foreigners!
581  {
582  HGFriendsServicesConnector friendsConn;
583  if (agentClientCircuit != null)
584  {
585  friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID);
586  friendsConn.NewFriendship(agentID, friendUUI + ";" + secret);
587  }
588  if (friendClientCircuit != null)
589  {
590  friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID);
591  friendsConn.NewFriendship(friendID, agentUUI + ";" + secret);
592  }
593  }
594  // my brain hurts now
595  }
596 
597  private void DeletePreviousRelations(UUID a1, UUID a2)
598  {
599  // Delete any previous friendship relations
600  FriendInfo[] finfos = null;
601  FriendInfo f = null;
602  finfos = GetFriendsFromCache(a1);
603  if (finfos != null)
604  {
605  f = GetFriend(finfos, a2);
606  if (f != null)
607  {
608  FriendsService.Delete(a1, f.Friend);
609  // and also the converse
610  FriendsService.Delete(f.Friend, a1.ToString());
611  }
612  }
613 
614  finfos = GetFriendsFromCache(a2);
615  if (finfos != null)
616  {
617  f = GetFriend(finfos, a1);
618  if (f != null)
619  {
620  FriendsService.Delete(a2, f.Friend);
621  // and also the converse
622  FriendsService.Delete(f.Friend, a2.ToString());
623  }
624  }
625  }
626 
627  protected override bool DeleteFriendship(UUID agentID, UUID exfriendID)
628  {
629  Boolean agentIsLocal = true;
630  Boolean friendIsLocal = true;
631  if (UserManagementModule != null)
632  {
633  agentIsLocal = UserManagementModule.IsLocalGridUser(agentID);
634  friendIsLocal = UserManagementModule.IsLocalGridUser(exfriendID);
635  }
636 
637  // Are they both local users?
638  if (agentIsLocal && friendIsLocal)
639  {
640  // local grid users
641  return base.DeleteFriendship(agentID, exfriendID);
642  }
643 
644  // ok, at least one of them is foreigner, let's get their data
645  string agentUUI = string.Empty;
646  string friendUUI = string.Empty;
647 
648  if (agentIsLocal) // agent is local, 'friend' is foreigner
649  {
650  // We need to look for its information in the friends list itself
651  FriendInfo[] finfos = GetFriendsFromCache(agentID);
652  FriendInfo finfo = GetFriend(finfos, exfriendID);
653  if (finfo != null)
654  {
655  friendUUI = finfo.Friend;
656 
657  // delete in the local friends service the reference to the foreign friend
658  FriendsService.Delete(agentID, friendUUI);
659  // and also the converse
660  FriendsService.Delete(friendUUI, agentID.ToString());
661 
662  // notify the exfriend's service
663  Util.FireAndForget(
664  delegate { Delete(exfriendID, agentID, friendUUI); }, null, "HGFriendsModule.DeleteFriendshipForeignFriend");
665 
666  m_log.DebugFormat("[HGFRIENDS MODULE]: {0} terminated {1}", agentID, friendUUI);
667  return true;
668  }
669  }
670  else if (friendIsLocal) // agent is foreigner, 'friend' is local
671  {
672  agentUUI = GetUUI(exfriendID, agentID);
673 
674  if (agentUUI != string.Empty)
675  {
676  // delete in the local friends service the reference to the foreign agent
677  FriendsService.Delete(exfriendID, agentUUI);
678  // and also the converse
679  FriendsService.Delete(agentUUI, exfriendID.ToString());
680 
681  // notify the agent's service?
682  Util.FireAndForget(
683  delegate { Delete(agentID, exfriendID, agentUUI); }, null, "HGFriendsModule.DeleteFriendshipLocalFriend");
684 
685  m_log.DebugFormat("[HGFRIENDS MODULE]: {0} terminated {1}", agentUUI, exfriendID);
686  return true;
687  }
688  }
689  //else They're both foreigners! Can't handle this
690 
691  return false;
692  }
693 
694  private string GetUUI(UUID localUser, UUID foreignUser)
695  {
696  // Let's see if the user is here by any chance
697  FriendInfo[] finfos = GetFriendsFromCache(localUser);
698  if (finfos != EMPTY_FRIENDS) // friend is here, cool
699  {
700  FriendInfo finfo = GetFriend(finfos, foreignUser);
701  if (finfo != null)
702  {
703  return finfo.Friend;
704  }
705  }
706  else // user is not currently on this sim, need to get from the service
707  {
708  finfos = FriendsService.GetFriends(localUser);
709  foreach (FriendInfo finfo in finfos)
710  {
711  if (finfo.Friend.StartsWith(foreignUser.ToString())) // found it!
712  {
713  return finfo.Friend;
714  }
715  }
716  }
717  return string.Empty;
718  }
719 
720  private void Delete(UUID foreignUser, UUID localUser, string uui)
721  {
722  UUID id;
723  string url = string.Empty, secret = string.Empty, tmp = string.Empty;
724  if (Util.ParseUniversalUserIdentifier(uui, out id, out url, out tmp, out tmp, out secret))
725  {
726  m_log.DebugFormat("[HGFRIENDS MODULE]: Deleting friendship from {0}", url);
728  friendConn.DeleteFriendship(foreignUser, localUser, secret);
729  }
730  }
731 
732  protected override bool ForwardFriendshipOffer(UUID agentID, UUID friendID, GridInstantMessage im)
733  {
734  if (base.ForwardFriendshipOffer(agentID, friendID, im))
735  return true;
736 
737  // OK, that didn't work, so let's try to find this user somewhere
738  if (!m_uMan.IsLocalGridUser(friendID))
739  {
740  string friendsURL = m_uMan.GetUserServerURL(friendID, "FriendsServerURI");
741  if (friendsURL != string.Empty)
742  {
743  m_log.DebugFormat("[HGFRIENDS MODULE]: Forwading friendship from {0} to {1} @ {2}", agentID, friendID, friendsURL);
744  GridRegion region = new GridRegion();
745  region.ServerURI = friendsURL;
746 
747  string name = im.fromAgentName;
748  if (m_uMan.IsLocalGridUser(agentID))
749  {
750  IClientAPI agentClient = LocateClientObject(agentID);
751  AgentCircuitData agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode);
752  string agentHomeService = string.Empty;
753  try
754  {
755  agentHomeService = agentClientCircuit.ServiceURLs["HomeURI"].ToString();
756  string lastname = "@" + new Uri(agentHomeService).Authority;
757  string firstname = im.fromAgentName.Replace(" ", ".");
758  name = firstname + lastname;
759  }
760  catch (KeyNotFoundException)
761  {
762  m_log.DebugFormat("[HGFRIENDS MODULE]: Key HomeURI not found for user {0}", agentID);
763  return false;
764  }
765  catch (NullReferenceException)
766  {
767  m_log.DebugFormat("[HGFRIENDS MODULE]: Null HomeUri for local user {0}", agentID);
768  return false;
769  }
770  catch (UriFormatException)
771  {
772  m_log.DebugFormat("[HGFRIENDS MODULE]: Malformed HomeUri {0} for local user {1}", agentHomeService, agentID);
773  return false;
774  }
775  }
776 
777  m_HGFriendsConnector.FriendshipOffered(region, agentID, friendID, im.message, name);
778 
779  return true;
780  }
781  }
782 
783  return false;
784  }
785 
786  public override bool LocalFriendshipOffered(UUID toID, GridInstantMessage im)
787  {
788  if (base.LocalFriendshipOffered(toID, im))
789  {
790  if (im.fromAgentName.Contains("@"))
791  {
792  string[] parts = im.fromAgentName.Split(new char[] { '@' });
793  if (parts.Length == 2)
794  {
795  string[] fl = parts[0].Trim().Split(new char[] { '.' });
796  if (fl.Length == 2)
797  m_uMan.AddUser(new UUID(im.fromAgentID), fl[0], fl[1], "http://" + parts[1]);
798  else
799  m_uMan.AddUser(new UUID(im.fromAgentID), fl[0], "", "http://" + parts[1]);
800  }
801  }
802  return true;
803  }
804  return false;
805  }
806  }
807 }
string ServiceSessionID
Hypergrid service token; generated by the user domain, consumed by the receiving grid. There is one such unique token for each grid visited.
override void StoreFriendships(UUID agentID, UUID friendID)
override void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
override bool ForwardFriendshipOffer(UUID agentID, UUID friendID, GridInstantMessage im)
override void OnInstantMessage(IClientAPI client, GridInstantMessage im)
OpenSim.Services.Interfaces.FriendInfo FriendInfo
override void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
OpenSim.Services.Interfaces.GridRegion GridRegion
override bool StoreRights(UUID agentID, UUID friendID, int rights)
UUID SessionID
Non secure Session ID
bool StatusNotify(UUID friendID, UUID userID, bool online)
Notify the user that the friend's status changed
override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
override bool CacheFriends(IClientAPI client)
Cache the friends list or increment the refcount for the existing friends list.
override void OnApproveFriendRequest(IClientAPI client, UUID friendID, List< UUID > callingCardFolders)
override FriendInfo[] GetFriendsFromService(IClientAPI client)
override void GetOnlineFriends(UUID userID, List< string > friendList, List< UUID > online)
Circuit data for an agent. Connection information shared between regions that accept UDP connections ...
override bool SendFriendsOnlineIfNeeded(IClientAPI client)
override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
override bool DeleteFriendship(UUID agentID, UUID exfriendID)
OpenSim.Services.Interfaces.PresenceInfo PresenceInfo
override void StatusNotify(List< FriendInfo > friendList, UUID userID, bool online)
int TheirFlags
The permissions that the friend has granted to this user.
uint teleportFlags
How this agent got here
This maintains the relationship between a UUID and a user name.
override void StoreBackwards(UUID friendID, UUID agentID)
override bool LocalFriendshipOffered(UUID toID, GridInstantMessage im)