aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs353
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs599
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs342
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs14
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs38
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs16
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs41
-rw-r--r--OpenSim/Region/Framework/Interfaces/IFriendsModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUserManagement.cs2
10 files changed, 1272 insertions, 139 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 5baf078..f82716d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -49,6 +49,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
49{ 49{
50 public class FriendsModule : ISharedRegionModule, IFriendsModule 50 public class FriendsModule : ISharedRegionModule, IFriendsModule
51 { 51 {
52 protected bool m_Enabled = false;
53
52 protected class UserFriendData 54 protected class UserFriendData
53 { 55 {
54 public UUID PrincipalID; 56 public UUID PrincipalID;
@@ -67,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
67 } 69 }
68 } 70 }
69 71
70 private static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0]; 72 protected static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0];
71 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 73 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
72 74
73 protected List<Scene> m_Scenes = new List<Scene>(); 75 protected List<Scene> m_Scenes = new List<Scene>();
@@ -130,8 +132,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
130 } 132 }
131 } 133 }
132 134
135 #region ISharedRegionModule
133 public void Initialise(IConfigSource config) 136 public void Initialise(IConfigSource config)
134 { 137 {
138 IConfig moduleConfig = config.Configs["Modules"];
139 if (moduleConfig != null)
140 {
141 string name = moduleConfig.GetString("FriendsModule", "FriendsModule");
142 if (name == Name)
143 {
144 InitModule(config);
145
146 m_Enabled = true;
147 m_log.InfoFormat("[FRIENDS MODULE]: {0} enabled.", Name);
148 }
149 }
150 }
151
152 protected void InitModule(IConfigSource config)
153 {
135 IConfig friendsConfig = config.Configs["Friends"]; 154 IConfig friendsConfig = config.Configs["Friends"];
136 if (friendsConfig != null) 155 if (friendsConfig != null)
137 { 156 {
@@ -153,7 +172,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
153 m_log.Error("[FRIENDS]: No Connector defined in section Friends, or failed to load, cannot continue"); 172 m_log.Error("[FRIENDS]: No Connector defined in section Friends, or failed to load, cannot continue");
154 throw new Exception("Connector load error"); 173 throw new Exception("Connector load error");
155 } 174 }
156
157 } 175 }
158 176
159 public void PostInitialise() 177 public void PostInitialise()
@@ -164,8 +182,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
164 { 182 {
165 } 183 }
166 184
167 public void AddRegion(Scene scene) 185 public virtual void AddRegion(Scene scene)
168 { 186 {
187 if (!m_Enabled)
188 return;
189 m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name);
190
169 m_Scenes.Add(scene); 191 m_Scenes.Add(scene);
170 scene.RegisterModuleInterface<IFriendsModule>(this); 192 scene.RegisterModuleInterface<IFriendsModule>(this);
171 193
@@ -181,10 +203,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
181 203
182 public void RemoveRegion(Scene scene) 204 public void RemoveRegion(Scene scene)
183 { 205 {
206 if (!m_Enabled)
207 return;
208
184 m_Scenes.Remove(scene); 209 m_Scenes.Remove(scene);
185 } 210 }
186 211
187 public string Name 212 public virtual string Name
188 { 213 {
189 get { return "FriendsModule"; } 214 get { return "FriendsModule"; }
190 } 215 }
@@ -194,13 +219,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
194 get { return null; } 219 get { return null; }
195 } 220 }
196 221
197 public uint GetFriendPerms(UUID principalID, UUID friendID) 222 #endregion
223
224 public virtual uint GetFriendPerms(UUID principalID, UUID friendID)
198 { 225 {
199 FriendInfo[] friends = GetFriends(principalID); 226 FriendInfo[] friends = GetFriends(principalID);
200 foreach (FriendInfo fi in friends) 227 FriendInfo finfo = GetFriend(friends, friendID);
228 if (finfo != null)
201 { 229 {
202 if (fi.Friend == friendID.ToString()) 230 return (uint)finfo.TheirFlags;
203 return (uint)fi.TheirFlags;
204 } 231 }
205 232
206 return 0; 233 return 0;
@@ -214,30 +241,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
214 client.OnTerminateFriendship += OnTerminateFriendship; 241 client.OnTerminateFriendship += OnTerminateFriendship;
215 client.OnGrantUserRights += OnGrantUserRights; 242 client.OnGrantUserRights += OnGrantUserRights;
216 243
217 // Asynchronously fetch the friends list or increment the refcount for the existing 244 Util.FireAndForget(delegate { FetchFriendslist(client); });
218 // friends list 245 }
219 Util.FireAndForget( 246
220 delegate(object o) 247 /// Fetch the friends list or increment the refcount for the existing
248 /// friends list
249 /// Returns true if the list was fetched, false if it wasn't
250 protected virtual bool FetchFriendslist(IClientAPI client)
251 {
252 UUID agentID = client.AgentId;
253 lock (m_Friends)
254 {
255 UserFriendData friendsData;
256 if (m_Friends.TryGetValue(agentID, out friendsData))
221 { 257 {
222 lock (m_Friends) 258 friendsData.Refcount++;
223 { 259 return false;
224 UserFriendData friendsData; 260 }
225 if (m_Friends.TryGetValue(client.AgentId, out friendsData)) 261 else
226 { 262 {
227 friendsData.Refcount++; 263 friendsData = new UserFriendData();
228 } 264 friendsData.PrincipalID = agentID;
229 else 265 friendsData.Friends = GetFriendsFromService(client);
230 { 266 friendsData.Refcount = 1;
231 friendsData = new UserFriendData();
232 friendsData.PrincipalID = client.AgentId;
233 friendsData.Friends = FriendsService.GetFriends(client.AgentId);
234 friendsData.Refcount = 1;
235 267
236 m_Friends[client.AgentId] = friendsData; 268 m_Friends[agentID] = friendsData;
237 } 269 return true;
238 }
239 } 270 }
240 ); 271 }
241 } 272 }
242 273
243 private void OnClientClosed(UUID agentID, Scene scene) 274 private void OnClientClosed(UUID agentID, Scene scene)
@@ -263,14 +294,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
263 294
264 private void OnMakeRootAgent(ScenePresence sp) 295 private void OnMakeRootAgent(ScenePresence sp)
265 { 296 {
266 UUID agentID = sp.ControllingClient.AgentId; 297 RefetchFriends(sp.ControllingClient);
267 UpdateFriendsCache(agentID);
268 } 298 }
269 299
270 private void OnClientLogin(IClientAPI client) 300 private void OnClientLogin(IClientAPI client)
271 { 301 {
272 UUID agentID = client.AgentId; 302 UUID agentID = client.AgentId;
273 303
304 //m_log.DebugFormat("[XXX]: OnClientLogin!");
274 // Inform the friends that this user is online 305 // Inform the friends that this user is online
275 StatusChange(agentID, true); 306 StatusChange(agentID, true);
276 307
@@ -279,7 +310,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
279 m_NeedsListOfFriends.Add(agentID); 310 m_NeedsListOfFriends.Add(agentID);
280 } 311 }
281 312
282 public void SendFriendsOnlineIfNeeded(IClientAPI client) 313 public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client)
283 { 314 {
284 UUID agentID = client.AgentId; 315 UUID agentID = client.AgentId;
285 316
@@ -287,7 +318,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
287 lock (m_NeedsListOfFriends) 318 lock (m_NeedsListOfFriends)
288 { 319 {
289 if (!m_NeedsListOfFriends.Remove(agentID)) 320 if (!m_NeedsListOfFriends.Remove(agentID))
290 return; 321 return false;
291 } 322 }
292 323
293 // Send the friends online 324 // Send the friends online
@@ -313,10 +344,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
313 foreach (string fid in outstanding) 344 foreach (string fid in outstanding)
314 { 345 {
315 UUID fromAgentID; 346 UUID fromAgentID;
316 if (!UUID.TryParse(fid, out fromAgentID)) 347 string firstname = "Unknown", lastname = "User";
348 if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname))
349 {
350 m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid);
317 continue; 351 continue;
318 352 }
319 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, fromAgentID);
320 353
321 PresenceInfo presence = null; 354 PresenceInfo presence = null;
322 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid }); 355 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid });
@@ -326,13 +359,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
326 im.offline = 0; 359 im.offline = 0;
327 360
328 im.fromAgentID = fromAgentID.Guid; 361 im.fromAgentID = fromAgentID.Guid;
329 im.fromAgentName = account.FirstName + " " + account.LastName; 362 im.fromAgentName = firstname + " " + lastname;
330 im.offline = (byte)((presence == null) ? 1 : 0); 363 im.offline = (byte)((presence == null) ? 1 : 0);
331 im.imSessionID = im.fromAgentID; 364 im.imSessionID = im.fromAgentID;
365 im.message = FriendshipMessage(fid);
332 366
333 // Finally 367 // Finally
334 LocalFriendshipOffered(agentID, im); 368 LocalFriendshipOffered(agentID, im);
335 } 369 }
370
371 return true;
372 }
373
374 protected virtual string FriendshipMessage(string friendID)
375 {
376 return "Will you be my friend?";
377 }
378
379 protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
380 {
381 first = "Unknown"; last = "User";
382 if (!UUID.TryParse(fid, out agentID))
383 return false;
384
385 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(scopeID, agentID);
386 if (account != null)
387 {
388 first = account.FirstName;
389 last = account.LastName;
390 }
391
392 return true;
336 } 393 }
337 394
338 List<UUID> GetOnlineFriends(UUID userID) 395 List<UUID> GetOnlineFriends(UUID userID)
@@ -348,19 +405,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
348 } 405 }
349 406
350 if (friendList.Count > 0) 407 if (friendList.Count > 0)
351 { 408 GetOnlineFriends(userID, friendList, online);
352 PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
353 foreach (PresenceInfo pi in presence)
354 {
355 UUID presenceID;
356 if (UUID.TryParse(pi.UserID, out presenceID))
357 online.Add(presenceID);
358 }
359 }
360 409
361 return online; 410 return online;
362 } 411 }
363 412
413 protected virtual void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
414 {
415 PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
416 foreach (PresenceInfo pi in presence)
417 {
418 UUID presenceID;
419 if (UUID.TryParse(pi.UserID, out presenceID))
420 online.Add(presenceID);
421 }
422 }
423
364 /// <summary> 424 /// <summary>
365 /// Find the client for a ID 425 /// Find the client for a ID
366 /// </summary> 426 /// </summary>
@@ -415,51 +475,51 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
415 Util.FireAndForget( 475 Util.FireAndForget(
416 delegate 476 delegate
417 { 477 {
418 foreach (FriendInfo fi in friendList) 478 m_log.DebugFormat("[FRIENDS MODULE]: Notifying {0} friends", friendList.Count);
419 { 479 // Notify about this user status
420 //m_log.DebugFormat("[FRIENDS]: Notifying {0}", fi.PrincipalID); 480 StatusNotify(friendList, agentID, online);
421 // Notify about this user status
422 StatusNotify(fi, agentID, online);
423 }
424 } 481 }
425 ); 482 );
426 } 483 }
427 } 484 }
428 485
429 private void StatusNotify(FriendInfo friend, UUID userID, bool online) 486 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
430 { 487 {
431 UUID friendID; 488 foreach (FriendInfo friend in friendList)
432 if (UUID.TryParse(friend.Friend, out friendID))
433 { 489 {
434 // Try local 490 UUID friendID;
435 if (LocalStatusNotification(userID, friendID, online)) 491 if (UUID.TryParse(friend.Friend, out friendID))
436 return;
437
438 // The friend is not here [as root]. Let's forward.
439 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
440 if (friendSessions != null && friendSessions.Length > 0)
441 { 492 {
442 PresenceInfo friendSession = null; 493 // Try local
443 foreach (PresenceInfo pinfo in friendSessions) 494 if (LocalStatusNotification(userID, friendID, online))
444 if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad 495 return;
445 {
446 friendSession = pinfo;
447 break;
448 }
449 496
450 if (friendSession != null) 497 // The friend is not here [as root]. Let's forward.
498 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
499 if (friendSessions != null && friendSessions.Length > 0)
451 { 500 {
452 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); 501 PresenceInfo friendSession = null;
453 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); 502 foreach (PresenceInfo pinfo in friendSessions)
454 m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); 503 if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad
504 {
505 friendSession = pinfo;
506 break;
507 }
508
509 if (friendSession != null)
510 {
511 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
512 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
513 m_FriendsSimConnector.StatusNotify(region, userID, friendID, online);
514 }
455 } 515 }
456 }
457 516
458 // Friend is not online. Ignore. 517 // Friend is not online. Ignore.
459 } 518 }
460 else 519 else
461 { 520 {
462 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); 521 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend);
522 }
463 } 523 }
464 } 524 }
465 525
@@ -475,7 +535,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
475 535
476 // This user wants to be friends with the other user. 536 // This user wants to be friends with the other user.
477 // Let's add the relation backwards, in case the other is not online 537 // Let's add the relation backwards, in case the other is not online
478 FriendsService.StoreFriend(friendID, principalID.ToString(), 0); 538 StoreBackwards(friendID, principalID);
479 539
480 // Now let's ask the other user to be friends with this user 540 // Now let's ask the other user to be friends with this user
481 ForwardFriendshipOffer(principalID, friendID, im); 541 ForwardFriendshipOffer(principalID, friendID, im);
@@ -487,11 +547,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
487 // !!!!!!!! This is a hack so that we don't have to keep state (transactionID/imSessionID) 547 // !!!!!!!! This is a hack so that we don't have to keep state (transactionID/imSessionID)
488 // We stick this agent's ID as imSession, so that it's directly available on the receiving end 548 // We stick this agent's ID as imSession, so that it's directly available on the receiving end
489 im.imSessionID = im.fromAgentID; 549 im.imSessionID = im.fromAgentID;
550 im.fromAgentName = GetFriendshipRequesterName(agentID);
490 551
491 // Try the local sim 552 // Try the local sim
492 UserAccount account = UserAccountService.GetUserAccount(UUID.Zero, agentID);
493 im.fromAgentName = (account == null) ? "Unknown" : account.FirstName + " " + account.LastName;
494
495 if (LocalFriendshipOffered(friendID, im)) 553 if (LocalFriendshipOffered(friendID, im))
496 return; 554 return;
497 555
@@ -509,15 +567,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
509 // If the prospective friend is not online, he'll get the message upon login. 567 // If the prospective friend is not online, he'll get the message upon login.
510 } 568 }
511 569
570 protected virtual string GetFriendshipRequesterName(UUID agentID)
571 {
572 UserAccount account = UserAccountService.GetUserAccount(UUID.Zero, agentID);
573 return (account == null) ? "Unknown" : account.FirstName + " " + account.LastName;
574 }
575
512 private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders) 576 private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
513 { 577 {
514 m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID); 578 m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID);
515 579
516 FriendsService.StoreFriend(agentID, friendID.ToString(), 1); 580 StoreFriendships(agentID, friendID);
517 FriendsService.StoreFriend(friendID, agentID.ToString(), 1);
518 581
519 // Update the local cache 582 // Update the local cache
520 UpdateFriendsCache(agentID); 583 RefetchFriends(client);
521 584
522 // 585 //
523 // Notify the friend 586 // Notify the friend
@@ -548,8 +611,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
548 { 611 {
549 m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", agentID, friendID); 612 m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", agentID, friendID);
550 613
551 FriendsService.Delete(agentID, friendID.ToString()); 614 DeleteFriendship(agentID, friendID);
552 FriendsService.Delete(friendID, agentID.ToString());
553 615
554 // 616 //
555 // Notify the friend 617 // Notify the friend
@@ -576,11 +638,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
576 638
577 private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID) 639 private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID)
578 { 640 {
579 FriendsService.Delete(agentID, exfriendID.ToString()); 641 if (!DeleteFriendship(agentID, exfriendID))
580 FriendsService.Delete(exfriendID, agentID.ToString()); 642 client.SendAlertMessage("Unable to terminate friendship on this sim.");
581 643
582 // Update local cache 644 // Update local cache
583 UpdateFriendsCache(agentID); 645 RefetchFriends(client);
584 646
585 client.SendTerminateFriend(exfriendID); 647 client.SendTerminateFriend(exfriendID);
586 648
@@ -606,23 +668,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
606 668
607 private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) 669 private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights)
608 { 670 {
671 m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target);
672
609 FriendInfo[] friends = GetFriends(remoteClient.AgentId); 673 FriendInfo[] friends = GetFriends(remoteClient.AgentId);
610 if (friends.Length == 0) 674 if (friends.Length == 0)
675 {
611 return; 676 return;
677 }
612 678
613 m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target);
614 // Let's find the friend in this user's friend list 679 // Let's find the friend in this user's friend list
615 FriendInfo friend = null; 680 FriendInfo friend = GetFriend(friends, target);
616 foreach (FriendInfo fi in friends)
617 {
618 if (fi.Friend == target.ToString())
619 friend = fi;
620 }
621 681
622 if (friend != null) // Found it 682 if (friend != null) // Found it
623 { 683 {
624 // Store it on the DB 684 // Store it on the DB
625 FriendsService.StoreFriend(requester, target.ToString(), rights); 685 if (!StoreRights(requester, target, rights))
686 {
687 remoteClient.SendAlertMessage("Unable to grant rights.");
688 return;
689 }
626 690
627 // Store it in the local cache 691 // Store it in the local cache
628 int myFlags = friend.MyFlags; 692 int myFlags = friend.MyFlags;
@@ -652,6 +716,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
652 } 716 }
653 } 717 }
654 } 718 }
719 else
720 m_log.DebugFormat("[FRIENDS MODULE]: friend {0} not found for {1}", target, requester);
721 }
722
723 protected virtual FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
724 {
725 foreach (FriendInfo fi in friends)
726 {
727 if (fi.Friend == friendID.ToString())
728 return fi;
729 }
730 return null;
655 } 731 }
656 732
657 #region Local 733 #region Local
@@ -680,7 +756,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
680 friendClient.SendInstantMessage(im); 756 friendClient.SendInstantMessage(im);
681 757
682 // Update the local cache 758 // Update the local cache
683 UpdateFriendsCache(friendID); 759 RefetchFriends(friendClient);
684 760
685 // we're done 761 // we're done
686 return true; 762 return true;
@@ -713,7 +789,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
713 // the friend in this sim as root agent 789 // the friend in this sim as root agent
714 friendClient.SendTerminateFriend(exfriendID); 790 friendClient.SendTerminateFriend(exfriendID);
715 // update local cache 791 // update local cache
716 UpdateFriendsCache(exfriendID); 792 RefetchFriends(friendClient);
717 // we're done 793 // we're done
718 return true; 794 return true;
719 } 795 }
@@ -743,15 +819,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
743 } 819 }
744 820
745 // Update local cache 821 // Update local cache
746 lock (m_Friends) 822 UpdateLocalCache(userID, friendID, rights);
747 {
748 FriendInfo[] friends = GetFriends(friendID);
749 foreach (FriendInfo finfo in friends)
750 {
751 if (finfo.Friend == userID.ToString())
752 finfo.TheirFlags = rights;
753 }
754 }
755 823
756 return true; 824 return true;
757 } 825 }
@@ -780,7 +848,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
780 848
781 #endregion 849 #endregion
782 850
783 private FriendInfo[] GetFriends(UUID agentID) 851 #region Get / Set friends in several flavours
852 /// <summary>
853 /// Get friends from local cache only
854 /// </summary>
855 /// <param name="agentID"></param>
856 /// <returns></returns>
857 protected FriendInfo[] GetFriends(UUID agentID)
784 { 858 {
785 UserFriendData friendsData; 859 UserFriendData friendsData;
786 860
@@ -793,14 +867,63 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
793 return EMPTY_FRIENDS; 867 return EMPTY_FRIENDS;
794 } 868 }
795 869
796 private void UpdateFriendsCache(UUID agentID) 870 /// <summary>
871 /// Update loca cache only
872 /// </summary>
873 /// <param name="userID"></param>
874 /// <param name="friendID"></param>
875 /// <param name="rights"></param>
876 protected void UpdateLocalCache(UUID userID, UUID friendID, int rights)
877 {
878 // Update local cache
879 lock (m_Friends)
880 {
881 FriendInfo[] friends = GetFriends(friendID);
882 FriendInfo finfo = GetFriend(friends, userID);
883 finfo.TheirFlags = rights;
884 }
885 }
886
887 protected virtual FriendInfo[] GetFriendsFromService(IClientAPI client)
888 {
889 return FriendsService.GetFriends(client.AgentId);
890 }
891
892 private void RefetchFriends(IClientAPI client)
797 { 893 {
894 UUID agentID = client.AgentId;
798 lock (m_Friends) 895 lock (m_Friends)
799 { 896 {
800 UserFriendData friendsData; 897 UserFriendData friendsData;
801 if (m_Friends.TryGetValue(agentID, out friendsData)) 898 if (m_Friends.TryGetValue(agentID, out friendsData))
802 friendsData.Friends = FriendsService.GetFriends(agentID); 899 friendsData.Friends = GetFriendsFromService(client);
803 } 900 }
804 } 901 }
902
903 protected virtual bool StoreRights(UUID agentID, UUID friendID, int rights)
904 {
905 FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), rights);
906 return true;
907 }
908
909 protected virtual void StoreBackwards(UUID friendID, UUID agentID)
910 {
911 FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0);
912 }
913
914 protected virtual void StoreFriendships(UUID agentID, UUID friendID)
915 {
916 FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), 1);
917 FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 1);
918 }
919
920 protected virtual bool DeleteFriendship(UUID agentID, UUID exfriendID)
921 {
922 FriendsService.Delete(agentID, exfriendID.ToString());
923 FriendsService.Delete(exfriendID, agentID.ToString());
924 return true;
925 }
926
927 #endregion
805 } 928 }
806} 929}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
new file mode 100644
index 0000000..b0a7567
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -0,0 +1,599 @@
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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using log4net;
33using Nini.Config;
34using Nwc.XmlRpc;
35using Mono.Addins;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using OpenSim.Services.Connectors.Hypergrid;
42using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
43using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
44using GridRegion = OpenSim.Services.Interfaces.GridRegion;
45
46namespace OpenSim.Region.CoreModules.Avatar.Friends
47{
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
49 public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule, IFriendsSimConnector
50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 #region ISharedRegionModule
54 public override string Name
55 {
56 get { return "HGFriendsModule"; }
57 }
58
59 public override void AddRegion(Scene scene)
60 {
61 if (!m_Enabled)
62 return;
63
64 base.AddRegion(scene);
65 scene.RegisterModuleInterface<IFriendsSimConnector>(this);
66 }
67
68 #endregion
69
70 #region IFriendsSimConnector
71
72 /// <summary>
73 /// Notify the user that the friend's status changed
74 /// </summary>
75 /// <param name="userID">user to be notified</param>
76 /// <param name="friendID">friend whose status changed</param>
77 /// <param name="online">status</param>
78 /// <returns></returns>
79 public bool StatusNotify(UUID userID, UUID friendID, bool online)
80 {
81 return LocalStatusNotification(friendID, userID, online);
82 }
83
84 #endregion
85
86 protected override bool FetchFriendslist(IClientAPI client)
87 {
88 if (base.FetchFriendslist(client))
89 {
90 UUID agentID = client.AgentId;
91 // We need to preload the user management cache with the names
92 // of foreign friends, just like we do with SOPs' creators
93 foreach (FriendInfo finfo in m_Friends[agentID].Friends)
94 {
95 if (finfo.TheirFlags != -1)
96 {
97 UUID id;
98 if (!UUID.TryParse(finfo.Friend, out id))
99 {
100 string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
101 if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last, out tmp))
102 {
103 IUserManagement uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
104 uMan.AddUser(id, url + ";" + first + " " + last);
105 }
106 }
107 }
108 }
109 return true;
110 }
111 return false;
112 }
113
114 public override bool SendFriendsOnlineIfNeeded(IClientAPI client)
115 {
116 if (base.SendFriendsOnlineIfNeeded(client))
117 {
118 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, client.AgentId);
119 if (account == null) // foreign
120 {
121 FriendInfo[] friends = GetFriends(client.AgentId);
122 foreach (FriendInfo f in friends)
123 {
124 client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags);
125 }
126 }
127 }
128 return false;
129 }
130
131 protected override void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
132 {
133 // Let's single out the UUIs
134 List<string> localFriends = new List<string>();
135 List<string> foreignFriends = new List<string>();
136 string tmp = string.Empty;
137
138 foreach (string s in friendList)
139 {
140 UUID id;
141 if (UUID.TryParse(s, out id))
142 localFriends.Add(s);
143 else if (Util.ParseUniversalUserIdentifier(s, out id, out tmp, out tmp, out tmp, out tmp))
144 {
145 foreignFriends.Add(s);
146 // add it here too, who knows maybe the foreign friends happens to be on this grid
147 localFriends.Add(id.ToString());
148 }
149 }
150
151 // OK, see who's present on this grid
152 List<string> toBeRemoved = new List<string>();
153 PresenceInfo[] presence = PresenceService.GetAgents(localFriends.ToArray());
154 foreach (PresenceInfo pi in presence)
155 {
156 UUID presenceID;
157 if (UUID.TryParse(pi.UserID, out presenceID))
158 {
159 online.Add(presenceID);
160 foreach (string s in foreignFriends)
161 if (s.StartsWith(pi.UserID))
162 toBeRemoved.Add(s);
163 }
164 }
165
166 foreach (string s in toBeRemoved)
167 foreignFriends.Remove(s);
168
169 // OK, let's send this up the stack, and leave a closure here
170 // collecting online friends in other grids
171 Util.FireAndForget(delegate { CollectOnlineFriendsElsewhere(userID, foreignFriends); });
172
173 }
174
175 private void CollectOnlineFriendsElsewhere(UUID userID, List<string> foreignFriends)
176 {
177 // let's divide the friends on a per-domain basis
178 Dictionary<string, List<string>> friendsPerDomain = new Dictionary<string, List<string>>();
179 foreach (string friend in foreignFriends)
180 {
181 UUID friendID;
182 if (!UUID.TryParse(friend, out friendID))
183 {
184 // it's a foreign friend
185 string url = string.Empty, tmp = string.Empty;
186 if (Util.ParseUniversalUserIdentifier(friend, out friendID, out url, out tmp, out tmp, out tmp))
187 {
188 if (!friendsPerDomain.ContainsKey(url))
189 friendsPerDomain[url] = new List<string>();
190 friendsPerDomain[url].Add(friend);
191 }
192 }
193 }
194
195 // Now, call those worlds
196
197 foreach (KeyValuePair<string, List<string>> kvp in friendsPerDomain)
198 {
199 List<string> ids = new List<string>();
200 foreach (string f in kvp.Value)
201 ids.Add(f);
202 UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key);
203 List<UUID> online = uConn.GetOnlineFriends(userID, ids);
204 // Finally send the notifications to the user
205 // this whole process may take a while, so let's check at every
206 // iteration that the user is still here
207 IClientAPI client = LocateClientObject(userID);
208 if (client != null)
209 client.SendAgentOnline(online.ToArray());
210 else
211 break;
212 }
213
214 }
215
216 protected override void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
217 {
218 // First, let's divide the friends on a per-domain basis
219 Dictionary<string, List<FriendInfo>> friendsPerDomain = new Dictionary<string, List<FriendInfo>>();
220 foreach (FriendInfo friend in friendList)
221 {
222 UUID friendID;
223 if (UUID.TryParse(friend.Friend, out friendID))
224 {
225 if (!friendsPerDomain.ContainsKey("local"))
226 friendsPerDomain["local"] = new List<FriendInfo>();
227 friendsPerDomain["local"].Add(friend);
228 }
229 else
230 {
231 // it's a foreign friend
232 string url = string.Empty, tmp = string.Empty;
233 if (Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out url, out tmp, out tmp, out tmp))
234 {
235 // Let's try our luck in the local sim. Who knows, maybe it's here
236 if (LocalStatusNotification(userID, friendID, online))
237 continue;
238
239 if (!friendsPerDomain.ContainsKey(url))
240 friendsPerDomain[url] = new List<FriendInfo>();
241 friendsPerDomain[url].Add(friend);
242 }
243 }
244 }
245
246 // For the local friends, just call the base method
247 // Let's do this first of all
248 if (friendsPerDomain.ContainsKey("local"))
249 base.StatusNotify(friendsPerDomain["local"], userID, online);
250
251 foreach (KeyValuePair<string, List<FriendInfo>> kvp in friendsPerDomain)
252 {
253 if (kvp.Key != "local")
254 {
255 // For the others, call the user agent service
256 List<string> ids = new List<string>();
257 foreach (FriendInfo f in kvp.Value)
258 ids.Add(f.Friend);
259 UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key);
260 uConn.StatusNotification(ids, userID, online);
261 }
262 }
263 }
264
265 protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
266 {
267 first = "Unknown"; last = "User";
268 if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last))
269 return true;
270
271 // fid is not a UUID...
272 string url = string.Empty, tmp = string.Empty;
273 if (Util.ParseUniversalUserIdentifier(fid, out agentID, out url, out first, out last, out tmp))
274 {
275 IUserManagement userMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
276 userMan.AddUser(agentID, url + ";" + first + " " + last);
277
278 try // our best
279 {
280 string[] parts = userMan.GetUserName(agentID).Split();
281 first = parts[0];
282 last = parts[1];
283 }
284 catch { }
285 return true;
286 }
287 return false;
288 }
289
290 protected override string GetFriendshipRequesterName(UUID agentID)
291 {
292 // For the time being we assume that HG friendship requests can only happen
293 // when avies are on the same region.
294 IClientAPI client = LocateClientObject(agentID);
295 if (client != null)
296 return client.FirstName + " " + client.LastName;
297 else
298 return base.GetFriendshipRequesterName(agentID);
299 }
300
301 protected override string FriendshipMessage(string friendID)
302 {
303 UUID id;
304 if (UUID.TryParse(friendID, out id))
305 return base.FriendshipMessage(friendID);
306
307 return "Please confirm this friendship you made while you were away.";
308 }
309
310 protected override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
311 {
312 foreach (FriendInfo fi in friends)
313 {
314 if (fi.Friend.StartsWith(friendID.ToString()))
315 return fi;
316 }
317 return null;
318 }
319
320
321 protected override FriendInfo[] GetFriendsFromService(IClientAPI client)
322 {
323 UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, client.AgentId);
324 if (account1 != null)
325 return base.GetFriendsFromService(client);
326
327 FriendInfo[] finfos = new FriendInfo[0];
328 // Foreigner
329 AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
330 if (agentClientCircuit != null)
331 {
332 string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
333
334 finfos = FriendsService.GetFriends(agentUUI);
335 m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI);
336 }
337 return finfos;
338 }
339
340 protected override bool StoreRights(UUID agentID, UUID friendID, int rights)
341 {
342 UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
343 UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID);
344 // Are they both local users?
345 if (account1 != null && account2 != null)
346 {
347 // local grid users
348 return base.StoreRights(agentID, friendID, rights);
349 }
350
351 if (account1 != null) // agent is local, friend is foreigner
352 {
353 FriendInfo[] finfos = GetFriends(agentID);
354 FriendInfo finfo = GetFriend(finfos, friendID);
355 if (finfo != null)
356 {
357 FriendsService.StoreFriend(agentID.ToString(), finfo.Friend, rights);
358 return true;
359 }
360 }
361
362 if (account2 != null) // agent is foreigner, friend is local
363 {
364 string agentUUI = GetUUI(friendID, agentID);
365 if (agentUUI != string.Empty)
366 {
367 FriendsService.StoreFriend(agentUUI, friendID.ToString(), rights);
368 return true;
369 }
370 }
371
372 return false;
373
374 }
375
376 protected override void StoreBackwards(UUID friendID, UUID agentID)
377 {
378 UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
379 UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID);
380 // Are they both local users?
381 if (account1 != null && account2 != null)
382 {
383 // local grid users
384 m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local");
385 base.StoreBackwards(friendID, agentID);
386 return;
387 }
388
389 // no provision for this temporary friendship state
390 //FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0);
391 }
392
393 protected override void StoreFriendships(UUID agentID, UUID friendID)
394 {
395 UserAccount agentAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
396 UserAccount friendAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID);
397 // Are they both local users?
398 if (agentAccount != null && friendAccount != null)
399 {
400 // local grid users
401 m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local");
402 base.StoreFriendships(agentID, friendID);
403 return;
404 }
405
406 // ok, at least one of them is foreigner, let's get their data
407 IClientAPI agentClient = LocateClientObject(agentID);
408 IClientAPI friendClient = LocateClientObject(friendID);
409 AgentCircuitData agentClientCircuit = null;
410 AgentCircuitData friendClientCircuit = null;
411 string agentUUI = string.Empty;
412 string friendUUI = string.Empty;
413 string agentFriendService = string.Empty;
414 string friendFriendService = string.Empty;
415
416 if (agentClient != null)
417 {
418 agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode);
419 agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
420 agentFriendService = agentClientCircuit.ServiceURLs["FriendsServerURI"].ToString();
421 }
422 if (friendClient != null)
423 {
424 friendClientCircuit = ((Scene)(friendClient.Scene)).AuthenticateHandler.GetAgentCircuitData(friendClient.CircuitCode);
425 friendUUI = Util.ProduceUserUniversalIdentifier(friendClientCircuit);
426 friendFriendService = friendClientCircuit.ServiceURLs["FriendsServerURI"].ToString();
427 }
428
429 m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}",
430 agentUUI, friendUUI, agentFriendService, friendFriendService);
431
432 // Generate a random 8-character hex number that will sign this friendship
433 string secret = UUID.Random().ToString().Substring(0, 8);
434
435 if (agentAccount != null) // agent is local, 'friend' is foreigner
436 {
437 // This may happen when the agent returned home, in which case the friend is not there
438 // We need to look for its information in the friends list itself
439 bool confirming = false;
440 if (friendUUI == string.Empty)
441 {
442 FriendInfo[] finfos = GetFriends(agentID);
443 foreach (FriendInfo finfo in finfos)
444 {
445 if (finfo.TheirFlags == -1)
446 {
447 if (finfo.Friend.StartsWith(friendID.ToString()))
448 {
449 friendUUI = finfo.Friend;
450 confirming = true;
451 }
452 }
453 }
454 }
455
456 // If it's confirming the friendship, we already have the full friendUUI with the secret
457 string theFriendUUID = confirming ? friendUUI : friendUUI + ";" + secret;
458
459 // store in the local friends service a reference to the foreign friend
460 FriendsService.StoreFriend(agentID.ToString(), theFriendUUID, 1);
461 // and also the converse
462 FriendsService.StoreFriend(theFriendUUID, agentID.ToString(), 1);
463
464 if (!confirming && friendClientCircuit != null)
465 {
466 // store in the foreign friends service a reference to the local agent
467 HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID);
468 friendsConn.NewFriendship(friendID, agentUUI + ";" + secret);
469 }
470 }
471 else if (friendAccount != null) // 'friend' is local, agent is foreigner
472 {
473 // store in the local friends service a reference to the foreign agent
474 FriendsService.StoreFriend(friendID.ToString(), agentUUI + ";" + secret, 1);
475 // and also the converse
476 FriendsService.StoreFriend(agentUUI + ";" + secret, friendID.ToString(), 1);
477
478 if (agentClientCircuit != null)
479 {
480 // store in the foreign friends service a reference to the local agent
481 HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID);
482 friendsConn.NewFriendship(agentID, friendUUI + ";" + secret);
483 }
484 }
485 else // They're both foreigners!
486 {
487 HGFriendsServicesConnector friendsConn;
488 if (agentClientCircuit != null)
489 {
490 friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID);
491 friendsConn.NewFriendship(agentID, friendUUI + ";" + secret);
492 }
493 if (friendClientCircuit != null)
494 {
495 friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID);
496 friendsConn.NewFriendship(friendID, agentUUI + ";" + secret);
497 }
498 }
499 // my brain hurts now
500 }
501
502 protected override bool DeleteFriendship(UUID agentID, UUID exfriendID)
503 {
504 UserAccount agentAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
505 UserAccount friendAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, exfriendID);
506 // Are they both local users?
507 if (agentAccount != null && friendAccount != null)
508 {
509 // local grid users
510 return base.DeleteFriendship(agentID, exfriendID);
511 }
512
513 // ok, at least one of them is foreigner, let's get their data
514 string agentUUI = string.Empty;
515 string friendUUI = string.Empty;
516
517 if (agentAccount != null) // agent is local, 'friend' is foreigner
518 {
519 // We need to look for its information in the friends list itself
520 FriendInfo[] finfos = GetFriends(agentID);
521 FriendInfo finfo = GetFriend(finfos, exfriendID);
522 if (finfo != null)
523 {
524 friendUUI = finfo.Friend;
525
526 // delete in the local friends service the reference to the foreign friend
527 FriendsService.Delete(agentID, friendUUI);
528 // and also the converse
529 FriendsService.Delete(friendUUI, agentID.ToString());
530
531 // notify the exfriend's service
532 Util.FireAndForget(delegate { Delete(exfriendID, agentID, friendUUI); });
533
534 m_log.DebugFormat("[HGFRIENDS MODULE]: {0} terminated {1}", agentID, friendUUI);
535 return true;
536 }
537 }
538 else if (friendAccount != null) // agent is foreigner, 'friend' is local
539 {
540 agentUUI = GetUUI(exfriendID, agentID);
541
542 if (agentUUI != string.Empty)
543 {
544 // delete in the local friends service the reference to the foreign agent
545 FriendsService.Delete(exfriendID, agentUUI);
546 // and also the converse
547 FriendsService.Delete(agentUUI, exfriendID.ToString());
548
549 // notify the agent's service?
550 Util.FireAndForget(delegate { Delete(agentID, exfriendID, agentUUI); });
551
552 m_log.DebugFormat("[HGFRIENDS MODULE]: {0} terminated {1}", agentUUI, exfriendID);
553 return true;
554 }
555 }
556 //else They're both foreigners! Can't handle this
557
558 return false;
559 }
560
561 private string GetUUI(UUID localUser, UUID foreignUser)
562 {
563 // Let's see if the user is here by any chance
564 FriendInfo[] finfos = GetFriends(localUser);
565 if (finfos != EMPTY_FRIENDS) // friend is here, cool
566 {
567 FriendInfo finfo = GetFriend(finfos, foreignUser);
568 if (finfo != null)
569 {
570 return finfo.Friend;
571 }
572 }
573 else // user is not currently on this sim, need to get from the service
574 {
575 finfos = FriendsService.GetFriends(localUser);
576 foreach (FriendInfo finfo in finfos)
577 {
578 if (finfo.Friend.StartsWith(foreignUser.ToString())) // found it!
579 {
580 return finfo.Friend;
581 }
582 }
583 }
584 return string.Empty;
585 }
586
587 private void Delete(UUID foreignUser, UUID localUser, string uui)
588 {
589 UUID id;
590 string url = string.Empty, secret = string.Empty, tmp = string.Empty;
591 if (Util.ParseUniversalUserIdentifier(uui, out id, out url, out tmp, out tmp, out secret))
592 {
593 m_log.DebugFormat("[HGFRIENDS MODULE]: Deleting friendship from {0}", url);
594 HGFriendsServicesConnector friendConn = new HGFriendsServicesConnector(url);
595 friendConn.DeleteFriendship(foreignUser, localUser, secret);
596 }
597 }
598 }
599}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
new file mode 100644
index 0000000..ed02119
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
@@ -0,0 +1,342 @@
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 */
27using System;
28using System.Collections;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32using log4net;
33using Nini.Config;
34using Nwc.XmlRpc;
35using Mono.Addins;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using GridRegion = OpenSim.Services.Interfaces.GridRegion;
41using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
42using OpenSim.Services.Interfaces;
43using OpenSim.Services.Connectors.InstantMessage;
44using OpenSim.Services.Connectors.Hypergrid;
45using OpenSim.Server.Handlers.Hypergrid;
46
47namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
48{
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
50 public class HGMessageTransferModule : ISharedRegionModule, IMessageTransferModule, IInstantMessageSimConnector
51 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 protected bool m_Enabled = false;
55 protected List<Scene> m_Scenes = new List<Scene>();
56
57 protected IInstantMessage m_IMService;
58 protected Dictionary<UUID, object> m_UserLocationMap = new Dictionary<UUID, object>();
59
60 public event UndeliveredMessage OnUndeliveredMessage;
61
62 IUserManagement m_uMan;
63 IUserManagement UserManagementModule
64 {
65 get
66 {
67 if (m_uMan == null)
68 m_uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
69 return m_uMan;
70 }
71 }
72
73 public virtual void Initialise(IConfigSource config)
74 {
75 IConfig cnf = config.Configs["Messaging"];
76 if (cnf != null && cnf.GetString(
77 "MessageTransferModule", "MessageTransferModule") != Name)
78 {
79 m_log.Debug("[HG MESSAGE TRANSFER]: Disabled by configuration");
80 return;
81 }
82
83 InstantMessageServerConnector imServer = new InstantMessageServerConnector(config, MainServer.Instance, this);
84 m_IMService = imServer.GetService();
85 m_Enabled = true;
86 }
87
88 public virtual void AddRegion(Scene scene)
89 {
90 if (!m_Enabled)
91 return;
92
93 lock (m_Scenes)
94 {
95 m_log.DebugFormat("[HG MESSAGE TRANSFER]: Message transfer module {0} active", Name);
96 scene.RegisterModuleInterface<IMessageTransferModule>(this);
97 m_Scenes.Add(scene);
98 }
99 }
100
101 public virtual void PostInitialise()
102 {
103 if (!m_Enabled)
104 return;
105
106 }
107
108 public virtual void RegionLoaded(Scene scene)
109 {
110 }
111
112 public virtual void RemoveRegion(Scene scene)
113 {
114 if (!m_Enabled)
115 return;
116
117 lock (m_Scenes)
118 {
119 m_Scenes.Remove(scene);
120 }
121 }
122
123 public virtual void Close()
124 {
125 }
126
127 public virtual string Name
128 {
129 get { return "HGMessageTransferModule"; }
130 }
131
132 public virtual Type ReplaceableInterface
133 {
134 get { return null; }
135 }
136
137 public void SendInstantMessage(GridInstantMessage im, MessageResultNotification result)
138 {
139 UUID toAgentID = new UUID(im.toAgentID);
140
141 // Try root avatar only first
142 foreach (Scene scene in m_Scenes)
143 {
144 if (scene.Entities.ContainsKey(toAgentID) &&
145 scene.Entities[toAgentID] is ScenePresence)
146 {
147// m_log.DebugFormat(
148// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
149// toAgentID.ToString(), scene.RegionInfo.RegionName);
150
151 ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
152 if (!user.IsChildAgent)
153 {
154 // Local message
155// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID);
156 user.ControllingClient.SendInstantMessage(im);
157
158 // Message sent
159 result(true);
160 return;
161 }
162 }
163 }
164
165 // try child avatar second
166 foreach (Scene scene in m_Scenes)
167 {
168// m_log.DebugFormat(
169// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
170
171 if (scene.Entities.ContainsKey(toAgentID) &&
172 scene.Entities[toAgentID] is ScenePresence)
173 {
174 // Local message
175 ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
176
177// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID);
178 user.ControllingClient.SendInstantMessage(im);
179
180 // Message sent
181 result(true);
182 return;
183 }
184 }
185
186// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
187 // Is the user a local user?
188 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, toAgentID);
189 string url = string.Empty;
190 PresenceInfo upd;
191 if (account == null) // foreign user
192 url = UserManagementModule.GetUserServerURL(toAgentID, "IMServerURI");
193
194 Util.FireAndForget(delegate
195 {
196 bool success = m_IMService.OutgoingInstantMessage(im, url);
197 if (!success && account == null)
198 {
199 // One last chance
200 string recipientUUI = TryGetRecipientUUI(new UUID(im.fromAgentID), toAgentID);
201 m_log.DebugFormat("[HG MESSAGE TRANSFER]: Got UUI {0}", recipientUUI);
202 if (recipientUUI != string.Empty)
203 {
204 UUID id; string u = string.Empty, first = string.Empty, last = string.Empty, secret = string.Empty;
205 if (Util.ParseUniversalUserIdentifier(recipientUUI, out id, out u, out first, out last, out secret))
206 {
207 success = m_IMService.OutgoingInstantMessage(im, u);
208 if (success)
209 UserManagementModule.AddUser(toAgentID, u + ";" + first + " " + last);
210 }
211 }
212 }
213 result(success);
214 });
215
216 return;
217 }
218
219 protected bool SendIMToScene(GridInstantMessage gim, UUID toAgentID)
220 {
221 bool successful = false;
222 foreach (Scene scene in m_Scenes)
223 {
224 if (scene.Entities.ContainsKey(toAgentID) &&
225 scene.Entities[toAgentID] is ScenePresence)
226 {
227 ScenePresence user =
228 (ScenePresence)scene.Entities[toAgentID];
229
230 if (!user.IsChildAgent)
231 {
232 scene.EventManager.TriggerIncomingInstantMessage(gim);
233 successful = true;
234 }
235 }
236 }
237 if (!successful)
238 {
239 // If the message can't be delivered to an agent, it
240 // is likely to be a group IM. On a group IM, the
241 // imSessionID = toAgentID = group id. Raise the
242 // unhandled IM event to give the groups module
243 // a chance to pick it up. We raise that in a random
244 // scene, since the groups module is shared.
245 //
246 m_Scenes[0].EventManager.TriggerUnhandledInstantMessage(gim);
247 }
248
249 return successful;
250 }
251
252 protected void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result)
253 {
254 UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage;
255
256 // If this event has handlers, then an IM from an agent will be
257 // considered delivered. This will suppress the error message.
258 //
259 if (handlerUndeliveredMessage != null)
260 {
261 handlerUndeliveredMessage(im);
262 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
263 result(true);
264 else
265 result(false);
266 return;
267 }
268
269 //m_log.DebugFormat("[INSTANT MESSAGE]: Undeliverable");
270 result(false);
271 }
272
273 private string TryGetRecipientUUI(UUID fromAgent, UUID toAgent)
274 {
275 // Let's call back the fromAgent's user agent service
276 // Maybe that service knows about the toAgent
277 IClientAPI client = LocateClientObject(fromAgent);
278 if (client != null)
279 {
280 AgentCircuitData circuit = m_Scenes[0].AuthenticateHandler.GetAgentCircuitData(client.AgentId);
281 if (circuit != null)
282 {
283 if (circuit.ServiceURLs.ContainsKey("HomeURI"))
284 {
285 string uasURL = circuit.ServiceURLs["HomeURI"].ToString();
286 m_log.DebugFormat("[HG MESSAGE TRANSFER]: getting UUI of user {0} from {1}", toAgent, uasURL);
287 UserAgentServiceConnector uasConn = new UserAgentServiceConnector(uasURL);
288 return uasConn.GetUUI(fromAgent, toAgent);
289 }
290 }
291 }
292
293 return string.Empty;
294 }
295
296
297 /// <summary>
298 /// Find the scene for an agent
299 /// </summary>
300 private Scene GetClientScene(UUID agentId)
301 {
302 lock (m_Scenes)
303 {
304 foreach (Scene scene in m_Scenes)
305 {
306 ScenePresence presence = scene.GetScenePresence(agentId);
307 if (presence != null && !presence.IsChildAgent)
308 return scene;
309 }
310 }
311
312 return null;
313 }
314
315 /// <summary>
316 /// Find the client for a ID
317 /// </summary>
318 public IClientAPI LocateClientObject(UUID agentID)
319 {
320 Scene scene = GetClientScene(agentID);
321 if (scene != null)
322 {
323 ScenePresence presence = scene.GetScenePresence(agentID);
324 if (presence != null)
325 return presence.ControllingClient;
326 }
327
328 return null;
329 }
330
331 #region IInstantMessageSimConnector
332 public bool SendInstantMessage(GridInstantMessage im)
333 {
334 //m_log.DebugFormat("[XXX] Hook SendInstantMessage {0}", im.message);
335 UUID agentID = new UUID(im.toAgentID);
336 return SendIMToScene(im, agentID);
337 }
338 #endregion
339
340
341 }
342}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
index 52791cb..429dda7 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
@@ -110,7 +110,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
110 public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel) 110 public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel)
111 { 111 {
112 string userAssetServer = string.Empty; 112 string userAssetServer = string.Empty;
113 if (IsForeignUser(avatarID, out userAssetServer) && m_OutboundPermission) 113 if (IsForeignUser(avatarID, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission)
114 { 114 {
115 Util.FireAndForget(delegate { m_assMapper.Post(assetID, avatarID, userAssetServer); }); 115 Util.FireAndForget(delegate { m_assMapper.Post(assetID, avatarID, userAssetServer); });
116 } 116 }
@@ -180,10 +180,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
180 public override void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver) 180 public override void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver)
181 { 181 {
182 string userAssetServer = string.Empty; 182 string userAssetServer = string.Empty;
183 if (IsForeignUser(sender, out userAssetServer)) 183 if (IsForeignUser(sender, out userAssetServer) && userAssetServer != string.Empty)
184 m_assMapper.Get(item.AssetID, sender, userAssetServer); 184 m_assMapper.Get(item.AssetID, sender, userAssetServer);
185 185
186 if (IsForeignUser(receiver, out userAssetServer) && m_OutboundPermission) 186 if (IsForeignUser(receiver, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission)
187 m_assMapper.Post(item.AssetID, receiver, userAssetServer); 187 m_assMapper.Post(item.AssetID, receiver, userAssetServer);
188 } 188 }
189 189
@@ -203,9 +203,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
203 if (aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) 203 if (aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
204 { 204 {
205 assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString(); 205 assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString();
206 assetServerURL = assetServerURL.Trim(new char[] { '/' }); return true; 206 assetServerURL = assetServerURL.Trim(new char[] { '/' });
207 } 207 }
208 } 208 }
209 else
210 {
211 assetServerURL = UserManagementModule.GetUserServerURL(userID, "AssetServerURI");
212 assetServerURL = assetServerURL.Trim(new char[] { '/' });
213 }
214 return true;
209 } 215 }
210 216
211 return false; 217 return false;
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index 4cc6905..4d073b2 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -35,6 +35,7 @@ using OpenSim.Region.Framework;
35using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Services.Interfaces; 37using OpenSim.Services.Interfaces;
38using OpenSim.Services.Connectors.Hypergrid;
38 39
39using OpenMetaverse; 40using OpenMetaverse;
40using log4net; 41using log4net;
@@ -47,7 +48,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
47 public UUID Id; 48 public UUID Id;
48 public string FirstName; 49 public string FirstName;
49 public string LastName; 50 public string LastName;
50 public string ProfileURL; 51 public string HomeURL;
52 public Dictionary<string, object> ServerURLs;
51 } 53 }
52 54
53 public class UserManagementModule : ISharedRegionModule, IUserManagement 55 public class UserManagementModule : ISharedRegionModule, IUserManagement
@@ -141,6 +143,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
141 143
142 void HandleUUIDNameRequest(UUID uuid, IClientAPI remote_client) 144 void HandleUUIDNameRequest(UUID uuid, IClientAPI remote_client)
143 { 145 {
146 m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0}", uuid);
144 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) 147 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid))
145 { 148 {
146 remote_client.SendNameReply(uuid, "Mr", "OpenSim"); 149 remote_client.SendNameReply(uuid, "Mr", "OpenSim");
@@ -210,6 +213,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
210 213
211 public string GetUserName(UUID uuid) 214 public string GetUserName(UUID uuid)
212 { 215 {
216 m_log.DebugFormat("[XXX] GetUserName {0}", uuid);
213 string[] names = GetUserNames(uuid); 217 string[] names = GetUserNames(uuid);
214 if (names.Length == 2) 218 if (names.Length == 2)
215 { 219 {
@@ -222,6 +226,34 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
222 return "(hippos)"; 226 return "(hippos)";
223 } 227 }
224 228
229 public string GetUserHomeURL(UUID userID)
230 {
231 if (m_UserCache.ContainsKey(userID))
232 return m_UserCache[userID].HomeURL;
233
234 return string.Empty;
235 }
236
237 public string GetUserServerURL(UUID userID, string serverType)
238 {
239 if (m_UserCache.ContainsKey(userID))
240 {
241 UserData userdata = m_UserCache[userID];
242 if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
243 return userdata.ServerURLs[serverType].ToString();
244
245 if (userdata.HomeURL != string.Empty)
246 {
247 UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL);
248 userdata.ServerURLs = uConn.GetServerURLs(userID);
249 if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
250 return userdata.ServerURLs[serverType].ToString();
251 }
252 }
253
254 return string.Empty;
255 }
256
225 public void AddUser(UUID id, string creatorData) 257 public void AddUser(UUID id, string creatorData)
226 { 258 {
227 if (m_UserCache.ContainsKey(id)) 259 if (m_UserCache.ContainsKey(id))
@@ -247,7 +279,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
247 string[] parts = creatorData.Split(';'); 279 string[] parts = creatorData.Split(';');
248 if (parts.Length >= 1) 280 if (parts.Length >= 1)
249 { 281 {
250 user.ProfileURL = parts[0]; 282 user.HomeURL = parts[0];
251 try 283 try
252 { 284 {
253 Uri uri = new Uri(parts[0]); 285 Uri uri = new Uri(parts[0]);
@@ -272,7 +304,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
272 lock (m_UserCache) 304 lock (m_UserCache)
273 m_UserCache[id] = user; 305 m_UserCache[id] = user;
274 306
275 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", user.Id, user.FirstName, user.LastName, user.ProfileURL); 307 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", user.Id, user.FirstName, user.LastName, user.HomeURL);
276 } 308 }
277 309
278 public void AddUser(UUID uuid, string first, string last, string profileURL) 310 public void AddUser(UUID uuid, string first, string last, string profileURL)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
index d2343c9..a5b5637 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
@@ -113,8 +113,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
113 ISimulationService simService = scene.RequestModuleInterface<ISimulationService>(); 113 ISimulationService simService = scene.RequestModuleInterface<ISimulationService>();
114 m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService); 114 m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService);
115 115
116 new UserAgentServerConnector(m_Config, MainServer.Instance); 116 IFriendsSimConnector friendsConn = scene.RequestModuleInterface<IFriendsSimConnector>();
117 new UserAgentServerConnector(m_Config, MainServer.Instance, friendsConn);
117 new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService"); 118 new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService");
119 new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService");
118 } 120 }
119 scene.RegisterModuleInterface<IGatekeeperService>(m_HypergridHandler.GateKeeper); 121 scene.RegisterModuleInterface<IGatekeeperService>(m_HypergridHandler.GateKeeper);
120 } 122 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
index 3f63db3..eef60a1 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
@@ -58,6 +58,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
58 58
59 private List<Scene> m_Scenes = new List<Scene>(); 59 private List<Scene> m_Scenes = new List<Scene>();
60 60
61 protected IUserManagement m_UserManagement;
62 protected IUserManagement UserManagementModule
63 {
64 get
65 {
66 if (m_UserManagement == null)
67 m_UserManagement = m_Scenes[0].RequestModuleInterface<IUserManagement>();
68 return m_UserManagement;
69 }
70 }
71
61 public Type ReplaceableInterface 72 public Type ReplaceableInterface
62 { 73 {
63 get { return null; } 74 get { return null; }
@@ -206,6 +217,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
206 return; 217 return;
207 } 218 }
208 } 219 }
220 else
221 {
222 inventoryURL = UserManagementModule.GetUserServerURL(userID, "InventoryServerURI");
223 inventoryURL = inventoryURL.Trim(new char[] { '/' });
224 }
209 } 225 }
210 } 226 }
211 } 227 }
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 170c35f..d7324c6 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -548,18 +548,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions
548 548
549 // libomv will moan about PrimFlags.ObjectYouOfficer being 549 // libomv will moan about PrimFlags.ObjectYouOfficer being
550 // deprecated 550 // deprecated
551 #pragma warning disable 0612 551#pragma warning disable 0612
552 objflags &= (uint) 552 objflags &= (uint)
553 ~(PrimFlags.ObjectCopy | // Tells client you can copy the object 553 ~(PrimFlags.ObjectCopy | // Tells client you can copy the object
554 PrimFlags.ObjectModify | // tells client you can modify the object 554 PrimFlags.ObjectModify | // tells client you can modify the object
555 PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) 555 PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod)
556 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it 556 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it
557 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object 557 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object
558 PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object 558 PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object
559 PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object 559 PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object
560 PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set 560 PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set
561 ); 561 );
562 #pragma warning restore 0612 562#pragma warning restore 0612
563 563
564 // Creating the three ObjectFlags options for this method to choose from. 564 // Creating the three ObjectFlags options for this method to choose from.
565 // Customize the OwnerMask 565 // Customize the OwnerMask
@@ -576,22 +576,27 @@ namespace OpenSim.Region.CoreModules.World.Permissions
576 576
577 if (m_bypassPermissions) 577 if (m_bypassPermissions)
578 return objectOwnerMask; 578 return objectOwnerMask;
579 579
580 // Object owners should be able to edit their own content 580 // Object owners should be able to edit their own content
581 if (user == objectOwner) 581 if (user == objectOwner)
582 return objectOwnerMask; 582 return objectOwnerMask;
583 583
584 if (IsFriendWithPerms(user, objectOwner)) 584 if (IsFriendWithPerms(user, objectOwner))
585 {
585 return objectOwnerMask; 586 return objectOwnerMask;
586 587 }
587 // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set 588 // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
588 if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner)) 589 if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner))
590 {
589 return objectOwnerMask; 591 return objectOwnerMask;
592 }
590 593
591 // Admin should be able to edit anything in the sim (including admin objects) 594 // Admin should be able to edit anything in the sim (including admin objects)
592 if (IsAdministrator(user)) 595 if (IsAdministrator(user))
596 {
593 return objectOwnerMask; 597 return objectOwnerMask;
594 598 }
599
595 // Users should be able to edit what is over their land. 600 // Users should be able to edit what is over their land.
596 Vector3 taskPos = task.AbsolutePosition; 601 Vector3 taskPos = task.AbsolutePosition;
597 ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y); 602 ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y);
@@ -599,13 +604,15 @@ namespace OpenSim.Region.CoreModules.World.Permissions
599 { 604 {
600 // Admin objects should not be editable by the above 605 // Admin objects should not be editable by the above
601 if (!IsAdministrator(objectOwner)) 606 if (!IsAdministrator(objectOwner))
607 {
602 return objectOwnerMask; 608 return objectOwnerMask;
609 }
603 } 610 }
604 611
605 // Group permissions 612 // Group permissions
606 if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0)) 613 if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0))
607 return objectGroupMask | objectEveryoneMask; 614 return objectGroupMask | objectEveryoneMask;
608 615
609 return objectEveryoneMask; 616 return objectEveryoneMask;
610 } 617 }
611 618
@@ -673,7 +680,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions
673 // 680 //
674 // Nobody but the object owner can set permissions on an object 681 // Nobody but the object owner can set permissions on an object
675 // 682 //
676
677 if (locked && (!IsAdministrator(currentUser)) && denyOnLocked) 683 if (locked && (!IsAdministrator(currentUser)) && denyOnLocked)
678 { 684 {
679 return false; 685 return false;
@@ -704,6 +710,11 @@ namespace OpenSim.Region.CoreModules.World.Permissions
704 // Return immediately, so that the administrator can shares group objects 710 // Return immediately, so that the administrator can shares group objects
705 return true; 711 return true;
706 } 712 }
713
714 // Friends with benefits should be able to edit the objects too
715 if (IsFriendWithPerms(currentUser, objectOwner))
716 // Return immediately, so that the administrator can share objects with friends
717 return true;
707 718
708 // Users should be able to edit what is over their land. 719 // Users should be able to edit what is over their land.
709 ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y); 720 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 0ff7dee..d4a6857 100644
--- a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs
@@ -34,6 +34,6 @@ namespace OpenSim.Region.Framework.Interfaces
34 public interface IFriendsModule 34 public interface IFriendsModule
35 { 35 {
36 uint GetFriendPerms(UUID PrincipalID, UUID FriendID); 36 uint GetFriendPerms(UUID PrincipalID, UUID FriendID);
37 void SendFriendsOnlineIfNeeded(IClientAPI client); 37 bool SendFriendsOnlineIfNeeded(IClientAPI client);
38 } 38 }
39} 39}
diff --git a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs
index 2904ee8..9cac3b0 100644
--- a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs
+++ b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs
@@ -8,6 +8,8 @@ namespace OpenSim.Region.Framework.Interfaces
8 public interface IUserManagement 8 public interface IUserManagement
9 { 9 {
10 string GetUserName(UUID uuid); 10 string GetUserName(UUID uuid);
11 string GetUserHomeURL(UUID uuid);
12 string GetUserServerURL(UUID uuid, string serverType);
11 void AddUser(UUID uuid, string userData); 13 void AddUser(UUID uuid, string userData);
12 void AddUser(UUID uuid, string firstName, string lastName, string profileURL); 14 void AddUser(UUID uuid, string firstName, string lastName, string profileURL);
13 } 15 }