Skip to content

Commit

Permalink
Display Names (#94)
Browse files Browse the repository at this point in the history
Authored-by: StolenRuby <[email protected]>
Reviewed-by: Michael Dickson
  • Loading branch information
mdickson authored Sep 18, 2024
1 parent 4bb0209 commit 0e09536
Show file tree
Hide file tree
Showing 17 changed files with 495 additions and 31 deletions.
5 changes: 3 additions & 2 deletions OpenSim/Data/MySQL/MySQLUserAccountData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,16 @@ public UserAccountData[] GetUsers(UUID scopeID, string query)
{
if (words.Length == 1)
{
cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?search or LastName like ?search) and active=1", m_Realm);
cmd.CommandText = string.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?search or LastName like ?search or DisplayName like ?search) and active=1", m_Realm);
cmd.Parameters.AddWithValue("?search", "%" + words[0] + "%");
cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString());
}
else
{
cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?searchFirst and LastName like ?searchLast) and active=1", m_Realm);
cmd.CommandText = string.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?searchFirst and LastName like ?searchLast or DisplayName like ?searchDisplay) and active=1", m_Realm);
cmd.Parameters.AddWithValue("?searchFirst", "%" + words[0] + "%");
cmd.Parameters.AddWithValue("?searchLast", "%" + words[1] + "%");
cmd.Parameters.AddWithValue("?searchDisplay", "%" + query + "%");
cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString());
}

Expand Down
10 changes: 10 additions & 0 deletions OpenSim/Data/MySQL/Resources/UserAccount.migrations
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,13 @@ BEGIN;
ALTER TABLE `UserAccounts` ADD `active` INT NOT NULL DEFAULT '1';

COMMIT;

:VERSION 7 # -------------------------

BEGIN;

ALTER TABLE `useraccounts`
ADD COLUMN `DisplayName` VARCHAR(31) NULL AFTER `active`,
ADD COLUMN `NameChanged` INT NULL DEFAULT 0 AFTER `DisplayName`;

COMMIT;
50 changes: 50 additions & 0 deletions OpenSim/Framework/IPeople.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,56 @@ public class UserData
public bool HasGridUserTried;
public bool IsLocal;
public double LastWebFail = -1;
public string DisplayName;
public DateTime NameChanged;

public bool IsNameDefault
{
get
{
return string.IsNullOrWhiteSpace(DisplayName);
}
}

public string LegacyName
{
get
{
if (LastName.ToLower() == "resident")
return FirstName;
else return $"{FirstName} {LastName}";
}
}

public string Username
{
get
{
if (LastName.ToLower() == "resident")
return FirstName;
else if(LastName.StartsWith("@"))
return $"{FirstName}{LastName}";
else return $"{FirstName}.{LastName}";
}
}

public string LowerUsername
{
get
{
return Username.ToLower();
}
}

public string ViewerDisplayName
{
get
{
if (IsNameDefault)
return LegacyName;
else return DisplayName;
}
}
}

