diff --git a/OpenSim/Data/IAgentPreferencesData.cs b/OpenSim/Data/IAgentPreferencesData.cs new file mode 100644 index 0000000000..18bf337585 --- /dev/null +++ b/OpenSim/Data/IAgentPreferencesData.cs @@ -0,0 +1,56 @@ +/* + * @brief Data store for AgentPreferences capability + * + * Copyright (C) 2015, Cinder Roxley + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Collections.Generic; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data +{ + public class AgentPreferencesData + { + public UUID PrincipalID = UUID.Zero; + public string AccessPrefs = "M"; + //public int GodLevel; + public double HoverHeight = 0.0; + public string Language = "en-us"; + public bool LanguageIsPublic = true; + // DefaultObjectPermMasks + public int PermEveryone = 0; + public int PermGroup = 0; + public int PermNextOwner = 532480; + } + + public interface IAgentPreferencesData + { + AgentPreferencesData GetPrefs(UUID agentID); + void StorePrefs(AgentPreferencesData data); + } +} + diff --git a/OpenSim/Data/MySQL/MySQLAgentPreferencesData.cs b/OpenSim/Data/MySQL/MySQLAgentPreferencesData.cs new file mode 100644 index 0000000000..0ea2f640b0 --- /dev/null +++ b/OpenSim/Data/MySQL/MySQLAgentPreferencesData.cs @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2015, Cinder Roxley + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using MySql.Data.MySqlClient; + +namespace OpenSim.Data.MySQL +{ + public class MySQLAgentPreferencesData : MySQLGenericTableHandler, IAgentPreferencesData + { + public MySQLAgentPreferencesData(string connectionString, string realm) + : base(connectionString, realm, "AgentPrefs") + { + } + + public AgentPreferencesData GetPrefs(UUID agentID) + { + AgentPreferencesData[] ret = Get("PrincipalID", agentID.ToString()); + + if (ret.Length == 0) + return null; + + return ret[0]; + } + + public void StorePrefs(AgentPreferencesData data) + { + using (MySqlCommand cmd = new MySqlCommand()) + { + cmd.CommandText = String.Format("replace into `{0}` (`PrincipalID`, `AccessPrefs`, `HoverHeight`, `Language`, `LanguageIsPublic`, `PermEveryone`, `PermGroup`, `PermNextOwner`) VALUES (?Principal, ?AP, ?HH, ?Lang, ?LIP, ?PE, ?PG, ?PNO)", m_Realm); + cmd.Parameters.AddWithValue("?Principal", data.PrincipalID.ToString()); + cmd.Parameters.AddWithValue("?AP", data.AccessPrefs); + cmd.Parameters.AddWithValue("?HH", data.HoverHeight); + cmd.Parameters.AddWithValue("?Lang", data.Language); + cmd.Parameters.AddWithValue("?LIP", data.LanguageIsPublic); + cmd.Parameters.AddWithValue("?PE", data.PermEveryone); + cmd.Parameters.AddWithValue("?PG", data.PermGroup); + cmd.Parameters.AddWithValue("?PNO", data.PermNextOwner); + + ExecuteNonQuery(cmd); + } + } + } +} + diff --git a/OpenSim/Data/MySQL/Resources/AgentPrefs.migrations b/OpenSim/Data/MySQL/Resources/AgentPrefs.migrations new file mode 100644 index 0000000000..e496f724ef --- /dev/null +++ b/OpenSim/Data/MySQL/Resources/AgentPrefs.migrations @@ -0,0 +1,18 @@ +:VERSION 1 # ------------------------- + +BEGIN; + +CREATE TABLE `AgentPrefs` ( + `PrincipalID` CHAR(36) NOT NULL, + `AccessPrefs` CHAR(2) NOT NULL DEFAULT 'M', + `HoverHeight` DOUBLE(30, 27) NOT NULL DEFAULT 0, + `Language` CHAR(5) NOT NULL DEFAULT 'en-us', + `LanguageIsPublic` BOOLEAN NOT NULL DEFAULT 1, + `PermEveryone` INT(6) NOT NULL DEFAULT 0, + `PermGroup` INT(6) NOT NULL DEFAULT 0, + `PermNextOwner` INT(6) NOT NULL DEFAULT 532480, + UNIQUE KEY `PrincipalID` (`PrincipalID`), + PRIMARY KEY(`PrincipalID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +COMMIT; diff --git a/OpenSim/Region/ClientStack/Linden/Caps/AgentPreferencesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/AgentPreferencesModule.cs new file mode 100644 index 0000000000..a738fba2cf --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/Caps/AgentPreferencesModule.cs @@ -0,0 +1,225 @@ +/* + * @brief AgentPreferences capability module + * + * Copyright (C) 2015, Cinder Roxley + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Reflection; +using System.IO; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Data; +using OpenSim.Data.MySQL; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; +using OpenSim.Capabilities.Handlers; + +namespace OpenSim.Region.ClientStack.LindenCaps +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AgentPreferencesModule")] + public class AgentPreferencesModule : ISharedRegionModule, IAgentPreferencesModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public bool m_enabled { get; private set; } + private Scene m_Scene; + protected IAgentPreferencesData m_Database; + + public void Initialise(IConfigSource source) + { + IConfig dbConfig = source.Configs["DatabaseService"]; + if (dbConfig != null) + { + string dllName = String.Empty; + string connString = String.Empty; + + dllName = dbConfig.GetString("StorageProvider", dllName); + connString = dbConfig.GetString("ConnectionString", connString); + + // We tried, but this doesn't exist. We can't proceed + if (dllName == String.Empty) + throw new Exception("No StorageProvider configured"); + + // *FIXME: This is a janky as hell, works for now. + if (dllName == "OpenSim.Data.MySQL.dll") + m_Database = new MySQLAgentPreferencesData(connString, "AgentPrefs"); + else + throw new Exception("Storage provider not supported!"); + + if (m_Database == null) + { + m_enabled = false; + throw new Exception("Could not find a storage interface in the given module"); + } + m_log.Debug("[AgentPrefs] AgentPrefs is enabled"); + m_enabled = true; + } + } + + #region Region module + public void AddRegion(Scene s) + { + if (!m_enabled) return; + + s.RegisterModuleInterface(this); + m_Scene = s; + } + + public void RemoveRegion(Scene s) + { + if (!m_enabled) return; + + m_Scene.UnregisterModuleInterface(this); + m_Scene.EventManager.OnRegisterCaps -= RegisterCaps; + m_Scene = null; + } + + public void RegionLoaded(Scene s) + { + if (!m_enabled) return; + + m_Scene.EventManager.OnRegisterCaps += delegate(UUID agentID, OpenSim.Framework.Capabilities.Caps caps) + { + RegisterCaps(agentID, caps); + }; + } + + public void PostInitialise() {} + + public void Close() {} + + public string Name { get { return "AgentPreferencesModule"; } } + + public Type ReplaceableInterface + { + get { return null; } + } + + public void RegisterCaps(UUID agent, Caps caps) + { + UUID capId = UUID.Random(); + caps.RegisterHandler("AgentPreferences", + new RestStreamHandler("POST", "/CAPS/" + capId, + delegate(string request, string path, string param, + IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + return UpdateAgentPreferences(request, path, param, agent); + })); + caps.RegisterHandler("UpdateAgentLanguage", + new RestStreamHandler("POST", "/CAPS/" + capId, + delegate(string request, string path, string param, + IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + return UpdateAgentPreferences(request, path, param, agent); + })); + caps.RegisterHandler("UpdateAgentInformation", + new RestStreamHandler("POST", "/CAPS/" + capId, + delegate(string request, string path, string param, + IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + return UpdateAgentPreferences(request, path, param, agent); + })); + } + + public string UpdateAgentPreferences(string request, string path, string param, UUID agent) + { + m_log.DebugFormat("[AgentPrefs] UpdateAgentPreferences for {0}", agent.ToString()); + OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request); + AgentPreferencesData data = m_Database.GetPrefs(agent); + if (data == null) + { + data = new AgentPreferencesData(); + data.PrincipalID = agent; + } + + if (req.ContainsKey("access_prefs")) + { + OSDMap accessPrefs = (OSDMap)req["access_prefs"]; // We could check with ContainsKey... + data.AccessPrefs = accessPrefs["max"].AsString(); + } + if (req.ContainsKey("default_object_perm_masks")) + { + OSDMap permsMap = (OSDMap)req["default_object_perm_masks"]; + data.PermEveryone = permsMap["Everyone"].AsInteger(); + data.PermGroup = permsMap["Group"].AsInteger(); + data.PermNextOwner = permsMap["NextOwner"].AsInteger(); + } + if (req.ContainsKey("hover_height")) + { + data.HoverHeight = req["hover_height"].AsReal(); + } + if (req.ContainsKey("language")) + { + data.Language = req["language"].AsString(); + } + if (req.ContainsKey("language_is_public")) + { + data.LanguageIsPublic = req["language_is_public"].AsBoolean(); + } + m_Database.StorePrefs(data); + OSDMap resp = new OSDMap(); + OSDMap respAccessPrefs = new OSDMap(); + respAccessPrefs["max"] = data.AccessPrefs; + resp["access_prefs"] = respAccessPrefs; + OSDMap respDefaultPerms = new OSDMap(); + respDefaultPerms["Everyone"] = data.PermEveryone; + respDefaultPerms["Group"] = data.PermGroup; + respDefaultPerms["NextOwner"] = data.PermNextOwner; + resp["default_object_perm_masks"] = respDefaultPerms; + resp["god_level"] = 0; // *TODO: Add this + resp["hover_height"] = data.HoverHeight; + resp["language"] = data.Language; + resp["language_is_public"] = data.LanguageIsPublic; + + string response = OSDParser.SerializeLLSDXmlString(resp); + return response; + } + #endregion Region module + + #region IAgentPreferences + public string GetLang(UUID agentID) + { + AgentPreferencesData data = m_Database.GetPrefs(agentID); + if (data != null) + { + if (data.LanguageIsPublic) + return data.Language; + } + return "en-us"; + + } + #endregion + } +} + diff --git a/OpenSim/Region/Framework/Interfaces/IAgentPreferencesModule.cs b/OpenSim/Region/Framework/Interfaces/IAgentPreferencesModule.cs new file mode 100644 index 0000000000..f2930ac3f6 --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/IAgentPreferencesModule.cs @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2015, Cinder Roxley + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using OpenMetaverse; + +namespace OpenSim.Region.Framework.Interfaces +{ + public interface IAgentPreferencesModule + { + string GetLang(UUID agentID); + } +} diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 53c198ec29..b50f429f02 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6147,12 +6147,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String llGetAgentLanguage(string id) { - // This should only return a value if the avatar is in the same region - //ckrinke 1-30-09 : This needs to parse the XMLRPC language field supplied - //by the client at login. Currently returning only en-us until our I18N - //effort gains momentum + // This should only return a value if the avatar is in the same region, but eh. idc. m_host.AddScriptLPS(1); - return "en-us"; + IAgentPreferencesModule ap = World.RequestModuleInterface(); + if (ap != null) + { + UUID key = new UUID(); + if (UUID.TryParse(id, out key)) + { + return ap.GetLang(key); + } + } + return new LSL_String("en-us"); } /// /// http://wiki.secondlife.com/wiki/LlGetAgentList