mirror of
https://github.com/opensim/opensim.git
synced 2026-08-08 18:25:33 +08:00
Merge branch 'master' into careminster-presence-refactor
This commit is contained in:
@@ -124,7 +124,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
|
||||
|
||||
ScenePresence sp = m_scene.GetScenePresence(avatarID);
|
||||
if (sp != null)
|
||||
sp.ControllingClient.SendDialog(objectName, objectID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels);
|
||||
sp.ControllingClient.SendDialog(
|
||||
objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels);
|
||||
}
|
||||
|
||||
public void SendUrlToUser(
|
||||
|
||||
@@ -49,6 +49,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
{
|
||||
public class FriendsModule : ISharedRegionModule, IFriendsModule
|
||||
{
|
||||
protected bool m_Enabled = false;
|
||||
|
||||
protected class UserFriendData
|
||||
{
|
||||
public UUID PrincipalID;
|
||||
@@ -67,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0];
|
||||
protected static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0];
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
protected List<Scene> m_Scenes = new List<Scene>();
|
||||
@@ -130,7 +132,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
}
|
||||
}
|
||||
|
||||
#region ISharedRegionModule
|
||||
public void Initialise(IConfigSource config)
|
||||
{
|
||||
IConfig moduleConfig = config.Configs["Modules"];
|
||||
if (moduleConfig != null)
|
||||
{
|
||||
string name = moduleConfig.GetString("FriendsModule", "FriendsModule");
|
||||
if (name == Name)
|
||||
{
|
||||
InitModule(config);
|
||||
|
||||
m_Enabled = true;
|
||||
m_log.InfoFormat("[FRIENDS MODULE]: {0} enabled.", Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void InitModule(IConfigSource config)
|
||||
{
|
||||
IConfig friendsConfig = config.Configs["Friends"];
|
||||
if (friendsConfig != null)
|
||||
@@ -153,7 +172,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
m_log.Error("[FRIENDS]: No Connector defined in section Friends, or failed to load, cannot continue");
|
||||
throw new Exception("Connector load error");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
@@ -164,8 +182,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
{
|
||||
}
|
||||
|
||||
public void AddRegion(Scene scene)
|
||||
public virtual void AddRegion(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name);
|
||||
|
||||
m_Scenes.Add(scene);
|
||||
scene.RegisterModuleInterface<IFriendsModule>(this);
|
||||
|
||||
@@ -181,10 +203,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
m_Scenes.Remove(scene);
|
||||
}
|
||||
|
||||
public string Name
|
||||
public virtual string Name
|
||||
{
|
||||
get { return "FriendsModule"; }
|
||||
}
|
||||
@@ -194,13 +219,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public uint GetFriendPerms(UUID principalID, UUID friendID)
|
||||
#endregion
|
||||
|
||||
public virtual uint GetFriendPerms(UUID principalID, UUID friendID)
|
||||
{
|
||||
FriendInfo[] friends = GetFriends(principalID);
|
||||
foreach (FriendInfo fi in friends)
|
||||
FriendInfo finfo = GetFriend(friends, friendID);
|
||||
if (finfo != null)
|
||||
{
|
||||
if (fi.Friend == friendID.ToString())
|
||||
return (uint)fi.TheirFlags;
|
||||
return (uint)finfo.TheirFlags;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -214,30 +241,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
client.OnTerminateFriendship += OnTerminateFriendship;
|
||||
client.OnGrantUserRights += OnGrantUserRights;
|
||||
|
||||
// Asynchronously fetch the friends list or increment the refcount for the existing
|
||||
// friends list
|
||||
Util.FireAndForget(
|
||||
delegate(object o)
|
||||
{
|
||||
lock (m_Friends)
|
||||
{
|
||||
UserFriendData friendsData;
|
||||
if (m_Friends.TryGetValue(client.AgentId, out friendsData))
|
||||
{
|
||||
friendsData.Refcount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
friendsData = new UserFriendData();
|
||||
friendsData.PrincipalID = client.AgentId;
|
||||
friendsData.Friends = FriendsService.GetFriends(client.AgentId);
|
||||
friendsData.Refcount = 1;
|
||||
Util.FireAndForget(delegate { FetchFriendslist(client); });
|
||||
}
|
||||
|
||||
m_Friends[client.AgentId] = friendsData;
|
||||
}
|
||||
}
|
||||
/// Fetch the friends list or increment the refcount for the existing
|
||||
/// friends list
|
||||
/// Returns true if the list was fetched, false if it wasn't
|
||||
protected virtual bool FetchFriendslist(IClientAPI client)
|
||||
{
|
||||
UUID agentID = client.AgentId;
|
||||
lock (m_Friends)
|
||||
{
|
||||
UserFriendData friendsData;
|
||||
if (m_Friends.TryGetValue(agentID, out friendsData))
|
||||
{
|
||||
friendsData.Refcount++;
|
||||
return false;
|
||||
}
|
||||
);
|
||||
else
|
||||
{
|
||||
friendsData = new UserFriendData();
|
||||
friendsData.PrincipalID = agentID;
|
||||
friendsData.Friends = GetFriendsFromService(client);
|
||||
friendsData.Refcount = 1;
|
||||
|
||||
m_Friends[agentID] = friendsData;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClientClosed(UUID agentID, Scene scene)
|
||||
@@ -263,14 +294,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
|
||||
private void OnMakeRootAgent(ScenePresence sp)
|
||||
{
|
||||
UUID agentID = sp.ControllingClient.AgentId;
|
||||
UpdateFriendsCache(agentID);
|
||||
RefetchFriends(sp.ControllingClient);
|
||||
}
|
||||
|
||||
private void OnClientLogin(IClientAPI client)
|
||||
{
|
||||
UUID agentID = client.AgentId;
|
||||
|
||||
//m_log.DebugFormat("[XXX]: OnClientLogin!");
|
||||
// Inform the friends that this user is online
|
||||
StatusChange(agentID, true);
|
||||
|
||||
@@ -279,7 +310,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
m_NeedsListOfFriends.Add(agentID);
|
||||
}
|
||||
|
||||
public void SendFriendsOnlineIfNeeded(IClientAPI client)
|
||||
public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client)
|
||||
{
|
||||
UUID agentID = client.AgentId;
|
||||
|
||||
@@ -287,7 +318,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
lock (m_NeedsListOfFriends)
|
||||
{
|
||||
if (!m_NeedsListOfFriends.Remove(agentID))
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Send the friends online
|
||||
@@ -313,10 +344,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
foreach (string fid in outstanding)
|
||||
{
|
||||
UUID fromAgentID;
|
||||
if (!UUID.TryParse(fid, out fromAgentID))
|
||||
string firstname = "Unknown", lastname = "User";
|
||||
if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname))
|
||||
{
|
||||
m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid);
|
||||
continue;
|
||||
|
||||
UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, fromAgentID);
|
||||
}
|
||||
|
||||
PresenceInfo presence = null;
|
||||
PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid });
|
||||
@@ -326,13 +359,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
im.offline = 0;
|
||||
|
||||
im.fromAgentID = fromAgentID.Guid;
|
||||
im.fromAgentName = account.FirstName + " " + account.LastName;
|
||||
im.fromAgentName = firstname + " " + lastname;
|
||||
im.offline = (byte)((presence == null) ? 1 : 0);
|
||||
im.imSessionID = im.fromAgentID;
|
||||
im.message = FriendshipMessage(fid);
|
||||
|
||||
// Finally
|
||||
LocalFriendshipOffered(agentID, im);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual string FriendshipMessage(string friendID)
|
||||
{
|
||||
return "Will you be my friend?";
|
||||
}
|
||||
|
||||
protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
|
||||
{
|
||||
first = "Unknown"; last = "User";
|
||||
if (!UUID.TryParse(fid, out agentID))
|
||||
return false;
|
||||
|
||||
UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(scopeID, agentID);
|
||||
if (account != null)
|
||||
{
|
||||
first = account.FirstName;
|
||||
last = account.LastName;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
List<UUID> GetOnlineFriends(UUID userID)
|
||||
@@ -348,19 +405,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
}
|
||||
|
||||
if (friendList.Count > 0)
|
||||
{
|
||||
PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
|
||||
foreach (PresenceInfo pi in presence)
|
||||
{
|
||||
UUID presenceID;
|
||||
if (UUID.TryParse(pi.UserID, out presenceID))
|
||||
online.Add(presenceID);
|
||||
}
|
||||
}
|
||||
GetOnlineFriends(userID, friendList, online);
|
||||
|
||||
return online;
|
||||
}
|
||||
|
||||
protected virtual void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
|
||||
{
|
||||
PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
|
||||
foreach (PresenceInfo pi in presence)
|
||||
{
|
||||
UUID presenceID;
|
||||
if (UUID.TryParse(pi.UserID, out presenceID))
|
||||
online.Add(presenceID);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the client for a ID
|
||||
/// </summary>
|
||||
@@ -415,51 +475,51 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
Util.FireAndForget(
|
||||
delegate
|
||||
{
|
||||
foreach (FriendInfo fi in friendList)
|
||||
{
|
||||
//m_log.DebugFormat("[FRIENDS]: Notifying {0}", fi.PrincipalID);
|
||||
// Notify about this user status
|
||||
StatusNotify(fi, agentID, online);
|
||||
}
|
||||
m_log.DebugFormat("[FRIENDS MODULE]: Notifying {0} friends", friendList.Count);
|
||||
// Notify about this user status
|
||||
StatusNotify(friendList, agentID, online);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void StatusNotify(FriendInfo friend, UUID userID, bool online)
|
||||
protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
|
||||
{
|
||||
UUID friendID;
|
||||
if (UUID.TryParse(friend.Friend, out friendID))
|
||||
foreach (FriendInfo friend in friendList)
|
||||
{
|
||||
// Try local
|
||||
if (LocalStatusNotification(userID, friendID, online))
|
||||
return;
|
||||
|
||||
// The friend is not here [as root]. Let's forward.
|
||||
PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
|
||||
if (friendSessions != null && friendSessions.Length > 0)
|
||||
UUID friendID;
|
||||
if (UUID.TryParse(friend.Friend, out friendID))
|
||||
{
|
||||
PresenceInfo friendSession = null;
|
||||
foreach (PresenceInfo pinfo in friendSessions)
|
||||
if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad
|
||||
{
|
||||
friendSession = pinfo;
|
||||
break;
|
||||
}
|
||||
// Try local
|
||||
if (LocalStatusNotification(userID, friendID, online))
|
||||
return;
|
||||
|
||||
if (friendSession != null)
|
||||
// The friend is not here [as root]. Let's forward.
|
||||
PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
|
||||
if (friendSessions != null && friendSessions.Length > 0)
|
||||
{
|
||||
GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
|
||||
//m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
|
||||
m_FriendsSimConnector.StatusNotify(region, userID, friendID, online);
|
||||
}
|
||||
}
|
||||
PresenceInfo friendSession = null;
|
||||
foreach (PresenceInfo pinfo in friendSessions)
|
||||
if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad
|
||||
{
|
||||
friendSession = pinfo;
|
||||
break;
|
||||
}
|
||||
|
||||
// Friend is not online. Ignore.
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend);
|
||||
if (friendSession != null)
|
||||
{
|
||||
GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
|
||||
//m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
|
||||
m_FriendsSimConnector.StatusNotify(region, userID, friendID, online);
|
||||
}
|
||||
}
|
||||
|
||||
// Friend is not online. Ignore.
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -475,7 +535,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
|
||||
// This user wants to be friends with the other user.
|
||||
// Let's add the relation backwards, in case the other is not online
|
||||
FriendsService.StoreFriend(friendID, principalID.ToString(), 0);
|
||||
StoreBackwards(friendID, principalID);
|
||||
|
||||
// Now let's ask the other user to be friends with this user
|
||||
ForwardFriendshipOffer(principalID, friendID, im);
|
||||
@@ -487,11 +547,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
// !!!!!!!! This is a hack so that we don't have to keep state (transactionID/imSessionID)
|
||||
// We stick this agent's ID as imSession, so that it's directly available on the receiving end
|
||||
im.imSessionID = im.fromAgentID;
|
||||
im.fromAgentName = GetFriendshipRequesterName(agentID);
|
||||
|
||||
// Try the local sim
|
||||
UserAccount account = UserAccountService.GetUserAccount(UUID.Zero, agentID);
|
||||
im.fromAgentName = (account == null) ? "Unknown" : account.FirstName + " " + account.LastName;
|
||||
|
||||
// Try the local sim
|
||||
if (LocalFriendshipOffered(friendID, im))
|
||||
return;
|
||||
|
||||
@@ -509,12 +567,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
// If the prospective friend is not online, he'll get the message upon login.
|
||||
}
|
||||
|
||||
protected virtual string GetFriendshipRequesterName(UUID agentID)
|
||||
{
|
||||
UserAccount account = UserAccountService.GetUserAccount(UUID.Zero, agentID);
|
||||
return (account == null) ? "Unknown" : account.FirstName + " " + account.LastName;
|
||||
}
|
||||
|
||||
private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
|
||||
{
|
||||
m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID);
|
||||
|
||||
FriendsService.StoreFriend(agentID, friendID.ToString(), 1);
|
||||
FriendsService.StoreFriend(friendID, agentID.ToString(), 1);
|
||||
|
||||
StoreFriendships(agentID, friendID);
|
||||
|
||||
ICallingCardModule ccm = client.Scene.RequestModuleInterface<ICallingCardModule>();
|
||||
if (ccm != null)
|
||||
@@ -523,7 +586,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
}
|
||||
|
||||
// Update the local cache
|
||||
UpdateFriendsCache(agentID);
|
||||
RefetchFriends(client);
|
||||
|
||||
//
|
||||
// Notify the friend
|
||||
@@ -554,8 +617,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
{
|
||||
m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", agentID, friendID);
|
||||
|
||||
FriendsService.Delete(agentID, friendID.ToString());
|
||||
FriendsService.Delete(friendID, agentID.ToString());
|
||||
DeleteFriendship(agentID, friendID);
|
||||
|
||||
//
|
||||
// Notify the friend
|
||||
@@ -582,11 +644,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
|
||||
private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID)
|
||||
{
|
||||
FriendsService.Delete(agentID, exfriendID.ToString());
|
||||
FriendsService.Delete(exfriendID, agentID.ToString());
|
||||
if (!DeleteFriendship(agentID, exfriendID))
|
||||
client.SendAlertMessage("Unable to terminate friendship on this sim.");
|
||||
|
||||
// Update local cache
|
||||
UpdateFriendsCache(agentID);
|
||||
RefetchFriends(client);
|
||||
|
||||
client.SendTerminateFriend(exfriendID);
|
||||
|
||||
@@ -612,23 +674,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
|
||||
private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights)
|
||||
{
|
||||
m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target);
|
||||
|
||||
FriendInfo[] friends = GetFriends(remoteClient.AgentId);
|
||||
if (friends.Length == 0)
|
||||
return;
|
||||
|
||||
m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target);
|
||||
// Let's find the friend in this user's friend list
|
||||
FriendInfo friend = null;
|
||||
foreach (FriendInfo fi in friends)
|
||||
{
|
||||
if (fi.Friend == target.ToString())
|
||||
friend = fi;
|
||||
return;
|
||||
}
|
||||
|
||||
// Let's find the friend in this user's friend list
|
||||
FriendInfo friend = GetFriend(friends, target);
|
||||
|
||||
if (friend != null) // Found it
|
||||
{
|
||||
// Store it on the DB
|
||||
FriendsService.StoreFriend(requester, target.ToString(), rights);
|
||||
if (!StoreRights(requester, target, rights))
|
||||
{
|
||||
remoteClient.SendAlertMessage("Unable to grant rights.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Store it in the local cache
|
||||
int myFlags = friend.MyFlags;
|
||||
@@ -658,6 +722,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
m_log.DebugFormat("[FRIENDS MODULE]: friend {0} not found for {1}", target, requester);
|
||||
}
|
||||
|
||||
protected virtual FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
|
||||
{
|
||||
foreach (FriendInfo fi in friends)
|
||||
{
|
||||
if (fi.Friend == friendID.ToString())
|
||||
return fi;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
#region Local
|
||||
@@ -693,7 +769,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
|
||||
|
||||
// Update the local cache
|
||||
UpdateFriendsCache(friendID);
|
||||
RefetchFriends(friendClient);
|
||||
|
||||
// we're done
|
||||
return true;
|
||||
@@ -726,7 +802,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
// the friend in this sim as root agent
|
||||
friendClient.SendTerminateFriend(exfriendID);
|
||||
// update local cache
|
||||
UpdateFriendsCache(exfriendID);
|
||||
RefetchFriends(friendClient);
|
||||
// we're done
|
||||
return true;
|
||||
}
|
||||
@@ -756,15 +832,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
}
|
||||
|
||||
// Update local cache
|
||||
lock (m_Friends)
|
||||
{
|
||||
FriendInfo[] friends = GetFriends(friendID);
|
||||
foreach (FriendInfo finfo in friends)
|
||||
{
|
||||
if (finfo.Friend == userID.ToString())
|
||||
finfo.TheirFlags = rights;
|
||||
}
|
||||
}
|
||||
UpdateLocalCache(userID, friendID, rights);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -775,10 +843,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
|
||||
public bool LocalStatusNotification(UUID userID, UUID friendID, bool online)
|
||||
{
|
||||
m_log.DebugFormat("[FRIENDS]: Local Status Notify {0} that user {1} is {2}", friendID, userID, online);
|
||||
IClientAPI friendClient = LocateClientObject(friendID);
|
||||
if (friendClient != null)
|
||||
{
|
||||
//m_log.DebugFormat("[FRIENDS]: Local Status Notify {0} that user {1} is {2}", friendID, userID, online);
|
||||
// the friend in this sim as root agent
|
||||
if (online)
|
||||
friendClient.SendAgentOnline(new UUID[] { userID });
|
||||
@@ -793,7 +861,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
|
||||
#endregion
|
||||
|
||||
private FriendInfo[] GetFriends(UUID agentID)
|
||||
#region Get / Set friends in several flavours
|
||||
/// <summary>
|
||||
/// Get friends from local cache only
|
||||
/// </summary>
|
||||
/// <param name="agentID"></param>
|
||||
/// <returns></returns>
|
||||
protected FriendInfo[] GetFriends(UUID agentID)
|
||||
{
|
||||
UserFriendData friendsData;
|
||||
|
||||
@@ -806,14 +880,63 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
return EMPTY_FRIENDS;
|
||||
}
|
||||
|
||||
private void UpdateFriendsCache(UUID agentID)
|
||||
/// <summary>
|
||||
/// Update loca cache only
|
||||
/// </summary>
|
||||
/// <param name="userID"></param>
|
||||
/// <param name="friendID"></param>
|
||||
/// <param name="rights"></param>
|
||||
protected void UpdateLocalCache(UUID userID, UUID friendID, int rights)
|
||||
{
|
||||
// Update local cache
|
||||
lock (m_Friends)
|
||||
{
|
||||
FriendInfo[] friends = GetFriends(friendID);
|
||||
FriendInfo finfo = GetFriend(friends, userID);
|
||||
finfo.TheirFlags = rights;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual FriendInfo[] GetFriendsFromService(IClientAPI client)
|
||||
{
|
||||
return FriendsService.GetFriends(client.AgentId);
|
||||
}
|
||||
|
||||
private void RefetchFriends(IClientAPI client)
|
||||
{
|
||||
UUID agentID = client.AgentId;
|
||||
lock (m_Friends)
|
||||
{
|
||||
UserFriendData friendsData;
|
||||
if (m_Friends.TryGetValue(agentID, out friendsData))
|
||||
friendsData.Friends = FriendsService.GetFriends(agentID);
|
||||
friendsData.Friends = GetFriendsFromService(client);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual bool StoreRights(UUID agentID, UUID friendID, int rights)
|
||||
{
|
||||
FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), rights);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual void StoreBackwards(UUID friendID, UUID agentID)
|
||||
{
|
||||
FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0);
|
||||
}
|
||||
|
||||
protected virtual void StoreFriendships(UUID agentID, UUID friendID)
|
||||
{
|
||||
FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), 1);
|
||||
FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 1);
|
||||
}
|
||||
|
||||
protected virtual bool DeleteFriendship(UUID agentID, UUID exfriendID)
|
||||
{
|
||||
FriendsService.Delete(agentID, exfriendID.ToString());
|
||||
FriendsService.Delete(exfriendID, agentID.ToString());
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
628
OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
Normal file
628
OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
Normal file
@@ -0,0 +1,628 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
using Nwc.XmlRpc;
|
||||
using Mono.Addins;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using OpenSim.Services.Connectors.Hypergrid;
|
||||
using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
|
||||
using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
|
||||
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
{
|
||||
public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule, IFriendsSimConnector
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
#region ISharedRegionModule
|
||||
public override string Name
|
||||
{
|
||||
get { return "HGFriendsModule"; }
|
||||
}
|
||||
|
||||
public override void AddRegion(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
base.AddRegion(scene);
|
||||
scene.RegisterModuleInterface<IFriendsSimConnector>(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IFriendsSimConnector
|
||||
|
||||
/// <summary>
|
||||
/// Notify the user that the friend's status changed
|
||||
/// </summary>
|
||||
/// <param name="userID">user to be notified</param>
|
||||
/// <param name="friendID">friend whose status changed</param>
|
||||
/// <param name="online">status</param>
|
||||
/// <returns></returns>
|
||||
public bool StatusNotify(UUID friendID, UUID userID, bool online)
|
||||
{
|
||||
return LocalStatusNotification(friendID, userID, online);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected override bool FetchFriendslist(IClientAPI client)
|
||||
{
|
||||
if (base.FetchFriendslist(client))
|
||||
{
|
||||
UUID agentID = client.AgentId;
|
||||
// we do this only for the root agent
|
||||
if (m_Friends[agentID].Refcount == 1)
|
||||
{
|
||||
// We need to preload the user management cache with the names
|
||||
// of foreign friends, just like we do with SOPs' creators
|
||||
foreach (FriendInfo finfo in m_Friends[agentID].Friends)
|
||||
{
|
||||
if (finfo.TheirFlags != -1)
|
||||
{
|
||||
UUID id;
|
||||
if (!UUID.TryParse(finfo.Friend, out id))
|
||||
{
|
||||
string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
|
||||
if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last, out tmp))
|
||||
{
|
||||
IUserManagement uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
|
||||
uMan.AddUser(id, url + ";" + first + " " + last);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool SendFriendsOnlineIfNeeded(IClientAPI client)
|
||||
{
|
||||
if (base.SendFriendsOnlineIfNeeded(client))
|
||||
{
|
||||
AgentCircuitData aCircuit = ((Scene)client.Scene).AuthenticateHandler.GetAgentCircuitData(client.AgentId);
|
||||
if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0)
|
||||
{
|
||||
UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, client.AgentId);
|
||||
if (account == null) // foreign
|
||||
{
|
||||
FriendInfo[] friends = GetFriends(client.AgentId);
|
||||
foreach (FriendInfo f in friends)
|
||||
{
|
||||
client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
|
||||
{
|
||||
List<string> fList = new List<string>();
|
||||
foreach (string s in friendList)
|
||||
fList.Add(s.Substring(0, 36));
|
||||
|
||||
PresenceInfo[] presence = PresenceService.GetAgents(fList.ToArray());
|
||||
foreach (PresenceInfo pi in presence)
|
||||
{
|
||||
UUID presenceID;
|
||||
if (UUID.TryParse(pi.UserID, out presenceID))
|
||||
online.Add(presenceID);
|
||||
}
|
||||
}
|
||||
|
||||
//protected override void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
|
||||
//{
|
||||
// // Let's single out the UUIs
|
||||
// List<string> localFriends = new List<string>();
|
||||
// List<string> foreignFriends = new List<string>();
|
||||
// string tmp = string.Empty;
|
||||
|
||||
// foreach (string s in friendList)
|
||||
// {
|
||||
// UUID id;
|
||||
// if (UUID.TryParse(s, out id))
|
||||
// localFriends.Add(s);
|
||||
// else if (Util.ParseUniversalUserIdentifier(s, out id, out tmp, out tmp, out tmp, out tmp))
|
||||
// {
|
||||
// foreignFriends.Add(s);
|
||||
// // add it here too, who knows maybe the foreign friends happens to be on this grid
|
||||
// localFriends.Add(id.ToString());
|
||||
// }
|
||||
// }
|
||||
|
||||
// // OK, see who's present on this grid
|
||||
// List<string> toBeRemoved = new List<string>();
|
||||
// PresenceInfo[] presence = PresenceService.GetAgents(localFriends.ToArray());
|
||||
// foreach (PresenceInfo pi in presence)
|
||||
// {
|
||||
// UUID presenceID;
|
||||
// if (UUID.TryParse(pi.UserID, out presenceID))
|
||||
// {
|
||||
// online.Add(presenceID);
|
||||
// foreach (string s in foreignFriends)
|
||||
// if (s.StartsWith(pi.UserID))
|
||||
// toBeRemoved.Add(s);
|
||||
// }
|
||||
// }
|
||||
|
||||
// foreach (string s in toBeRemoved)
|
||||
// foreignFriends.Remove(s);
|
||||
|
||||
// // OK, let's send this up the stack, and leave a closure here
|
||||
// // collecting online friends in other grids
|
||||
// Util.FireAndForget(delegate { CollectOnlineFriendsElsewhere(userID, foreignFriends); });
|
||||
|
||||
//}
|
||||
|
||||
private void CollectOnlineFriendsElsewhere(UUID userID, List<string> foreignFriends)
|
||||
{
|
||||
// let's divide the friends on a per-domain basis
|
||||
Dictionary<string, List<string>> friendsPerDomain = new Dictionary<string, List<string>>();
|
||||
foreach (string friend in foreignFriends)
|
||||
{
|
||||
UUID friendID;
|
||||
if (!UUID.TryParse(friend, out friendID))
|
||||
{
|
||||
// it's a foreign friend
|
||||
string url = string.Empty, tmp = string.Empty;
|
||||
if (Util.ParseUniversalUserIdentifier(friend, out friendID, out url, out tmp, out tmp, out tmp))
|
||||
{
|
||||
if (!friendsPerDomain.ContainsKey(url))
|
||||
friendsPerDomain[url] = new List<string>();
|
||||
friendsPerDomain[url].Add(friend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now, call those worlds
|
||||
|
||||
foreach (KeyValuePair<string, List<string>> kvp in friendsPerDomain)
|
||||
{
|
||||
List<string> ids = new List<string>();
|
||||
foreach (string f in kvp.Value)
|
||||
ids.Add(f);
|
||||
UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key);
|
||||
List<UUID> online = uConn.GetOnlineFriends(userID, ids);
|
||||
// Finally send the notifications to the user
|
||||
// this whole process may take a while, so let's check at every
|
||||
// iteration that the user is still here
|
||||
IClientAPI client = LocateClientObject(userID);
|
||||
if (client != null)
|
||||
client.SendAgentOnline(online.ToArray());
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected override void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
|
||||
{
|
||||
// First, let's divide the friends on a per-domain basis
|
||||
Dictionary<string, List<FriendInfo>> friendsPerDomain = new Dictionary<string, List<FriendInfo>>();
|
||||
foreach (FriendInfo friend in friendList)
|
||||
{
|
||||
UUID friendID;
|
||||
if (UUID.TryParse(friend.Friend, out friendID))
|
||||
{
|
||||
if (!friendsPerDomain.ContainsKey("local"))
|
||||
friendsPerDomain["local"] = new List<FriendInfo>();
|
||||
friendsPerDomain["local"].Add(friend);
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's a foreign friend
|
||||
string url = string.Empty, tmp = string.Empty;
|
||||
if (Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out url, out tmp, out tmp, out tmp))
|
||||
{
|
||||
// Let's try our luck in the local sim. Who knows, maybe it's here
|
||||
if (LocalStatusNotification(userID, friendID, online))
|
||||
continue;
|
||||
|
||||
if (!friendsPerDomain.ContainsKey(url))
|
||||
friendsPerDomain[url] = new List<FriendInfo>();
|
||||
friendsPerDomain[url].Add(friend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For the local friends, just call the base method
|
||||
// Let's do this first of all
|
||||
if (friendsPerDomain.ContainsKey("local"))
|
||||
base.StatusNotify(friendsPerDomain["local"], userID, online);
|
||||
|
||||
foreach (KeyValuePair<string, List<FriendInfo>> kvp in friendsPerDomain)
|
||||
{
|
||||
if (kvp.Key != "local")
|
||||
{
|
||||
// For the others, call the user agent service
|
||||
List<string> ids = new List<string>();
|
||||
foreach (FriendInfo f in kvp.Value)
|
||||
ids.Add(f.Friend);
|
||||
UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key);
|
||||
List<UUID> friendsOnline = uConn.StatusNotification(ids, userID, online);
|
||||
// need to debug this here
|
||||
if (online)
|
||||
{
|
||||
IClientAPI client = LocateClientObject(userID);
|
||||
if (client != null)
|
||||
client.SendAgentOnline(friendsOnline.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
|
||||
{
|
||||
first = "Unknown"; last = "User";
|
||||
if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last))
|
||||
return true;
|
||||
|
||||
// fid is not a UUID...
|
||||
string url = string.Empty, tmp = string.Empty;
|
||||
if (Util.ParseUniversalUserIdentifier(fid, out agentID, out url, out first, out last, out tmp))
|
||||
{
|
||||
IUserManagement userMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
|
||||
userMan.AddUser(agentID, url + ";" + first + " " + last);
|
||||
|
||||
try // our best
|
||||
{
|
||||
string[] parts = userMan.GetUserName(agentID).Split();
|
||||
first = parts[0];
|
||||
last = parts[1];
|
||||
}
|
||||
catch { }
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override string GetFriendshipRequesterName(UUID agentID)
|
||||
{
|
||||
// For the time being we assume that HG friendship requests can only happen
|
||||
// when avies are on the same region.
|
||||
IClientAPI client = LocateClientObject(agentID);
|
||||
if (client != null)
|
||||
return client.FirstName + " " + client.LastName;
|
||||
else
|
||||
return base.GetFriendshipRequesterName(agentID);
|
||||
}
|
||||
|
||||
protected override string FriendshipMessage(string friendID)
|
||||
{
|
||||
UUID id;
|
||||
if (UUID.TryParse(friendID, out id))
|
||||
return base.FriendshipMessage(friendID);
|
||||
|
||||
return "Please confirm this friendship you made while you were away.";
|
||||
}
|
||||
|
||||
protected override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
|
||||
{
|
||||
foreach (FriendInfo fi in friends)
|
||||
{
|
||||
if (fi.Friend.StartsWith(friendID.ToString()))
|
||||
return fi;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected override FriendInfo[] GetFriendsFromService(IClientAPI client)
|
||||
{
|
||||
UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, client.AgentId);
|
||||
if (account1 != null)
|
||||
return base.GetFriendsFromService(client);
|
||||
|
||||
FriendInfo[] finfos = new FriendInfo[0];
|
||||
// Foreigner
|
||||
AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
|
||||
if (agentClientCircuit != null)
|
||||
{
|
||||
string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
|
||||
|
||||
finfos = FriendsService.GetFriends(agentUUI);
|
||||
m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI);
|
||||
}
|
||||
return finfos;
|
||||
}
|
||||
|
||||
protected override bool StoreRights(UUID agentID, UUID friendID, int rights)
|
||||
{
|
||||
UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
|
||||
UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID);
|
||||
// Are they both local users?
|
||||
if (account1 != null && account2 != null)
|
||||
{
|
||||
// local grid users
|
||||
return base.StoreRights(agentID, friendID, rights);
|
||||
}
|
||||
|
||||
if (account1 != null) // agent is local, friend is foreigner
|
||||
{
|
||||
FriendInfo[] finfos = GetFriends(agentID);
|
||||
FriendInfo finfo = GetFriend(finfos, friendID);
|
||||
if (finfo != null)
|
||||
{
|
||||
FriendsService.StoreFriend(agentID.ToString(), finfo.Friend, rights);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (account2 != null) // agent is foreigner, friend is local
|
||||
{
|
||||
string agentUUI = GetUUI(friendID, agentID);
|
||||
if (agentUUI != string.Empty)
|
||||
{
|
||||
FriendsService.StoreFriend(agentUUI, friendID.ToString(), rights);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
protected override void StoreBackwards(UUID friendID, UUID agentID)
|
||||
{
|
||||
UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
|
||||
UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID);
|
||||
// Are they both local users?
|
||||
if (account1 != null && account2 != null)
|
||||
{
|
||||
// local grid users
|
||||
m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local");
|
||||
base.StoreBackwards(friendID, agentID);
|
||||
return;
|
||||
}
|
||||
|
||||
// no provision for this temporary friendship state
|
||||
//FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0);
|
||||
}
|
||||
|
||||
protected override void StoreFriendships(UUID agentID, UUID friendID)
|
||||
{
|
||||
UserAccount agentAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
|
||||
UserAccount friendAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID);
|
||||
// Are they both local users?
|
||||
if (agentAccount != null && friendAccount != null)
|
||||
{
|
||||
// local grid users
|
||||
m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local");
|
||||
base.StoreFriendships(agentID, friendID);
|
||||
return;
|
||||
}
|
||||
|
||||
// ok, at least one of them is foreigner, let's get their data
|
||||
IClientAPI agentClient = LocateClientObject(agentID);
|
||||
IClientAPI friendClient = LocateClientObject(friendID);
|
||||
AgentCircuitData agentClientCircuit = null;
|
||||
AgentCircuitData friendClientCircuit = null;
|
||||
string agentUUI = string.Empty;
|
||||
string friendUUI = string.Empty;
|
||||
string agentFriendService = string.Empty;
|
||||
string friendFriendService = string.Empty;
|
||||
|
||||
if (agentClient != null)
|
||||
{
|
||||
agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode);
|
||||
agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
|
||||
agentFriendService = agentClientCircuit.ServiceURLs["FriendsServerURI"].ToString();
|
||||
}
|
||||
if (friendClient != null)
|
||||
{
|
||||
friendClientCircuit = ((Scene)(friendClient.Scene)).AuthenticateHandler.GetAgentCircuitData(friendClient.CircuitCode);
|
||||
friendUUI = Util.ProduceUserUniversalIdentifier(friendClientCircuit);
|
||||
friendFriendService = friendClientCircuit.ServiceURLs["FriendsServerURI"].ToString();
|
||||
}
|
||||
|
||||
m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}",
|
||||
agentUUI, friendUUI, agentFriendService, friendFriendService);
|
||||
|
||||
// Generate a random 8-character hex number that will sign this friendship
|
||||
string secret = UUID.Random().ToString().Substring(0, 8);
|
||||
|
||||
if (agentAccount != null) // agent is local, 'friend' is foreigner
|
||||
{
|
||||
// This may happen when the agent returned home, in which case the friend is not there
|
||||
// We need to look for its information in the friends list itself
|
||||
bool confirming = false;
|
||||
if (friendUUI == string.Empty)
|
||||
{
|
||||
FriendInfo[] finfos = GetFriends(agentID);
|
||||
foreach (FriendInfo finfo in finfos)
|
||||
{
|
||||
if (finfo.TheirFlags == -1)
|
||||
{
|
||||
if (finfo.Friend.StartsWith(friendID.ToString()))
|
||||
{
|
||||
friendUUI = finfo.Friend;
|
||||
confirming = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If it's confirming the friendship, we already have the full friendUUI with the secret
|
||||
string theFriendUUID = confirming ? friendUUI : friendUUI + ";" + secret;
|
||||
|
||||
// store in the local friends service a reference to the foreign friend
|
||||
FriendsService.StoreFriend(agentID.ToString(), theFriendUUID, 1);
|
||||
// and also the converse
|
||||
FriendsService.StoreFriend(theFriendUUID, agentID.ToString(), 1);
|
||||
|
||||
if (!confirming && friendClientCircuit != null)
|
||||
{
|
||||
// store in the foreign friends service a reference to the local agent
|
||||
HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID);
|
||||
friendsConn.NewFriendship(friendID, agentUUI + ";" + secret);
|
||||
}
|
||||
}
|
||||
else if (friendAccount != null) // 'friend' is local, agent is foreigner
|
||||
{
|
||||
// store in the local friends service a reference to the foreign agent
|
||||
FriendsService.StoreFriend(friendID.ToString(), agentUUI + ";" + secret, 1);
|
||||
// and also the converse
|
||||
FriendsService.StoreFriend(agentUUI + ";" + secret, friendID.ToString(), 1);
|
||||
|
||||
if (agentClientCircuit != null)
|
||||
{
|
||||
// store in the foreign friends service a reference to the local agent
|
||||
HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID);
|
||||
friendsConn.NewFriendship(agentID, friendUUI + ";" + secret);
|
||||
}
|
||||
}
|
||||
else // They're both foreigners!
|
||||
{
|
||||
HGFriendsServicesConnector friendsConn;
|
||||
if (agentClientCircuit != null)
|
||||
{
|
||||
friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID);
|
||||
friendsConn.NewFriendship(agentID, friendUUI + ";" + secret);
|
||||
}
|
||||
if (friendClientCircuit != null)
|
||||
{
|
||||
friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID);
|
||||
friendsConn.NewFriendship(friendID, agentUUI + ";" + secret);
|
||||
}
|
||||
}
|
||||
// my brain hurts now
|
||||
}
|
||||
|
||||
protected override bool DeleteFriendship(UUID agentID, UUID exfriendID)
|
||||
{
|
||||
UserAccount agentAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
|
||||
UserAccount friendAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, exfriendID);
|
||||
// Are they both local users?
|
||||
if (agentAccount != null && friendAccount != null)
|
||||
{
|
||||
// local grid users
|
||||
return base.DeleteFriendship(agentID, exfriendID);
|
||||
}
|
||||
|
||||
// ok, at least one of them is foreigner, let's get their data
|
||||
string agentUUI = string.Empty;
|
||||
string friendUUI = string.Empty;
|
||||
|
||||
if (agentAccount != null) // agent is local, 'friend' is foreigner
|
||||
{
|
||||
// We need to look for its information in the friends list itself
|
||||
FriendInfo[] finfos = GetFriends(agentID);
|
||||
FriendInfo finfo = GetFriend(finfos, exfriendID);
|
||||
if (finfo != null)
|
||||
{
|
||||
friendUUI = finfo.Friend;
|
||||
|
||||
// delete in the local friends service the reference to the foreign friend
|
||||
FriendsService.Delete(agentID, friendUUI);
|
||||
// and also the converse
|
||||
FriendsService.Delete(friendUUI, agentID.ToString());
|
||||
|
||||
// notify the exfriend's service
|
||||
Util.FireAndForget(delegate { Delete(exfriendID, agentID, friendUUI); });
|
||||
|
||||
m_log.DebugFormat("[HGFRIENDS MODULE]: {0} terminated {1}", agentID, friendUUI);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (friendAccount != null) // agent is foreigner, 'friend' is local
|
||||
{
|
||||
agentUUI = GetUUI(exfriendID, agentID);
|
||||
|
||||
if (agentUUI != string.Empty)
|
||||
{
|
||||
// delete in the local friends service the reference to the foreign agent
|
||||
FriendsService.Delete(exfriendID, agentUUI);
|
||||
// and also the converse
|
||||
FriendsService.Delete(agentUUI, exfriendID.ToString());
|
||||
|
||||
// notify the agent's service?
|
||||
Util.FireAndForget(delegate { Delete(agentID, exfriendID, agentUUI); });
|
||||
|
||||
m_log.DebugFormat("[HGFRIENDS MODULE]: {0} terminated {1}", agentUUI, exfriendID);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//else They're both foreigners! Can't handle this
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private string GetUUI(UUID localUser, UUID foreignUser)
|
||||
{
|
||||
// Let's see if the user is here by any chance
|
||||
FriendInfo[] finfos = GetFriends(localUser);
|
||||
if (finfos != EMPTY_FRIENDS) // friend is here, cool
|
||||
{
|
||||
FriendInfo finfo = GetFriend(finfos, foreignUser);
|
||||
if (finfo != null)
|
||||
{
|
||||
return finfo.Friend;
|
||||
}
|
||||
}
|
||||
else // user is not currently on this sim, need to get from the service
|
||||
{
|
||||
finfos = FriendsService.GetFriends(localUser);
|
||||
foreach (FriendInfo finfo in finfos)
|
||||
{
|
||||
if (finfo.Friend.StartsWith(foreignUser.ToString())) // found it!
|
||||
{
|
||||
return finfo.Friend;
|
||||
}
|
||||
}
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private void Delete(UUID foreignUser, UUID localUser, string uui)
|
||||
{
|
||||
UUID id;
|
||||
string url = string.Empty, secret = string.Empty, tmp = string.Empty;
|
||||
if (Util.ParseUniversalUserIdentifier(uui, out id, out url, out tmp, out tmp, out secret))
|
||||
{
|
||||
m_log.DebugFormat("[HGFRIENDS MODULE]: Deleting friendship from {0}", url);
|
||||
HGFriendsServicesConnector friendConn = new HGFriendsServicesConnector(url);
|
||||
friendConn.DeleteFriendship(foreignUser, localUser, secret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
using Nwc.XmlRpc;
|
||||
using Mono.Addins;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||
using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using OpenSim.Services.Connectors.InstantMessage;
|
||||
using OpenSim.Services.Connectors.Hypergrid;
|
||||
using OpenSim.Server.Handlers.Hypergrid;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
|
||||
{
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
|
||||
public class HGMessageTransferModule : ISharedRegionModule, IMessageTransferModule, IInstantMessageSimConnector
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
protected bool m_Enabled = false;
|
||||
protected List<Scene> m_Scenes = new List<Scene>();
|
||||
|
||||
protected IInstantMessage m_IMService;
|
||||
protected Dictionary<UUID, object> m_UserLocationMap = new Dictionary<UUID, object>();
|
||||
|
||||
public event UndeliveredMessage OnUndeliveredMessage;
|
||||
|
||||
IUserManagement m_uMan;
|
||||
IUserManagement UserManagementModule
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_uMan == null)
|
||||
m_uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
|
||||
return m_uMan;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Initialise(IConfigSource config)
|
||||
{
|
||||
IConfig cnf = config.Configs["Messaging"];
|
||||
if (cnf != null && cnf.GetString(
|
||||
"MessageTransferModule", "MessageTransferModule") != Name)
|
||||
{
|
||||
m_log.Debug("[HG MESSAGE TRANSFER]: Disabled by configuration");
|
||||
return;
|
||||
}
|
||||
|
||||
InstantMessageServerConnector imServer = new InstantMessageServerConnector(config, MainServer.Instance, this);
|
||||
m_IMService = imServer.GetService();
|
||||
m_Enabled = true;
|
||||
}
|
||||
|
||||
public virtual void AddRegion(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
lock (m_Scenes)
|
||||
{
|
||||
m_log.DebugFormat("[HG MESSAGE TRANSFER]: Message transfer module {0} active", Name);
|
||||
scene.RegisterModuleInterface<IMessageTransferModule>(this);
|
||||
m_Scenes.Add(scene);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void PostInitialise()
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
public virtual void RegionLoaded(Scene scene)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void RemoveRegion(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
lock (m_Scenes)
|
||||
{
|
||||
m_Scenes.Remove(scene);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Close()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual string Name
|
||||
{
|
||||
get { return "HGMessageTransferModule"; }
|
||||
}
|
||||
|
||||
public virtual Type ReplaceableInterface
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public void SendInstantMessage(GridInstantMessage im, MessageResultNotification result)
|
||||
{
|
||||
UUID toAgentID = new UUID(im.toAgentID);
|
||||
|
||||
// Try root avatar only first
|
||||
foreach (Scene scene in m_Scenes)
|
||||
{
|
||||
if (scene.Entities.ContainsKey(toAgentID) &&
|
||||
scene.Entities[toAgentID] is ScenePresence)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
|
||||
// toAgentID.ToString(), scene.RegionInfo.RegionName);
|
||||
|
||||
ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
|
||||
if (!user.IsChildAgent)
|
||||
{
|
||||
// Local message
|
||||
// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID);
|
||||
user.ControllingClient.SendInstantMessage(im);
|
||||
|
||||
// Message sent
|
||||
result(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// try child avatar second
|
||||
foreach (Scene scene in m_Scenes)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
|
||||
|
||||
if (scene.Entities.ContainsKey(toAgentID) &&
|
||||
scene.Entities[toAgentID] is ScenePresence)
|
||||
{
|
||||
// Local message
|
||||
ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
|
||||
|
||||
// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID);
|
||||
user.ControllingClient.SendInstantMessage(im);
|
||||
|
||||
// Message sent
|
||||
result(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
|
||||
// Is the user a local user?
|
||||
UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, toAgentID);
|
||||
string url = string.Empty;
|
||||
bool foreigner = false;
|
||||
if (account == null) // foreign user
|
||||
{
|
||||
url = UserManagementModule.GetUserServerURL(toAgentID, "IMServerURI");
|
||||
foreigner = true;
|
||||
}
|
||||
|
||||
Util.FireAndForget(delegate
|
||||
{
|
||||
bool success = false;
|
||||
if (foreigner && url == string.Empty) // we don't know about this user
|
||||
{
|
||||
string recipientUUI = TryGetRecipientUUI(new UUID(im.fromAgentID), toAgentID);
|
||||
m_log.DebugFormat("[HG MESSAGE TRANSFER]: Got UUI {0}", recipientUUI);
|
||||
if (recipientUUI != string.Empty)
|
||||
{
|
||||
UUID id; string u = string.Empty, first = string.Empty, last = string.Empty, secret = string.Empty;
|
||||
if (Util.ParseUniversalUserIdentifier(recipientUUI, out id, out u, out first, out last, out secret))
|
||||
{
|
||||
success = m_IMService.OutgoingInstantMessage(im, u, true);
|
||||
if (success)
|
||||
UserManagementModule.AddUser(toAgentID, u + ";" + first + " " + last);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
success = m_IMService.OutgoingInstantMessage(im, url, foreigner);
|
||||
|
||||
if (!success && !foreigner)
|
||||
HandleUndeliveredMessage(im, result);
|
||||
else
|
||||
result(success);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
protected bool SendIMToScene(GridInstantMessage gim, UUID toAgentID)
|
||||
{
|
||||
bool successful = false;
|
||||
foreach (Scene scene in m_Scenes)
|
||||
{
|
||||
if (scene.Entities.ContainsKey(toAgentID) &&
|
||||
scene.Entities[toAgentID] is ScenePresence)
|
||||
{
|
||||
ScenePresence user =
|
||||
(ScenePresence)scene.Entities[toAgentID];
|
||||
|
||||
if (!user.IsChildAgent)
|
||||
{
|
||||
scene.EventManager.TriggerIncomingInstantMessage(gim);
|
||||
successful = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!successful)
|
||||
{
|
||||
// If the message can't be delivered to an agent, it
|
||||
// is likely to be a group IM. On a group IM, the
|
||||
// imSessionID = toAgentID = group id. Raise the
|
||||
// unhandled IM event to give the groups module
|
||||
// a chance to pick it up. We raise that in a random
|
||||
// scene, since the groups module is shared.
|
||||
//
|
||||
m_Scenes[0].EventManager.TriggerUnhandledInstantMessage(gim);
|
||||
}
|
||||
|
||||
return successful;
|
||||
}
|
||||
|
||||
protected void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result)
|
||||
{
|
||||
UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage;
|
||||
|
||||
// If this event has handlers, then an IM from an agent will be
|
||||
// considered delivered. This will suppress the error message.
|
||||
//
|
||||
if (handlerUndeliveredMessage != null)
|
||||
{
|
||||
handlerUndeliveredMessage(im);
|
||||
if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
|
||||
result(true);
|
||||
else
|
||||
result(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//m_log.DebugFormat("[INSTANT MESSAGE]: Undeliverable");
|
||||
result(false);
|
||||
}
|
||||
|
||||
private string TryGetRecipientUUI(UUID fromAgent, UUID toAgent)
|
||||
{
|
||||
// Let's call back the fromAgent's user agent service
|
||||
// Maybe that service knows about the toAgent
|
||||
IClientAPI client = LocateClientObject(fromAgent);
|
||||
if (client != null)
|
||||
{
|
||||
AgentCircuitData circuit = m_Scenes[0].AuthenticateHandler.GetAgentCircuitData(client.AgentId);
|
||||
if (circuit != null)
|
||||
{
|
||||
if (circuit.ServiceURLs.ContainsKey("HomeURI"))
|
||||
{
|
||||
string uasURL = circuit.ServiceURLs["HomeURI"].ToString();
|
||||
m_log.DebugFormat("[HG MESSAGE TRANSFER]: getting UUI of user {0} from {1}", toAgent, uasURL);
|
||||
UserAgentServiceConnector uasConn = new UserAgentServiceConnector(uasURL);
|
||||
return uasConn.GetUUI(fromAgent, toAgent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Find the scene for an agent
|
||||
/// </summary>
|
||||
private Scene GetClientScene(UUID agentId)
|
||||
{
|
||||
lock (m_Scenes)
|
||||
{
|
||||
foreach (Scene scene in m_Scenes)
|
||||
{
|
||||
ScenePresence presence = scene.GetScenePresence(agentId);
|
||||
if (presence != null && !presence.IsChildAgent)
|
||||
return scene;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the client for a ID
|
||||
/// </summary>
|
||||
public IClientAPI LocateClientObject(UUID agentID)
|
||||
{
|
||||
Scene scene = GetClientScene(agentID);
|
||||
if (scene != null)
|
||||
{
|
||||
ScenePresence presence = scene.GetScenePresence(agentID);
|
||||
if (presence != null)
|
||||
return presence.ControllingClient;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#region IInstantMessageSimConnector
|
||||
public bool SendInstantMessage(GridInstantMessage im)
|
||||
{
|
||||
//m_log.DebugFormat("[XXX] Hook SendInstantMessage {0}", im.message);
|
||||
UUID agentID = new UUID(im.toAgentID);
|
||||
return SendIMToScene(im, agentID);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -149,14 +149,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
|
||||
|
||||
/// <summary>
|
||||
/// Find an item given a PATH_DELIMITOR delimited path starting from the user's root folder.
|
||||
///
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method does not handle paths that contain multiple delimitors
|
||||
///
|
||||
/// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some
|
||||
/// XPath like expression
|
||||
///
|
||||
/// FIXME: Delimitors which occur in names themselves are not currently escapable.
|
||||
/// </summary>
|
||||
/// </remarks>
|
||||
///
|
||||
/// <param name="inventoryService">
|
||||
/// Inventory service to query
|
||||
@@ -178,32 +179,66 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
|
||||
|
||||
return FindItemByPath(inventoryService, rootFolder, path);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Find an item given a PATH_DELIMITOR delimited path starting from this folder.
|
||||
///
|
||||
/// This method does not handle paths that contain multiple delimitors
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method does not handle paths that contain multiple delimiters
|
||||
///
|
||||
/// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some
|
||||
/// XPath like expression
|
||||
///
|
||||
/// FIXME: Delimitors which occur in names themselves are not currently escapable.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="inventoryService">
|
||||
/// Inventory service to query
|
||||
/// </param>
|
||||
/// <param name="startFolder">
|
||||
/// The folder from which the path starts
|
||||
/// </param>
|
||||
/// <param name="path">
|
||||
/// <param name="path">
|
||||
/// The path to the required item.
|
||||
/// </param>
|
||||
/// </remarks>
|
||||
///
|
||||
/// <param name="inventoryService">Inventory service to query</param>
|
||||
/// <param name="startFolder">The folder from which the path starts</param>
|
||||
/// <param name="path">The path to the required item.</param>
|
||||
/// <returns>null if the item is not found</returns>
|
||||
public static InventoryItemBase FindItemByPath(
|
||||
IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
|
||||
{
|
||||
List<InventoryItemBase> foundItems = FindItemsByPath(inventoryService, startFolder, path);
|
||||
|
||||
if (foundItems.Count != 0)
|
||||
return foundItems[0];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<InventoryItemBase> FindItemsByPath(
|
||||
IInventoryService inventoryService, UUID userId, string path)
|
||||
{
|
||||
InventoryFolderBase rootFolder = inventoryService.GetRootFolder(userId);
|
||||
|
||||
if (null == rootFolder)
|
||||
return new List<InventoryItemBase>();
|
||||
|
||||
return FindItemsByPath(inventoryService, rootFolder, path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find items that match a given PATH_DELIMITOR delimited path starting from this folder.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method does not handle paths that contain multiple delimiters
|
||||
///
|
||||
/// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some
|
||||
/// XPath like expression
|
||||
///
|
||||
/// FIXME: Delimitors which occur in names themselves are not currently escapable.
|
||||
/// </remarks>
|
||||
///
|
||||
/// <param name="inventoryService">Inventory service to query</param>
|
||||
/// <param name="startFolder">The folder from which the path starts</param>
|
||||
/// <param name="path">The path to the required item.</param>
|
||||
/// <returns>The items that were found with this path. An empty list if no items were found.</returns>
|
||||
public static List<InventoryItemBase> FindItemsByPath(
|
||||
IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
|
||||
{
|
||||
List<InventoryItemBase> foundItems = new List<InventoryItemBase>();
|
||||
|
||||
// If the path isn't just / then trim any starting extraneous slashes
|
||||
path = path.TrimStart(new char[] { PATH_DELIMITER });
|
||||
|
||||
@@ -215,11 +250,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
|
||||
if (components.Length == 1)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}",
|
||||
// "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}",
|
||||
// components[0], startFolder.Name, startFolder.ID);
|
||||
|
||||
List<InventoryItemBase> items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID);
|
||||
|
||||
|
||||
// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Found {0} items in FindItemByPath()", items.Count);
|
||||
|
||||
foreach (InventoryItemBase item in items)
|
||||
@@ -227,24 +262,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
|
||||
// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Inspecting item {0} {1}", item.Name, item.ID);
|
||||
|
||||
if (item.Name == components[0])
|
||||
return item;
|
||||
foundItems.Add(item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// m_log.DebugFormat("FOUND COMPONENTS [{0}] and [{1}]", components[0], components[1]);
|
||||
|
||||
|
||||
InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID);
|
||||
|
||||
foreach (InventoryFolderBase folder in contents.Folders)
|
||||
{
|
||||
if (folder.Name == components[0])
|
||||
return FindItemByPath(inventoryService, folder, components[1]);
|
||||
foundItems.AddRange(FindItemsByPath(inventoryService, folder, components[1]));
|
||||
}
|
||||
}
|
||||
|
||||
// We didn't find an item or intermediate folder with the given name
|
||||
return null;
|
||||
return foundItems;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -154,7 +154,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
|
||||
string serialization = UserInventoryItemSerializer.Serialize(inventoryItem, options, userAccountService);
|
||||
m_archiveWriter.WriteFile(filename, serialization);
|
||||
|
||||
if (SaveAssets)
|
||||
AssetType itemAssetType = (AssetType)inventoryItem.AssetType;
|
||||
|
||||
// Don't chase down link asset items as they actually point to their target item IDs rather than an asset
|
||||
if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder)
|
||||
m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids);
|
||||
}
|
||||
|
||||
@@ -246,10 +249,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
|
||||
|
||||
// The path may point to an item instead
|
||||
if (inventoryFolder == null)
|
||||
{
|
||||
inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath);
|
||||
//inventoryItem = m_userInfo.RootFolder.FindItemByPath(m_invPath);
|
||||
}
|
||||
|
||||
if (null == inventoryFolder && null == inventoryItem)
|
||||
{
|
||||
|
||||
244
OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
Normal file
244
OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using Mono.Addins;
|
||||
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Services.Connectors.Hypergrid;
|
||||
|
||||
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.Avatar.Lure
|
||||
{
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
|
||||
public class HGLureModule : ISharedRegionModule
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(
|
||||
MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private readonly List<Scene> m_scenes = new List<Scene>();
|
||||
|
||||
private IMessageTransferModule m_TransferModule = null;
|
||||
private bool m_Enabled = false;
|
||||
|
||||
private string m_ThisGridURL;
|
||||
|
||||
private ExpiringCache<UUID, GridInstantMessage> m_PendingLures = new ExpiringCache<UUID, GridInstantMessage>();
|
||||
|
||||
public void Initialise(IConfigSource config)
|
||||
{
|
||||
if (config.Configs["Messaging"] != null)
|
||||
{
|
||||
if (config.Configs["Messaging"].GetString("LureModule", string.Empty) == "HGLureModule")
|
||||
{
|
||||
m_Enabled = true;
|
||||
|
||||
m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", string.Empty);
|
||||
m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddRegion(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
lock (m_scenes)
|
||||
{
|
||||
m_scenes.Add(scene);
|
||||
scene.EventManager.OnIncomingInstantMessage += OnIncomingInstantMessage;
|
||||
scene.EventManager.OnNewClient += OnNewClient;
|
||||
}
|
||||
}
|
||||
|
||||
public void RegionLoaded(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
if (m_TransferModule == null)
|
||||
{
|
||||
m_TransferModule =
|
||||
scene.RequestModuleInterface<IMessageTransferModule>();
|
||||
|
||||
if (m_TransferModule == null)
|
||||
{
|
||||
m_log.Error("[LURE MODULE]: No message transfer module, lures will not work!");
|
||||
|
||||
m_Enabled = false;
|
||||
m_scenes.Clear();
|
||||
scene.EventManager.OnNewClient -= OnNewClient;
|
||||
scene.EventManager.OnIncomingInstantMessage -= OnIncomingInstantMessage;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
lock (m_scenes)
|
||||
{
|
||||
m_scenes.Remove(scene);
|
||||
scene.EventManager.OnNewClient -= OnNewClient;
|
||||
scene.EventManager.OnIncomingInstantMessage -= OnIncomingInstantMessage;
|
||||
}
|
||||
}
|
||||
|
||||
void OnNewClient(IClientAPI client)
|
||||
{
|
||||
client.OnInstantMessage += OnInstantMessage;
|
||||
client.OnStartLure += OnStartLure;
|
||||
client.OnTeleportLureRequest += OnTeleportLureRequest;
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
{
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return "HGLureModule"; }
|
||||
}
|
||||
|
||||
public Type ReplaceableInterface
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
void OnInstantMessage(IClientAPI client, GridInstantMessage im)
|
||||
{
|
||||
}
|
||||
|
||||
void OnIncomingInstantMessage(GridInstantMessage im)
|
||||
{
|
||||
if (im.dialog == (byte)InstantMessageDialog.RequestTeleport)
|
||||
{
|
||||
UUID sessionID = new UUID(im.imSessionID);
|
||||
m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", im.imSessionID, im.RegionID, im.message);
|
||||
m_PendingLures.Add(sessionID, im, 7200); // 2 hours
|
||||
|
||||
// Forward. We do this, because the IM module explicitly rejects
|
||||
// IMs of this type
|
||||
if (m_TransferModule != null)
|
||||
m_TransferModule.SendInstantMessage(im, delegate(bool success) { });
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void OnStartLure(byte lureType, string message, UUID targetid, IClientAPI client)
|
||||
{
|
||||
if (!(client.Scene is Scene))
|
||||
return;
|
||||
|
||||
Scene scene = (Scene)(client.Scene);
|
||||
ScenePresence presence = scene.GetScenePresence(client.AgentId);
|
||||
|
||||
message += "@" + m_ThisGridURL;
|
||||
|
||||
m_log.DebugFormat("[HG LURE MODULE]: TP invite with message {0}", message);
|
||||
|
||||
GridInstantMessage m = new GridInstantMessage(scene, client.AgentId,
|
||||
client.FirstName+" "+client.LastName, targetid,
|
||||
(byte)InstantMessageDialog.RequestTeleport, false,
|
||||
message, UUID.Random(), false, presence.AbsolutePosition,
|
||||
new Byte[0]);
|
||||
m.RegionID = client.Scene.RegionInfo.RegionID.Guid;
|
||||
|
||||
if (m_TransferModule != null)
|
||||
{
|
||||
m_TransferModule.SendInstantMessage(m,
|
||||
delegate(bool success) { });
|
||||
}
|
||||
}
|
||||
|
||||
public void OnTeleportLureRequest(UUID lureID, uint teleportFlags, IClientAPI client)
|
||||
{
|
||||
if (!(client.Scene is Scene))
|
||||
return;
|
||||
|
||||
Scene scene = (Scene)(client.Scene);
|
||||
|
||||
GridInstantMessage im = null;
|
||||
if (m_PendingLures.TryGetValue(lureID, out im))
|
||||
{
|
||||
m_PendingLures.Remove(lureID);
|
||||
Lure(client, teleportFlags, im);
|
||||
}
|
||||
else
|
||||
m_log.DebugFormat("[HG LURE MODULE]: pending lure {0} not found", lureID);
|
||||
|
||||
}
|
||||
|
||||
private void Lure(IClientAPI client, uint teleportflags, GridInstantMessage im)
|
||||
{
|
||||
Scene scene = (Scene)(client.Scene);
|
||||
GridRegion region = scene.GridService.GetRegionByUUID(scene.RegionInfo.ScopeID, new UUID(im.RegionID));
|
||||
if (region != null)
|
||||
scene.RequestTeleportLocation(client, region.RegionHandle, im.Position + new Vector3(0.5f, 0.5f, 0f), Vector3.UnitX, teleportflags);
|
||||
else // we don't have that region here. Check if it's HG
|
||||
{
|
||||
string[] parts = im.message.Split(new char[] { '@' });
|
||||
if (parts.Length > 1)
|
||||
{
|
||||
string url = parts[parts.Length - 1]; // the last part
|
||||
if (url.Trim(new char[] {'/'}) != m_ThisGridURL.Trim(new char[] {'/'}))
|
||||
{
|
||||
m_log.DebugFormat("[HG LURE MODULE]: Luring agent to grid {0} region {1} position {2}", url, im.RegionID, im.Position);
|
||||
GatekeeperServiceConnector gConn = new GatekeeperServiceConnector();
|
||||
GridRegion gatekeeper = new GridRegion();
|
||||
gatekeeper.ServerURI = url;
|
||||
GridRegion finalDestination = gConn.GetHyperlinkRegion(gatekeeper, new UUID(im.RegionID));
|
||||
if (finalDestination != null)
|
||||
{
|
||||
ScenePresence sp = scene.GetScenePresence(client.AgentId);
|
||||
IEntityTransferModule transferMod = scene.RequestModuleInterface<IEntityTransferModule>();
|
||||
IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
|
||||
if (transferMod != null && sp != null && eq != null)
|
||||
transferMod.DoTeleport(sp, gatekeeper, finalDestination, im.Position + new Vector3(0.5f, 0.5f, 0f), Vector3.UnitX, teleportflags, eq);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,16 +45,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
|
||||
private readonly List<Scene> m_scenes = new List<Scene>();
|
||||
|
||||
private IMessageTransferModule m_TransferModule = null;
|
||||
private bool m_Enabled = true;
|
||||
private bool m_Enabled = false;
|
||||
|
||||
public void Initialise(IConfigSource config)
|
||||
{
|
||||
if (config.Configs["Messaging"] != null)
|
||||
{
|
||||
if (config.Configs["Messaging"].GetString(
|
||||
"LureModule", "LureModule") !=
|
||||
"LureModule", "LureModule") ==
|
||||
"LureModule")
|
||||
m_Enabled = false;
|
||||
{
|
||||
m_Enabled = true;
|
||||
m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +77,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
|
||||
|
||||
public void RegionLoaded(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
if (m_TransferModule == null)
|
||||
{
|
||||
m_TransferModule =
|
||||
@@ -96,6 +102,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
lock (m_scenes)
|
||||
{
|
||||
m_scenes.Remove(scene);
|
||||
|
||||
173
OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
Normal file
173
OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
|
||||
using OpenMetaverse;
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
using Mono.Addins;
|
||||
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Services.Interfaces;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.Avatar.Profile
|
||||
{
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
|
||||
public class BasicProfileModule : ISharedRegionModule
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
//
|
||||
// Module vars
|
||||
//
|
||||
private List<Scene> m_Scenes = new List<Scene>();
|
||||
private bool m_Enabled = false;
|
||||
|
||||
#region ISharedRegionModule
|
||||
|
||||
public void Initialise(IConfigSource config)
|
||||
{
|
||||
if (config.Configs["Profile"] != null)
|
||||
{
|
||||
if (config.Configs["Profile"].GetString("Module", string.Empty) != "BasicProfileModule")
|
||||
return;
|
||||
}
|
||||
|
||||
m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled");
|
||||
m_Enabled = true;
|
||||
|
||||
}
|
||||
|
||||
public void AddRegion(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
lock (m_Scenes)
|
||||
{
|
||||
if (!m_Scenes.Contains(scene))
|
||||
{
|
||||
m_Scenes.Add(scene);
|
||||
// Hook up events
|
||||
scene.EventManager.OnNewClient += OnNewClient;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RegionLoaded(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
lock (m_Scenes)
|
||||
{
|
||||
m_Scenes.Remove(scene);
|
||||
}
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
{
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return "BasicProfileModule"; }
|
||||
}
|
||||
|
||||
public Type ReplaceableInterface
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// New Client Event Handler
|
||||
private void OnNewClient(IClientAPI client)
|
||||
{
|
||||
//Profile
|
||||
client.OnRequestAvatarProperties += RequestAvatarProperties;
|
||||
}
|
||||
|
||||
public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
|
||||
{
|
||||
IScene s = remoteClient.Scene;
|
||||
if (!(s is Scene))
|
||||
return;
|
||||
|
||||
Scene scene = (Scene)s;
|
||||
|
||||
string profileUrl = String.Empty;
|
||||
string aboutText = String.Empty;
|
||||
string firstLifeAboutText = String.Empty;
|
||||
UUID image = UUID.Zero;
|
||||
UUID firstLifeImage = UUID.Zero;
|
||||
UUID partner = UUID.Zero;
|
||||
uint wantMask = 0;
|
||||
string wantText = String.Empty;
|
||||
uint skillsMask = 0;
|
||||
string skillsText = String.Empty;
|
||||
string languages = String.Empty;
|
||||
|
||||
Byte[] charterMember = Utils.StringToBytes("Avatar");
|
||||
|
||||
profileUrl = "No profile data";
|
||||
aboutText = string.Empty;
|
||||
firstLifeAboutText = string.Empty;
|
||||
image = UUID.Zero;
|
||||
firstLifeImage = UUID.Zero;
|
||||
partner = UUID.Zero;
|
||||
|
||||
remoteClient.SendAvatarProperties(avatarID, aboutText,
|
||||
Util.ToDateTime(0).ToString(
|
||||
"M/d/yyyy", CultureInfo.InvariantCulture),
|
||||
charterMember, firstLifeAboutText,
|
||||
(uint)(0 & 0xff),
|
||||
firstLifeImage, image, profileUrl, partner);
|
||||
|
||||
//Viewer expects interest data when it asks for properties.
|
||||
remoteClient.SendAvatarInterestsReply(avatarID, wantMask, wantText,
|
||||
skillsMask, skillsText, languages);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
|
||||
protected bool m_Enabled = false;
|
||||
protected Scene m_aScene;
|
||||
protected List<Scene> m_Scenes = new List<Scene>();
|
||||
protected List<UUID> m_agentsInTransit;
|
||||
private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions =
|
||||
new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
|
||||
@@ -96,13 +97,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
if (m_aScene == null)
|
||||
m_aScene = scene;
|
||||
|
||||
m_Scenes.Add(scene);
|
||||
scene.RegisterModuleInterface<IEntityTransferModule>(this);
|
||||
scene.EventManager.OnNewClient += OnNewClient;
|
||||
}
|
||||
|
||||
protected virtual void OnNewClient(IClientAPI client)
|
||||
{
|
||||
client.OnTeleportHomeRequest += TeleportHomeFired;
|
||||
client.OnTeleportHomeRequest += TriggerTeleportHome;
|
||||
client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
|
||||
}
|
||||
|
||||
public virtual void Close()
|
||||
@@ -118,6 +121,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
return;
|
||||
if (scene == m_aScene)
|
||||
m_aScene = null;
|
||||
|
||||
m_Scenes.Remove(scene);
|
||||
}
|
||||
|
||||
public virtual void RegionLoaded(Scene scene)
|
||||
@@ -127,7 +132,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Agent Teleports
|
||||
@@ -249,7 +253,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
}
|
||||
}
|
||||
|
||||
protected void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq)
|
||||
public void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq)
|
||||
{
|
||||
if (reg == null || finalDestination == null)
|
||||
{
|
||||
@@ -557,9 +561,32 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
|
||||
#endregion
|
||||
|
||||
#region Landmark Teleport
|
||||
/// <summary>
|
||||
/// Tries to teleport agent to landmark.
|
||||
/// </summary>
|
||||
/// <param name="remoteClient"></param>
|
||||
/// <param name="regionHandle"></param>
|
||||
/// <param name="position"></param>
|
||||
public virtual void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm)
|
||||
{
|
||||
GridRegion info = m_aScene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
|
||||
|
||||
if (info == null)
|
||||
{
|
||||
// can't find the region: Tell viewer and abort
|
||||
remoteClient.SendTeleportFailed("The teleport destination could not be found.");
|
||||
return;
|
||||
}
|
||||
((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position,
|
||||
Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Teleport Home
|
||||
|
||||
public void TeleportHomeFired(UUID id, IClientAPI client)
|
||||
public virtual void TriggerTeleportHome(UUID id, IClientAPI client)
|
||||
{
|
||||
TeleportHome(id, client);
|
||||
}
|
||||
|
||||
@@ -86,7 +86,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
|
||||
protected override void OnNewClient(IClientAPI client)
|
||||
{
|
||||
client.OnTeleportHomeRequest += TeleportHomeFired;
|
||||
client.OnTeleportHomeRequest += TriggerTeleportHome;
|
||||
client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
|
||||
client.OnConnectionClosed += new Action<IClientAPI>(OnConnectionClosed);
|
||||
}
|
||||
|
||||
@@ -178,7 +179,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
return m_aScene.SimulationService.CreateAgent(reg, agentCircuit, teleportFlags, out reason);
|
||||
}
|
||||
|
||||
public void TeleportHomeFired(UUID id, IClientAPI client)
|
||||
public void TriggerTeleportHome(UUID id, IClientAPI client)
|
||||
{
|
||||
TeleportHome(id, client);
|
||||
}
|
||||
@@ -233,6 +234,58 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome), eq);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to teleport agent to landmark.
|
||||
/// </summary>
|
||||
/// <param name="remoteClient"></param>
|
||||
/// <param name="regionHandle"></param>
|
||||
/// <param name="position"></param>
|
||||
public override void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm)
|
||||
{
|
||||
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Teleporting agent via landmark to {0} region {1} position {2}",
|
||||
(lm.Gatekeeper == string.Empty) ? "local" : lm.Gatekeeper, lm.RegionID, lm.Position);
|
||||
if (lm.Gatekeeper == string.Empty)
|
||||
{
|
||||
base.RequestTeleportLandmark(remoteClient, lm);
|
||||
return;
|
||||
}
|
||||
|
||||
GridRegion info = m_aScene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
|
||||
|
||||
// Local region?
|
||||
if (info != null)
|
||||
{
|
||||
((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position,
|
||||
Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Foreign region
|
||||
Scene scene = (Scene)(remoteClient.Scene);
|
||||
GatekeeperServiceConnector gConn = new GatekeeperServiceConnector();
|
||||
GridRegion gatekeeper = new GridRegion();
|
||||
gatekeeper.ServerURI = lm.Gatekeeper;
|
||||
GridRegion finalDestination = gConn.GetHyperlinkRegion(gatekeeper, new UUID(lm.RegionID));
|
||||
if (finalDestination != null)
|
||||
{
|
||||
ScenePresence sp = scene.GetScenePresence(remoteClient.AgentId);
|
||||
IEntityTransferModule transferMod = scene.RequestModuleInterface<IEntityTransferModule>();
|
||||
IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
|
||||
if (transferMod != null && sp != null && eq != null)
|
||||
transferMod.DoTeleport(sp, gatekeeper, finalDestination, lm.Position,
|
||||
Vector3.UnitX, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark), eq);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// can't find the region: Tell viewer and abort
|
||||
remoteClient.SendTeleportFailed("The teleport destination could not be found.");
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region IUserAgentVerificationModule
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
|
||||
private string m_ProfileServerURI;
|
||||
private bool m_OutboundPermission;
|
||||
private string m_ThisGatekeeper;
|
||||
|
||||
// private bool m_Initialized = false;
|
||||
|
||||
@@ -85,6 +86,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
{
|
||||
m_ProfileServerURI = thisModuleConfig.GetString("ProfileServerURI", string.Empty);
|
||||
m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true);
|
||||
m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty);
|
||||
}
|
||||
else
|
||||
m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!");
|
||||
@@ -110,7 +112,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel)
|
||||
{
|
||||
string userAssetServer = string.Empty;
|
||||
if (IsForeignUser(avatarID, out userAssetServer) && m_OutboundPermission)
|
||||
if (IsForeignUser(avatarID, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission)
|
||||
{
|
||||
Util.FireAndForget(delegate { m_assMapper.Post(assetID, avatarID, userAssetServer); });
|
||||
}
|
||||
@@ -119,6 +121,24 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
#endregion
|
||||
|
||||
#region Overrides of Basic Inventory Access methods
|
||||
|
||||
protected override string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix)
|
||||
{
|
||||
UserAccount account = m_Scene.UserAccountService.GetUserAccount(m_Scene.RegionInfo.ScopeID, presence.UUID);
|
||||
if (account == null)
|
||||
prefix = "HG ";
|
||||
else
|
||||
prefix = string.Empty;
|
||||
suffix = " @ " + m_ThisGatekeeper;
|
||||
Vector3 pos = presence.AbsolutePosition;
|
||||
return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\ngatekeeper {5}\n",
|
||||
presence.Scene.RegionInfo.RegionID,
|
||||
pos.X, pos.Y, pos.Z,
|
||||
presence.RegionHandle,
|
||||
m_ThisGatekeeper);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// CapsUpdateInventoryItemAsset
|
||||
///
|
||||
@@ -180,10 +200,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
public override void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver)
|
||||
{
|
||||
string userAssetServer = string.Empty;
|
||||
if (IsForeignUser(sender, out userAssetServer))
|
||||
if (IsForeignUser(sender, out userAssetServer) && userAssetServer != string.Empty)
|
||||
m_assMapper.Get(item.AssetID, sender, userAssetServer);
|
||||
|
||||
if (IsForeignUser(receiver, out userAssetServer) && m_OutboundPermission)
|
||||
if (IsForeignUser(receiver, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission)
|
||||
m_assMapper.Post(item.AssetID, receiver, userAssetServer);
|
||||
}
|
||||
|
||||
@@ -203,9 +223,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
if (aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
|
||||
{
|
||||
assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString();
|
||||
assetServerURL = assetServerURL.Trim(new char[] { '/' }); return true;
|
||||
assetServerURL = assetServerURL.Trim(new char[] { '/' });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assetServerURL = UserManagementModule.GetUserServerURL(userID, "AssetServerURI");
|
||||
assetServerURL = assetServerURL.Trim(new char[] { '/' });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -30,6 +30,7 @@ using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Xml;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
using OpenSim.Framework;
|
||||
@@ -128,7 +129,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
|
||||
protected virtual void OnNewClient(IClientAPI client)
|
||||
{
|
||||
|
||||
client.OnCreateNewInventoryItem += CreateNewInventoryItem;
|
||||
}
|
||||
|
||||
public virtual void Close()
|
||||
@@ -156,6 +157,87 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
|
||||
#region Inventory Access
|
||||
|
||||
/// <summary>
|
||||
/// Create a new inventory item. Called when the client creates a new item directly within their
|
||||
/// inventory (e.g. by selecting a context inventory menu option).
|
||||
/// </summary>
|
||||
/// <param name="remoteClient"></param>
|
||||
/// <param name="transactionID"></param>
|
||||
/// <param name="folderID"></param>
|
||||
/// <param name="callbackID"></param>
|
||||
/// <param name="description"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="invType"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="wearableType"></param>
|
||||
/// <param name="nextOwnerMask"></param>
|
||||
public void CreateNewInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID,
|
||||
uint callbackID, string description, string name, sbyte invType,
|
||||
sbyte assetType,
|
||||
byte wearableType, uint nextOwnerMask, int creationDate)
|
||||
{
|
||||
m_log.DebugFormat("[AGENT INVENTORY]: Received request to create inventory item {0} in folder {1}", name, folderID);
|
||||
|
||||
if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId))
|
||||
return;
|
||||
|
||||
InventoryFolderBase f = new InventoryFolderBase(folderID, remoteClient.AgentId);
|
||||
InventoryFolderBase folder = m_Scene.InventoryService.GetFolder(f);
|
||||
|
||||
if (folder == null || folder.Owner != remoteClient.AgentId)
|
||||
return;
|
||||
|
||||
if (transactionID == UUID.Zero)
|
||||
{
|
||||
ScenePresence presence;
|
||||
if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence))
|
||||
{
|
||||
byte[] data = null;
|
||||
|
||||
if (invType == (sbyte)InventoryType.Landmark && presence != null)
|
||||
{
|
||||
string suffix = string.Empty, prefix = string.Empty;
|
||||
string strdata = GenerateLandmark(presence, out prefix, out suffix);
|
||||
data = Encoding.ASCII.GetBytes(strdata);
|
||||
name = prefix + name;
|
||||
description += suffix;
|
||||
}
|
||||
|
||||
AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId);
|
||||
m_Scene.AssetService.Store(asset);
|
||||
|
||||
m_Scene.CreateNewInventoryItem(remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, asset.Name, 0, callbackID, asset, invType, nextOwnerMask, creationDate);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem",
|
||||
remoteClient.AgentId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IAgentAssetTransactions agentTransactions = m_Scene.RequestModuleInterface<IAgentAssetTransactions>();
|
||||
if (agentTransactions != null)
|
||||
{
|
||||
agentTransactions.HandleItemCreationFromTransaction(
|
||||
remoteClient, transactionID, folderID, callbackID, description,
|
||||
name, invType, assetType, wearableType, nextOwnerMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix)
|
||||
{
|
||||
prefix = string.Empty;
|
||||
suffix = string.Empty;
|
||||
Vector3 pos = presence.AbsolutePosition;
|
||||
return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\n",
|
||||
presence.Scene.RegionInfo.RegionID,
|
||||
pos.X, pos.Y, pos.Z,
|
||||
presence.RegionHandle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Capability originating call to update the asset of an item in an agent's inventory
|
||||
/// </summary>
|
||||
|
||||
@@ -30,11 +30,13 @@ using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Console;
|
||||
|
||||
using OpenSim.Region.Framework;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using OpenSim.Services.Connectors.Hypergrid;
|
||||
|
||||
using OpenMetaverse;
|
||||
using log4net;
|
||||
@@ -47,7 +49,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||
public UUID Id;
|
||||
public string FirstName;
|
||||
public string LastName;
|
||||
public string ProfileURL;
|
||||
public string HomeURL;
|
||||
public Dictionary<string, object> ServerURLs;
|
||||
}
|
||||
|
||||
public class UserManagementModule : ISharedRegionModule, IUserManagement
|
||||
@@ -78,6 +81,14 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
MainConsole.Instance.Commands.AddCommand("grid", true,
|
||||
"show user-names",
|
||||
"show user-names",
|
||||
"Show the bindings between user UUIDs and user names",
|
||||
String.Empty,
|
||||
HandleShowUsers);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public bool IsSharedModule
|
||||
@@ -101,6 +112,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||
|
||||
scene.RegisterModuleInterface<IUserManagement>(this);
|
||||
scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient);
|
||||
scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded);
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
@@ -109,18 +121,12 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||
m_Scenes.Remove(scene);
|
||||
}
|
||||
|
||||
public void RegionLoaded(Scene scene)
|
||||
public void RegionLoaded(Scene s)
|
||||
{
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
{
|
||||
foreach (Scene s in m_Scenes)
|
||||
{
|
||||
// let's sniff all the user names referenced by objects in the scene
|
||||
m_log.DebugFormat("[USER MANAGEMENT MODULE]: Caching creators' data from {0} ({1} objects)...", s.RegionInfo.RegionName, s.GetEntities().Length);
|
||||
s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); });
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
@@ -134,6 +140,14 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
void EventManager_OnPrimsLoaded(Scene s)
|
||||
{
|
||||
// let's sniff all the user names referenced by objects in the scene
|
||||
m_log.DebugFormat("[USER MANAGEMENT MODULE]: Caching creators' data from {0} ({1} objects)...", s.RegionInfo.RegionName, s.GetEntities().Length);
|
||||
s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); });
|
||||
}
|
||||
|
||||
|
||||
void EventManager_OnNewClient(IClientAPI client)
|
||||
{
|
||||
client.OnNameFromUUIDRequest += new UUIDNameRequest(HandleUUIDNameRequest);
|
||||
@@ -150,6 +164,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||
string[] names = GetUserNames(uuid);
|
||||
if (names.Length == 2)
|
||||
{
|
||||
//m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0} is {1} {2}", uuid, names[0], names[1]);
|
||||
remote_client.SendNameReply(uuid, names[0], names[1]);
|
||||
}
|
||||
|
||||
@@ -210,6 +225,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||
|
||||
public string GetUserName(UUID uuid)
|
||||
{
|
||||
//m_log.DebugFormat("[XXX] GetUserName {0}", uuid);
|
||||
string[] names = GetUserNames(uuid);
|
||||
if (names.Length == 2)
|
||||
{
|
||||
@@ -222,6 +238,60 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||
return "(hippos)";
|
||||
}
|
||||
|
||||
public string GetUserHomeURL(UUID userID)
|
||||
{
|
||||
if (m_UserCache.ContainsKey(userID))
|
||||
return m_UserCache[userID].HomeURL;
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public string GetUserServerURL(UUID userID, string serverType)
|
||||
{
|
||||
if (m_UserCache.ContainsKey(userID))
|
||||
{
|
||||
UserData userdata = m_UserCache[userID];
|
||||
if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
|
||||
return userdata.ServerURLs[serverType].ToString();
|
||||
|
||||
if (userdata.HomeURL != string.Empty)
|
||||
{
|
||||
UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL);
|
||||
userdata.ServerURLs = uConn.GetServerURLs(userID);
|
||||
if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
|
||||
return userdata.ServerURLs[serverType].ToString();
|
||||
}
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public string GetUserUUI(UUID userID)
|
||||
{
|
||||
UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, userID);
|
||||
if (account != null)
|
||||
return userID.ToString();
|
||||
|
||||
if (m_UserCache.ContainsKey(userID))
|
||||
{
|
||||
UserData ud = m_UserCache[userID];
|
||||
string homeURL = ud.HomeURL;
|
||||
string first = ud.FirstName, last = ud.LastName;
|
||||
if (ud.LastName.StartsWith("@"))
|
||||
{
|
||||
string[] parts = ud.FirstName.Split('.');
|
||||
if (parts.Length >= 2)
|
||||
{
|
||||
first = parts[0];
|
||||
last = parts[1];
|
||||
}
|
||||
return userID + ";" + homeURL + ";" + first + " " + last;
|
||||
}
|
||||
}
|
||||
|
||||
return userID.ToString();
|
||||
}
|
||||
|
||||
public void AddUser(UUID id, string creatorData)
|
||||
{
|
||||
if (m_UserCache.ContainsKey(id))
|
||||
@@ -247,13 +317,13 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||
string[] parts = creatorData.Split(';');
|
||||
if (parts.Length >= 1)
|
||||
{
|
||||
user.ProfileURL = parts[0];
|
||||
user.HomeURL = parts[0];
|
||||
try
|
||||
{
|
||||
Uri uri = new Uri(parts[0]);
|
||||
user.LastName = "@" + uri.Authority;
|
||||
}
|
||||
catch
|
||||
catch (UriFormatException)
|
||||
{
|
||||
m_log.DebugFormat("[SCENE]: Unable to parse Uri {0}", parts[0]);
|
||||
user.LastName = "@unknown";
|
||||
@@ -272,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||
lock (m_UserCache)
|
||||
m_UserCache[id] = user;
|
||||
|
||||
m_log.DebugFormat("[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", user.Id, user.FirstName, user.LastName, user.ProfileURL);
|
||||
m_log.DebugFormat("[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", user.Id, user.FirstName, user.LastName, user.HomeURL);
|
||||
}
|
||||
|
||||
public void AddUser(UUID uuid, string first, string last, string profileURL)
|
||||
@@ -311,5 +381,25 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||
//}
|
||||
|
||||
#endregion IUserManagement
|
||||
|
||||
private void HandleShowUsers(string module, string[] cmd)
|
||||
{
|
||||
if (m_UserCache.Count == 0)
|
||||
{
|
||||
MainConsole.Instance.Output("No users not found");
|
||||
return;
|
||||
}
|
||||
|
||||
MainConsole.Instance.Output("UUID User Name");
|
||||
MainConsole.Instance.Output("-----------------------------------------------------------------------------");
|
||||
foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache)
|
||||
{
|
||||
MainConsole.Instance.Output(String.Format("{0} {1} {2}",
|
||||
kvp.Key, kvp.Value.FirstName, kvp.Value.LastName));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using log4net;
|
||||
@@ -67,9 +68,26 @@ namespace OpenSim.Region.CoreModules.Hypergrid
|
||||
|
||||
foreach (GridRegion r in regions)
|
||||
{
|
||||
MapBlockData block = new MapBlockData();
|
||||
MapBlockFromGridRegion(block, r);
|
||||
mapBlocks.Add(block);
|
||||
uint x = 0, y = 0;
|
||||
long handle = 0;
|
||||
if (r.RegionSecret != null && r.RegionSecret != string.Empty)
|
||||
{
|
||||
if (long.TryParse(r.RegionSecret, out handle))
|
||||
{
|
||||
Utils.LongToUInts((ulong)handle, out x, out y);
|
||||
x = x / Constants.RegionSize;
|
||||
y = y / Constants.RegionSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (handle == 0 ||
|
||||
// Check the distance from the current region
|
||||
(handle != 0 && Math.Abs((int)(x - m_scene.RegionInfo.RegionLocX)) < 4096 && Math.Abs((int)(y - m_scene.RegionInfo.RegionLocY)) < 4096))
|
||||
{
|
||||
MapBlockData block = new MapBlockData();
|
||||
MapBlockFromGridRegion(block, r);
|
||||
mapBlocks.Add(block);
|
||||
}
|
||||
}
|
||||
|
||||
// Different from super
|
||||
@@ -77,6 +95,7 @@ namespace OpenSim.Region.CoreModules.Hypergrid
|
||||
//
|
||||
|
||||
remoteClient.SendMapBlock(mapBlocks, 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
<RegionModule id="UrlModule" type="OpenSim.Region.CoreModules.Scripting.LSLHttp.UrlModule" />
|
||||
<RegionModule id="Chat" type="OpenSim.Region.CoreModules.Avatar.Chat.ChatModule" />
|
||||
<RegionModule id="FriendsModule" type="OpenSim.Region.CoreModules.Avatar.Friends.FriendsModule" />
|
||||
<RegionModule id="HGFriendsModule" type="OpenSim.Region.CoreModules.Avatar.Friends.HGFriendsModule" />
|
||||
<RegionModule id="PresenceModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.PresenceModule" />
|
||||
<RegionModule id="MuteListModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.MuteListModule" />
|
||||
<RegionModule id="OfflineMessageModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.OfflineMessageModule" />
|
||||
|
||||
@@ -113,8 +113,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
|
||||
ISimulationService simService = scene.RequestModuleInterface<ISimulationService>();
|
||||
m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService);
|
||||
|
||||
new UserAgentServerConnector(m_Config, MainServer.Instance);
|
||||
IFriendsSimConnector friendsConn = scene.RequestModuleInterface<IFriendsSimConnector>();
|
||||
new UserAgentServerConnector(m_Config, MainServer.Instance, friendsConn);
|
||||
new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService");
|
||||
new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService");
|
||||
}
|
||||
scene.RegisterModuleInterface<IGatekeeperService>(m_HypergridHandler.GateKeeper);
|
||||
}
|
||||
|
||||
@@ -58,6 +58,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
||||
|
||||
private List<Scene> m_Scenes = new List<Scene>();
|
||||
|
||||
protected IUserManagement m_UserManagement;
|
||||
protected IUserManagement UserManagementModule
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_UserManagement == null)
|
||||
m_UserManagement = m_Scenes[0].RequestModuleInterface<IUserManagement>();
|
||||
return m_UserManagement;
|
||||
}
|
||||
}
|
||||
|
||||
public Type ReplaceableInterface
|
||||
{
|
||||
get { return null; }
|
||||
@@ -207,6 +218,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sp == null)
|
||||
{
|
||||
inventoryURL = UserManagementModule.GetUserServerURL(userID, "InventoryServerURI");
|
||||
if (inventoryURL != null && inventoryURL != string.Empty)
|
||||
{
|
||||
inventoryURL = inventoryURL.Trim(new char[] { '/' });
|
||||
m_InventoryURLs.Add(userID, inventoryURL);
|
||||
m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Added {0} to the cache of inventory URLs", inventoryURL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -230,6 +230,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
/// <param name="asset"></param>
|
||||
public void AssetRequestCallback(string id, object sender, AssetBase asset)
|
||||
{
|
||||
Culture.SetCurrentCulture();
|
||||
|
||||
try
|
||||
{
|
||||
lock (this)
|
||||
@@ -289,6 +291,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
/// </summary>
|
||||
protected void PerformAssetsRequestCallback(object o)
|
||||
{
|
||||
Culture.SetCurrentCulture();
|
||||
|
||||
try
|
||||
{
|
||||
m_assetsRequestCallback(m_foundAssetUuids, m_notFoundAssetUuids);
|
||||
|
||||
@@ -548,18 +548,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions
|
||||
|
||||
// libomv will moan about PrimFlags.ObjectYouOfficer being
|
||||
// deprecated
|
||||
#pragma warning disable 0612
|
||||
#pragma warning disable 0612
|
||||
objflags &= (uint)
|
||||
~(PrimFlags.ObjectCopy | // Tells client you can copy the object
|
||||
PrimFlags.ObjectModify | // tells client you can modify the object
|
||||
PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod)
|
||||
PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it
|
||||
PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object
|
||||
PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object
|
||||
PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object
|
||||
PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set
|
||||
PrimFlags.ObjectModify | // tells client you can modify the object
|
||||
PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod)
|
||||
PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it
|
||||
PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object
|
||||
PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object
|
||||
PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object
|
||||
PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set
|
||||
);
|
||||
#pragma warning restore 0612
|
||||
#pragma warning restore 0612
|
||||
|
||||
// Creating the three ObjectFlags options for this method to choose from.
|
||||
// Customize the OwnerMask
|
||||
@@ -576,22 +576,27 @@ namespace OpenSim.Region.CoreModules.World.Permissions
|
||||
|
||||
if (m_bypassPermissions)
|
||||
return objectOwnerMask;
|
||||
|
||||
|
||||
// Object owners should be able to edit their own content
|
||||
if (user == objectOwner)
|
||||
return objectOwnerMask;
|
||||
|
||||
if (IsFriendWithPerms(user, objectOwner))
|
||||
return objectOwnerMask;
|
||||
|
||||
if (IsFriendWithPerms(user, objectOwner))
|
||||
{
|
||||
return objectOwnerMask;
|
||||
}
|
||||
// Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
|
||||
if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner))
|
||||
{
|
||||
return objectOwnerMask;
|
||||
}
|
||||
|
||||
// Admin should be able to edit anything in the sim (including admin objects)
|
||||
if (IsAdministrator(user))
|
||||
{
|
||||
return objectOwnerMask;
|
||||
|
||||
}
|
||||
|
||||
// Users should be able to edit what is over their land.
|
||||
Vector3 taskPos = task.AbsolutePosition;
|
||||
ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y);
|
||||
@@ -599,13 +604,15 @@ namespace OpenSim.Region.CoreModules.World.Permissions
|
||||
{
|
||||
// Admin objects should not be editable by the above
|
||||
if (!IsAdministrator(objectOwner))
|
||||
{
|
||||
return objectOwnerMask;
|
||||
}
|
||||
}
|
||||
|
||||
// Group permissions
|
||||
if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0))
|
||||
return objectGroupMask | objectEveryoneMask;
|
||||
|
||||
|
||||
return objectEveryoneMask;
|
||||
}
|
||||
|
||||
@@ -673,7 +680,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions
|
||||
//
|
||||
// Nobody but the object owner can set permissions on an object
|
||||
//
|
||||
|
||||
if (locked && (!IsAdministrator(currentUser)) && denyOnLocked)
|
||||
{
|
||||
return false;
|
||||
@@ -704,6 +710,11 @@ namespace OpenSim.Region.CoreModules.World.Permissions
|
||||
// Return immediately, so that the administrator can shares group objects
|
||||
return true;
|
||||
}
|
||||
|
||||
// Friends with benefits should be able to edit the objects too
|
||||
if (IsFriendWithPerms(currentUser, objectOwner))
|
||||
// Return immediately, so that the administrator can share objects with friends
|
||||
return true;
|
||||
|
||||
// Users should be able to edit what is over their land.
|
||||
ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y);
|
||||
|
||||
@@ -208,52 +208,65 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||
//m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}",
|
||||
// path, param, agentID.ToString());
|
||||
|
||||
// this is here because CAPS map requests work even beyond the 10,000 limit.
|
||||
ScenePresence avatarPresence = null;
|
||||
// There is a major hack going on in this method. The viewer doesn't request
|
||||
// map blocks (RequestMapBlocks) above 4096. That means that if we don't hack,
|
||||
// grids above that cell don't have a map at all. So, here's the hack: we wait
|
||||
// for this CAP request to come, and we inject the map blocks at this point.
|
||||
// In a normal scenario, this request simply sends back the MapLayer (the blue color).
|
||||
// In the hacked scenario, it also sends the map blocks via UDP.
|
||||
//
|
||||
// 6/8/2011 -- I'm adding an explicit 4096 check, so that we never forget that there is
|
||||
// a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks.
|
||||
|
||||
m_scene.TryGetScenePresence(agentID, out avatarPresence);
|
||||
|
||||
if (avatarPresence != null)
|
||||
if (m_scene.RegionInfo.RegionLocX >= 4096 || m_scene.RegionInfo.RegionLocY >= 4096)
|
||||
{
|
||||
bool lookup = false;
|
||||
ScenePresence avatarPresence = null;
|
||||
|
||||
lock (cachedMapBlocks)
|
||||
m_scene.TryGetScenePresence(agentID, out avatarPresence);
|
||||
|
||||
if (avatarPresence != null)
|
||||
{
|
||||
if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch()))
|
||||
{
|
||||
List<MapBlockData> mapBlocks;
|
||||
|
||||
mapBlocks = cachedMapBlocks;
|
||||
avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
lookup = true;
|
||||
}
|
||||
}
|
||||
if (lookup)
|
||||
{
|
||||
List<MapBlockData> mapBlocks = new List<MapBlockData>(); ;
|
||||
|
||||
List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
|
||||
(int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize,
|
||||
(int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize,
|
||||
(int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize,
|
||||
(int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize);
|
||||
foreach (GridRegion r in regions)
|
||||
{
|
||||
MapBlockData block = new MapBlockData();
|
||||
MapBlockFromGridRegion(block, r);
|
||||
mapBlocks.Add(block);
|
||||
}
|
||||
avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
|
||||
bool lookup = false;
|
||||
|
||||
lock (cachedMapBlocks)
|
||||
cachedMapBlocks = mapBlocks;
|
||||
{
|
||||
if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch()))
|
||||
{
|
||||
List<MapBlockData> mapBlocks;
|
||||
|
||||
cachedTime = Util.UnixTimeSinceEpoch();
|
||||
mapBlocks = cachedMapBlocks;
|
||||
avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
lookup = true;
|
||||
}
|
||||
}
|
||||
if (lookup)
|
||||
{
|
||||
List<MapBlockData> mapBlocks = new List<MapBlockData>(); ;
|
||||
|
||||
List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
|
||||
(int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize,
|
||||
(int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize,
|
||||
(int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize,
|
||||
(int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize);
|
||||
foreach (GridRegion r in regions)
|
||||
{
|
||||
MapBlockData block = new MapBlockData();
|
||||
MapBlockFromGridRegion(block, r);
|
||||
mapBlocks.Add(block);
|
||||
}
|
||||
avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
|
||||
|
||||
lock (cachedMapBlocks)
|
||||
cachedMapBlocks = mapBlocks;
|
||||
|
||||
cachedTime = Util.UnixTimeSinceEpoch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
|
||||
mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
|
||||
return mapResponse.ToString();
|
||||
|
||||
Reference in New Issue
Block a user