public interface IPeople
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,10 @@ private LLSDPerson ConvertUserData(UserData user)
LLSDPerson p = new LLSDPerson();
p.legacy_first_name = user.FirstName;
p.legacy_last_name = user.LastName;
p.display_name = user.FirstName + " " + user.LastName;
if (user.LastName.StartsWith("@"))
p.username = user.FirstName.ToLower() + user.LastName.ToLower();
else
p.username = user.FirstName.ToLower() + "." + user.LastName.ToLower();
p.display_name = user.ViewerDisplayName;
p.username = user.LowerUsername;
p.id = user.Id;
p.is_display_name_default = false;
p.is_display_name_default = user.IsNameDefault;
return p;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2234,16 +2234,15 @@ public void GetDisplayNames(IOSHttpRequest httpRequest, IOSHttpResponse httpResp
if (string.IsNullOrEmpty(ud.FirstName) || ud.FirstName.Equals("Unkown"))
continue;

string fullname = ud.FirstName + " " + ud.LastName;
LLSDxmlEncode2.AddMap(lsl);
LLSDxmlEncode2.AddElem("username", fullname, lsl);
LLSDxmlEncode2.AddElem("display_name", fullname, lsl);
LLSDxmlEncode2.AddElem("display_name_next_update", DateTime.UtcNow.AddDays(8), lsl);
LLSDxmlEncode2.AddElem("display_name_expires", DateTime.UtcNow.AddMonths(1), lsl);
LLSDxmlEncode2.AddElem("username", ud.LowerUsername, lsl);
LLSDxmlEncode2.AddElem("display_name", ud.ViewerDisplayName, lsl);
LLSDxmlEncode2.AddElem("display_name_next_update", ud.NameChanged.AddDays(7), lsl);
LLSDxmlEncode2.AddElem("display_name_expires", DateTime.UtcNow.AddDays(1), lsl);
LLSDxmlEncode2.AddElem("legacy_first_name", ud.FirstName, lsl);
LLSDxmlEncode2.AddElem("legacy_last_name", ud.LastName, lsl);
LLSDxmlEncode2.AddElem("id", ud.Id, lsl);
LLSDxmlEncode2.AddElem("is_display_name_default", true, lsl);
LLSDxmlEncode2.AddElem("is_display_name_default", ud.IsNameDefault, lsl);
LLSDxmlEncode2.AddEndMap(lsl);
}
LLSDxmlEncode2.AddEndArray(lsl);
Expand Down
238 changes: 238 additions & 0 deletions OpenSim/Region/ClientStack/Linden/Caps/DisplayNameModule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
using System.Reflection;
using log4net;
using Mono.Addins;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using Caps = OpenSim.Framework.Capabilities.Caps;
using OpenSim.Framework;
using System.Net;

namespace OpenSim.Region.ClientStack.LindenCaps
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DisplayNameModule")]
public class DisplayNameModule : IDisplayNameModule, INonSharedRegionModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

private IEventQueue m_EventQueue = null;

protected Scene m_Scene = null;

private bool m_Enabled = false;

#region ISharedRegionModule

public void Initialise(IConfigSource source)
{
IConfig config = source.Configs["ClientStack.LindenCaps"];
if (config == null)
return;

string url = config.GetString("Cap_SetDisplayName", string.Empty);
if (url == "localhost")
m_Enabled = true;

if (!m_Enabled)
return;

m_log.Info("[DISPLAY NAMES] Plugin enabled!");
}

public void AddRegion(Scene scene)
{
if (!m_Enabled)
return;

m_Scene = scene;

scene.RegisterModuleInterface<IDisplayNameModule>(this);
}

public void RemoveRegion(Scene scene)
{
if (!m_Enabled)
return;

m_Scene = null;
}

public void RegionLoaded(Scene scene)
{
if (!m_Enabled)
return;

m_EventQueue = scene.RequestModuleInterface<IEventQueue>();
if (m_EventQueue is null)
{
m_log.Info("[DISPLAY NAMES]: Module disabled becuase IEventQueue was not found!");
return;
}

scene.EventManager.OnRegisterCaps += OnRegisterCaps;
}

public void PostInitialise() { }

public void Close() { }

public string Name { get { return "DisplayNamesModule"; } }

public Type ReplaceableInterface
{
get { return null; }
}

#endregion

#region IDisplayNameModule

public string GetDisplayName(UUID avatar)
{
var user = m_Scene.UserManagementModule.GetUserData(avatar);

if (user is not null)
{
return user.ViewerDisplayName;
}

return string.Empty;
}

#endregion

private void OnRegisterCaps(UUID agentID, Caps caps)
{
if (m_Scene.UserManagementModule.IsLocalGridUser(agentID))
{
caps.RegisterSimpleHandler("SetDisplayName", new SimpleStreamHandler($"/{UUID.Random()}", (req, resp) => SetDisplayName(agentID, req, resp)));
return;
}
}

private void SetDisplayName(UUID agent_id, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
if (httpRequest.HttpMethod != "POST")
{
httpResponse.StatusCode = (int)HttpStatusCode.NotFound;
return;
}

ScenePresence sp = m_Scene.GetScenePresence(agent_id);
if (sp == null || sp.IsDeleted)
{
httpResponse.StatusCode = (int)HttpStatusCode.Gone;
return;
}

if (sp.IsInTransit && !sp.IsInLocalTransit)
{
httpResponse.StatusCode = (int)HttpStatusCode.ServiceUnavailable;
httpResponse.AddHeader("Retry-After", "30");
return;
}

var userData = m_Scene.UserManagementModule.GetUserData(agent_id);

if (userData.NameChanged.AddDays(7) > DateTime.UtcNow)
{
m_Scene.GetScenePresence(agent_id).ControllingClient.SendAlertMessage("You can only change your display name once a week!");
return;
}

OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(httpRequest.InputStream);
if (req.ContainsKey("display_name"))
{
OSDArray name = req["display_name"] as OSDArray;

string oldName = name[0].AsString();
string newName = name[1].AsString();

bool resetting = string.IsNullOrWhiteSpace(newName);
if (resetting) newName = string.Empty;

bool success = m_Scene.UserManagementModule.SetDisplayName(agent_id, newName);

if (success)
{
// Update the current object
userData.DisplayName = newName;
userData.NameChanged = DateTime.UtcNow;

if (resetting)
m_log.InfoFormat("[DISPLAY NAMES] {0} {1} reset their display name", userData.FirstName, userData.LastName);
else
m_log.InfoFormat("[DISPLAY NAMES] {0} {1} changed their display name to {2}", userData.FirstName, userData.LastName, userData.DisplayName);

DateTime next_update = DateTime.UtcNow.AddDays(7);

OSD update = FormatDisplayNameUpdate(oldName, userData, next_update);

m_Scene.ForEachClient(x => {
m_EventQueue.Enqueue(update, x.AgentId);
});

SendSetDisplayNameReply(newName, oldName, userData, next_update);
}
else
{
m_Scene.GetScenePresence(agent_id).ControllingClient.SendAlertMessage("Failed to update display name.");
httpResponse.StatusCode = (int)HttpStatusCode.InternalServerError;
return;
}
}

httpResponse.ContentType = "application/llsd+xml";
httpResponse.RawBuffer = Utils.StringToBytes("<llsd><undef/></llsd>");
httpResponse.StatusCode = (int)HttpStatusCode.OK;
}

public OSD FormatDisplayNameUpdate(string oldName, UserData userData, DateTime nextUpdate)
{
var agentData = new OSDMap();
agentData["display_name"] = OSD.FromString(userData.ViewerDisplayName);
agentData["id"] = OSD.FromUUID(userData.Id);
agentData["is_display_name_default"] = OSD.FromBoolean(userData.IsNameDefault);
agentData["legacy_first_name"] = OSD.FromString(userData.FirstName);
agentData["legacy_last_name"] = OSD.FromString(userData.LastName);
agentData["username"] = OSD.FromString(userData.Username);
agentData["display_name_next_update"] = OSD.FromDate(nextUpdate);

var body = new OSDMap();
body["agent"] = agentData;
body["agent_id"] = OSD.FromString(userData.Id.ToString());
body["old_display_name"] = OSD.FromString(oldName);

var nameReply = new OSDMap();
nameReply["body"] = body;
nameReply["message"] = OSD.FromString("DisplayNameUpdate");
return nameReply;
}

public void SendSetDisplayNameReply(string newDisplayName, string oldDisplayName, UserData nameInfo, DateTime nextUpdate)
{
var content = new OSDMap();
content["display_name"] = OSD.FromString(nameInfo.ViewerDisplayName);
content["display_name_next_update"] = OSD.FromDate(nextUpdate);
content["id"] = OSD.FromUUID(nameInfo.Id);
content["is_display_name_default"] = OSD.FromBoolean(nameInfo.IsNameDefault);
content["legacy_first_name"] = OSD.FromString(nameInfo.FirstName);
content["legacy_last_name"] = OSD.FromString(nameInfo.LastName);
content["username"] = OSD.FromString(nameInfo.LowerUsername);

var body = new OSDMap();
body["content"] = content;
body["reason"] = OSD.FromString("OK");
body["status"] = OSD.FromInteger(200);

var nameReply = new OSDMap();
nameReply["body"] = body;
nameReply["message"] = OSD.FromString("SetDisplayNameReply");

m_EventQueue.Enqueue((OSD)nameReply, nameInfo.Id);
}
}
}
Loading

0 comments on commit 0e09536

Please sign in to comment.