From 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 19 May 2019 21:24:15 +1000 Subject: Dump OpenSim 0.9.0.1 into it's own branch. --- OpenSim/Server/Base/CommandManager.cs | 90 ++++---- OpenSim/Server/Base/HttpServerBase.cs | 35 +-- OpenSim/Server/Base/Properties/AssemblyInfo.cs | 10 +- OpenSim/Server/Base/ProtocolVersions.cs | 14 +- OpenSim/Server/Base/ServerUtils.cs | 179 +++++++++----- OpenSim/Server/Base/ServicesServerBase.cs | 202 +++++++++++++--- .../AgentPreferencesServerPostHandler.cs | 3 +- .../Server/Handlers/Asset/AssetServerConnector.cs | 14 +- .../Server/Handlers/Asset/AssetServerGetHandler.cs | 4 +- .../Asset/Tests/AssetServerPostHandlerTests.cs | 12 +- .../AuthenticationServerPostHandler.cs | 28 +-- .../Authentication/OpenIdServerConnector.cs | 2 +- .../Handlers/Authentication/OpenIdServerHandler.cs | 11 +- .../AuthorizationServerPostHandler.cs | 2 +- .../Handlers/Avatar/AvatarServerPostHandler.cs | 12 +- OpenSim/Server/Handlers/BakedTextures/XBakes.cs | 4 +- .../Server/Handlers/BakedTextures/XBakesHandler.cs | 2 +- .../Handlers/BakedTextures/XBakesPostHandler.cs | 8 +- OpenSim/Server/Handlers/Base/ServerConnector.cs | 6 +- .../Handlers/Estate/EstateDataRobustConnector.cs | 7 +- .../Handlers/Friends/FriendsServerPostHandler.cs | 6 +- OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs | 10 +- .../Server/Handlers/Grid/GridServerPostHandler.cs | 20 +- .../Handlers/GridUser/GridUserServerConnector.cs | 2 +- .../Handlers/GridUser/GridUserServerPostHandler.cs | 11 +- OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs | 4 +- .../Handlers/Hypergrid/HGFriendServerConnector.cs | 2 +- .../Hypergrid/HGFriendsServerPostHandler.cs | 18 +- .../Server/Handlers/Hypergrid/HomeAgentHandlers.cs | 2 +- .../Server/Handlers/Hypergrid/HypergridHandlers.cs | 7 +- .../Hypergrid/InstantMessageServerConnector.cs | 2 +- .../Handlers/Hypergrid/UserAgentServerConnector.cs | 5 +- .../Inventory/InventoryServerInConnector.cs | 24 +- .../Handlers/Inventory/XInventoryInConnector.cs | 22 +- OpenSim/Server/Handlers/Land/LandHandlers.cs | 3 +- .../Server/Handlers/Land/LandServiceInConnector.cs | 2 +- OpenSim/Server/Handlers/Login/LLLoginHandlers.cs | 19 +- .../Handlers/Login/LLLoginServiceInConnector.cs | 4 +- .../Server/Handlers/Map/MapAddServerConnector.cs | 29 ++- .../Server/Handlers/Map/MapGetServerConnector.cs | 28 ++- .../Handlers/Map/MapRemoveServerConnector.cs | 256 +++++++++++++++++++++ .../Handlers/MuteList/MuteListServerConnector.cs | 63 +++++ .../Handlers/MuteList/MuteListServerPostHandler.cs | 240 +++++++++++++++++++ .../Server/Handlers/Neighbour/NeighbourHandlers.cs | 2 +- .../Neighbour/NeighbourServiceInConnector.cs | 2 +- .../Handlers/Presence/PresenceServerPostHandler.cs | 4 +- .../Handlers/Profiles/UserProfilesConnector.cs | 6 +- .../Handlers/Profiles/UserProfilesHandlers.cs | 109 ++++----- OpenSim/Server/Handlers/Properties/AssemblyInfo.cs | 10 +- .../Server/Handlers/Simulation/AgentHandlers.cs | 110 ++++++--- .../Server/Handlers/Simulation/ObjectHandlers.cs | 2 + .../UserAccounts/UserAccountServerPostHandler.cs | 66 +++++- OpenSim/Server/Properties/AssemblyInfo.cs | 8 +- OpenSim/Server/ServerMain.cs | 17 +- 54 files changed, 1348 insertions(+), 412 deletions(-) create mode 100644 OpenSim/Server/Handlers/Map/MapRemoveServerConnector.cs create mode 100644 OpenSim/Server/Handlers/MuteList/MuteListServerConnector.cs create mode 100644 OpenSim/Server/Handlers/MuteList/MuteListServerPostHandler.cs (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Base/CommandManager.cs b/OpenSim/Server/Base/CommandManager.cs index bd18485..b6e2903 100644 --- a/OpenSim/Server/Base/CommandManager.cs +++ b/OpenSim/Server/Base/CommandManager.cs @@ -41,117 +41,117 @@ namespace OpenSim.Server.Base { /// /// Command manager - - /// Wrapper for OpenSim.Framework.PluginManager to allow + /// Wrapper for OpenSim.Framework.PluginManager to allow /// us to add commands to the console to perform operations /// on our repos and plugins /// - public class CommandManager - { - public AddinRegistry PluginRegistry; - protected PluginManager PluginManager; + public class CommandManager + { + public AddinRegistry PluginRegistry; + protected PluginManager PluginManager; - public CommandManager(AddinRegistry registry) + public CommandManager(AddinRegistry registry) { - PluginRegistry = registry; - PluginManager = new PluginManager(PluginRegistry); - AddManagementCommands(); - } - - private void AddManagementCommands() - { - // add plugin - MainConsole.Instance.Commands.AddCommand("Plugin", true, + PluginRegistry = registry; + PluginManager = new PluginManager(PluginRegistry); + AddManagementCommands(); + } + + private void AddManagementCommands() + { + // add plugin + MainConsole.Instance.Commands.AddCommand("Plugin", true, "plugin add", "plugin add \"plugin index\"", - "Install plugin from repository.", + "Install plugin from repository.", HandleConsoleInstallPlugin); - // remove plugin + // remove plugin MainConsole.Instance.Commands.AddCommand("Plugin", true, "plugin remove", "plugin remove \"plugin index\"", - "Remove plugin from repository", + "Remove plugin from repository", HandleConsoleUnInstallPlugin); - // list installed plugins + // list installed plugins MainConsole.Instance.Commands.AddCommand("Plugin", true, - "plugin list installed", - "plugin list installed","List install plugins", + "plugin list installed", + "plugin list installed","List install plugins", HandleConsoleListInstalledPlugin); - // list plugins available from registered repositories + // list plugins available from registered repositories MainConsole.Instance.Commands.AddCommand("Plugin", true, "plugin list available", - "plugin list available","List available plugins", + "plugin list available","List available plugins", HandleConsoleListAvailablePlugin); - // List available updates + // List available updates MainConsole.Instance.Commands.AddCommand("Plugin", true, "plugin updates", "plugin updates","List availble updates", HandleConsoleListUpdates); - // Update plugin + // Update plugin MainConsole.Instance.Commands.AddCommand("Plugin", true, "plugin update", "plugin update \"plugin index\"","Update the plugin", HandleConsoleUpdatePlugin); - // Add repository + // Add repository MainConsole.Instance.Commands.AddCommand("Repository", true, "repo add", "repo add \"url\"","Add repository", HandleConsoleAddRepo); - // Refresh repo + // Refresh repo MainConsole.Instance.Commands.AddCommand("Repository", true, "repo refresh", "repo refresh \"url\"", "Sync with a registered repository", HandleConsoleGetRepo); - // Remove repository from registry + // Remove repository from registry MainConsole.Instance.Commands.AddCommand("Repository", true, "repo remove", - "repo remove \"[url | index]\"", - "Remove repository from registry", + "repo remove \"[url | index]\"", + "Remove repository from registry", HandleConsoleRemoveRepo); - // Enable repo + // Enable repo MainConsole.Instance.Commands.AddCommand("Repository", true, "repo enable", "repo enable \"[url | index]\"", - "Enable registered repository", + "Enable registered repository", HandleConsoleEnableRepo); - // Disable repo + // Disable repo MainConsole.Instance.Commands.AddCommand("Repository", true, "repo disable", "repo disable\"[url | index]\"", - "Disable registered repository", + "Disable registered repository", HandleConsoleDisableRepo); - // List registered repositories + // List registered repositories MainConsole.Instance.Commands.AddCommand("Repository", true, "repo list", "repo list", - "List registered repositories", + "List registered repositories", HandleConsoleListRepos); - // * + // * MainConsole.Instance.Commands.AddCommand("Plugin", true, "plugin info", "plugin info \"plugin index\"","Show detailed information for plugin", HandleConsoleShowAddinInfo); - // Plugin disable + // Plugin disable MainConsole.Instance.Commands.AddCommand("Plugin", true, "plugin disable", "plugin disable \"plugin index\"", - "Disable a plugin", + "Disable a plugin", HandleConsoleDisablePlugin); - // Enable plugin + // Enable plugin MainConsole.Instance.Commands.AddCommand("Plugin", true, "plugin enable", "plugin enable \"plugin index\"", - "Enable the selected plugin plugin", + "Enable the selected plugin plugin", HandleConsoleEnablePlugin); } - + #region console handlers // Handle our console commands // // Install plugin from registered repository /// /// Handles the console install plugin command. Attempts to install the selected plugin - /// and + /// and /// /// /// Module. @@ -323,7 +323,7 @@ namespace OpenSim.Server.Base { if (cmd.Length >= 3) { - + Dictionary result = new Dictionary(); int ndx = Convert.ToInt16(cmd[2]); @@ -355,5 +355,5 @@ namespace OpenSim.Server.Base return; } #endregion - } + } } \ No newline at end of file diff --git a/OpenSim/Server/Base/HttpServerBase.cs b/OpenSim/Server/Base/HttpServerBase.cs index 44ef124..3357250 100644 --- a/OpenSim/Server/Base/HttpServerBase.cs +++ b/OpenSim/Server/Base/HttpServerBase.cs @@ -40,7 +40,7 @@ namespace OpenSim.Server.Base { public class HttpServerBase : ServicesServerBase { -// private static readonly ILog m_Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private uint m_consolePort; @@ -70,6 +70,7 @@ namespace OpenSim.Server.Base bool ssl_main = networkConfig.GetBoolean("https_main",false); bool ssl_listener = networkConfig.GetBoolean("https_listener",false); + bool ssl_external = networkConfig.GetBoolean("https_external",false); m_consolePort = (uint)networkConfig.GetInt("ConsolePort", 0); @@ -111,25 +112,33 @@ namespace OpenSim.Server.Base MainServer.Instance = httpServer; // If https_listener = true, then add an ssl listener on the https_port... - if (ssl_listener == true) + if (ssl_listener == true) { uint https_port = (uint)networkConfig.GetInt("https_port", 0); - string cert_path = networkConfig.GetString("cert_path",String.Empty); - if (cert_path == String.Empty) + m_log.WarnFormat("[SSL]: External flag is {0}", ssl_external); + if (!ssl_external) { - System.Console.WriteLine("ERROR: Path to X509 certificate is missing, server can't start."); - Environment.Exit(1); + string cert_path = networkConfig.GetString("cert_path",String.Empty); + if ( cert_path == String.Empty ) + { + System.Console.WriteLine("Path to X509 certificate is missing, server can't start."); + Thread.CurrentThread.Abort(); + } + string cert_pass = networkConfig.GetString("cert_pass",String.Empty); + if ( cert_pass == String.Empty ) + { + System.Console.WriteLine("Password for X509 certificate is missing, server can't start."); + Thread.CurrentThread.Abort(); + } + + MainServer.AddHttpServer(new BaseHttpServer(https_port, ssl_listener, cert_path, cert_pass)); } - - string cert_pass = networkConfig.GetString("cert_pass",String.Empty); - if (cert_pass == String.Empty) + else { - System.Console.WriteLine("ERROR: Password for X509 certificate is missing, server can't start."); - Environment.Exit(1); + m_log.WarnFormat("[SSL]: SSL port is active but no SSL is used because external SSL was requested."); + MainServer.AddHttpServer(new BaseHttpServer(https_port)); } - - MainServer.AddHttpServer(new BaseHttpServer(https_port, ssl_listener, cert_path, cert_pass)); } } diff --git a/OpenSim/Server/Base/Properties/AssemblyInfo.cs b/OpenSim/Server/Base/Properties/AssemblyInfo.cs index 3c634a7..4be0f25 100644 --- a/OpenSim/Server/Base/Properties/AssemblyInfo.cs +++ b/OpenSim/Server/Base/Properties/AssemblyInfo.cs @@ -2,7 +2,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following +// General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("OpenSim.Server.Base")] @@ -14,8 +14,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] @@ -25,9 +25,9 @@ using System.Runtime.InteropServices; // Version information for an assembly consists of the following four values: // // Major Version -// Minor Version +// Minor Version // Build Number // Revision // -[assembly: AssemblyVersion("0.8.3.*")] +[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)] diff --git a/OpenSim/Server/Base/ProtocolVersions.cs b/OpenSim/Server/Base/ProtocolVersions.cs index 5c2278c..27eed4c 100644 --- a/OpenSim/Server/Base/ProtocolVersions.cs +++ b/OpenSim/Server/Base/ProtocolVersions.cs @@ -31,20 +31,20 @@ namespace OpenSim.Server.Base { /// /// This is the external protocol versions. It is separate from the OpenSimulator project version. - /// + /// /// These version numbers should be increased by 1 every time a code - /// change in the Service.Connectors and Server.Handlers, espectively, + /// change in the Service.Connectors and Server.Handlers, espectively, /// makes the previous OpenSimulator revision incompatible - /// with the new revision. - /// + /// with the new revision. + /// /// Changes which are compatible with an older revision (e.g. older revisions experience degraded functionality /// but not outright failure) do not need a version number increment. - /// + /// /// Having this version number allows the grid service to reject connections from regions running a version - /// of the code that is too old. + /// of the code that is too old. /// /// - + // The range of acceptable servers for client-side connectors public readonly static int ClientProtocolVersionMin = 1; public readonly static int ClientProtocolVersionMax = 1; diff --git a/OpenSim/Server/Base/ServerUtils.cs b/OpenSim/Server/Base/ServerUtils.cs index 18a4266..cc506bc 100644 --- a/OpenSim/Server/Base/ServerUtils.cs +++ b/OpenSim/Server/Base/ServerUtils.cs @@ -39,7 +39,7 @@ using OpenMetaverse; using Mono.Addins; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Servers; - +using OpenMetaverse.StructuredData; // LitJson is hidden on this [assembly:AddinRoot("Robust", OpenSim.VersionInfo.VersionNumber)] namespace OpenSim.Server.Base @@ -104,7 +104,7 @@ namespace OpenSim.Server.Base // libomv, which has a hard-coded path to "." for pinvoke // to load the openjpeg dll // - // Will look for a way to fix, but for now this keeps the + // Will look for a way to fix, but for now this keeps the // confusion to a minimum. this was copied from our region // plugin loader, we have been doing this in there for a long time. // @@ -183,7 +183,7 @@ namespace OpenSim.Server.Base if(port != 0) server = MainServer.GetHttpServer(port); - else + else server = MainServer.Instance; return server; @@ -222,19 +222,19 @@ namespace OpenSim.Server.Base // This is good to debug configuration problems //if (dllName == string.Empty) // Util.PrintCallStack(); - + string className = String.Empty; // The path for a dynamic plugin will contain ":" on Windows string[] parts = dllName.Split (new char[] {':'}); - if (parts [0].Length > 1) + if (parts [0].Length > 1) { dllName = parts [0]; if (parts.Length > 1) className = parts[1]; - } - else + } + else { // This is Windows - we must replace the ":" in the path dllName = String.Format ("{0}:{1}", parts [0], parts [1]); @@ -242,6 +242,18 @@ namespace OpenSim.Server.Base className = parts[2]; } + // Handle extra string arguments in a more generic way + if (dllName.Contains("@")) + { + string[] dllNameParts = dllName.Split(new char[] {'@'}); + dllName = dllNameParts[dllNameParts.Length - 1]; + List argList = new List(args); + for (int i = 0 ; i < dllNameParts.Length - 1 ; ++i) + argList.Add(dllNameParts[i]); + + args = argList.ToArray(); + } + return LoadPlugin(dllName, className, args); } @@ -264,10 +276,10 @@ namespace OpenSim.Server.Base { if (pluginType.IsPublic) { - if (className != String.Empty + if (className != String.Empty && pluginType.ToString() != pluginType.Namespace + "." + className) continue; - + Type typeInterface = pluginType.GetInterface(interfaceName); if (typeInterface != null) @@ -283,8 +295,8 @@ namespace OpenSim.Server.Base if (!(e is System.MissingMethodException)) { m_log.Error(string.Format("[SERVER UTILS]: Error loading plugin {0} from {1}. Exception: {2}", - interfaceName, - dllName, + interfaceName, + dllName, e.InnerException == null ? e.Message : e.InnerException.Message), e); } @@ -315,49 +327,62 @@ namespace OpenSim.Server.Base public static Dictionary ParseQueryString(string query) { - Dictionary result = new Dictionary(); string[] terms = query.Split(new char[] {'&'}); - if (terms.Length == 0) - return result; + int nterms = terms.Length; + if (nterms == 0) + return new Dictionary(); - foreach (string t in terms) + Dictionary result = new Dictionary(nterms); + string name; + + for(int i = 0; i < nterms; ++i) { - string[] elems = t.Split(new char[] {'='}); + string[] elems = terms[i].Split(new char[] {'='}); + if (elems.Length == 0) continue; - string name = System.Web.HttpUtility.UrlDecode(elems[0]); - string value = String.Empty; + if(String.IsNullOrWhiteSpace(elems[0])) + continue; - if (elems.Length > 1) - value = System.Web.HttpUtility.UrlDecode(elems[1]); + name = System.Web.HttpUtility.UrlDecode(elems[0]); if (name.EndsWith("[]")) { - string cleanName = name.Substring(0, name.Length - 2); - if (result.ContainsKey(cleanName)) + name = name.Substring(0, name.Length - 2); + if(String.IsNullOrWhiteSpace(name)) + continue; + if (result.ContainsKey(name)) { - if (!(result[cleanName] is List)) + if (!(result[name] is List)) continue; - List l = (List)result[cleanName]; - - l.Add(value); + List l = (List)result[name]; + if (elems.Length > 1 && !String.IsNullOrWhiteSpace(elems[1])) + l.Add(System.Web.HttpUtility.UrlDecode(elems[1])); + else + l.Add(String.Empty); } else { List newList = new List(); - - newList.Add(value); - - result[cleanName] = newList; + if (elems.Length > 1 && !String.IsNullOrWhiteSpace(elems[1])) + newList.Add(System.Web.HttpUtility.UrlDecode(elems[1])); + else + newList.Add(String.Empty); + result[name] = newList; } } else { if (!result.ContainsKey(name)) - result[name] = value; + { + if (elems.Length > 1 && !String.IsNullOrWhiteSpace(elems[1])) + result[name] = System.Web.HttpUtility.UrlDecode(elems[1]); + else + result[name] = String.Empty; + } } } @@ -366,47 +391,70 @@ namespace OpenSim.Server.Base public static string BuildQueryString(Dictionary data) { - string qstring = String.Empty; + // this is not conform to html url encoding + // can only be used on Body of POST or PUT + StringBuilder sb = new StringBuilder(4096); - string part; + string pvalue; foreach (KeyValuePair kvp in data) { if (kvp.Value is List) { List l = (List)kvp.Value; - - foreach (string s in l) + int llen = l.Count; + string nkey = System.Web.HttpUtility.UrlEncode(kvp.Key); + for(int i = 0; i < llen; ++i) { - part = System.Web.HttpUtility.UrlEncode(kvp.Key) + - "[]=" + System.Web.HttpUtility.UrlEncode(s); - - if (qstring != String.Empty) - qstring += "&"; - - qstring += part; + if (sb.Length != 0) + sb.Append("&"); + sb.Append(nkey); + sb.Append("[]="); + sb.Append(System.Web.HttpUtility.UrlEncode(l[i])); } } - else + else if(kvp.Value is Dictionary) { - if (kvp.Value.ToString() != String.Empty) + // encode complex structures as JSON + // needed for estate bans with the encoding used on xml + // encode can be here because object does contain the structure information + // but decode needs to be on estateSettings (or other user) + string js; + try { - part = System.Web.HttpUtility.UrlEncode(kvp.Key) + - "=" + System.Web.HttpUtility.UrlEncode(kvp.Value.ToString()); + // bypass libovm, we dont need even more useless high level maps + // this should only be called once.. but no problem, i hope + // (other uses may need more..) + LitJson.JsonMapper.RegisterExporter((uuid, writer) => writer.Write(uuid.ToString()) ); + js = LitJson.JsonMapper.ToJson(kvp.Value); } - else + // catch(Exception e) + catch { - part = System.Web.HttpUtility.UrlEncode(kvp.Key); + continue; + } + if (sb.Length != 0) + sb.Append("&"); + sb.Append(System.Web.HttpUtility.UrlEncode(kvp.Key)); + sb.Append("="); + sb.Append(System.Web.HttpUtility.UrlEncode(js)); + } + else + { + if (sb.Length != 0) + sb.Append("&"); + sb.Append(System.Web.HttpUtility.UrlEncode(kvp.Key)); + + pvalue = kvp.Value.ToString(); + if (!String.IsNullOrEmpty(pvalue)) + { + sb.Append("="); + sb.Append(System.Web.HttpUtility.UrlEncode(pvalue)); } - - if (qstring != String.Empty) - qstring += "&"; - - qstring += part; } } - return qstring; + return sb.ToString(); } public static string BuildXmlResponse(Dictionary data) @@ -465,18 +513,23 @@ namespace OpenSim.Server.Base Dictionary ret = new Dictionary(); XmlDocument doc = new XmlDocument(); + doc.XmlResolver = null; + try + { + doc.LoadXml(data); + XmlNodeList rootL = doc.GetElementsByTagName("ServerResponse"); - doc.LoadXml(data); - - XmlNodeList rootL = doc.GetElementsByTagName("ServerResponse"); - - if (rootL.Count != 1) - return ret; - - XmlNode rootNode = rootL[0]; + if (rootL.Count != 1) + return ret; - ret = ParseElement(rootNode); + XmlNode rootNode = rootL[0]; + ret = ParseElement(rootNode); + } + catch (Exception e) + { + m_log.DebugFormat("[serverUtils.ParseXmlResponse]: failed error: {0} \n --- string: {1} - ",e.Message, data); + } return ret; } diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs index 076868d..176e876 100644 --- a/OpenSim/Server/Base/ServicesServerBase.cs +++ b/OpenSim/Server/Base/ServicesServerBase.cs @@ -55,16 +55,16 @@ namespace OpenSim.Server.Base // protected string[] m_Arguments; - public string ConfigDirectory - { - get; - private set; - } + protected string m_configDirectory = "."; // Run flag // private bool m_Running = true; +#if (_MONO) + private static Mono.Unix.UnixSignal[] signals; +#endif + // Handle all the automagical stuff // public ServicesServerBase(string prompt, string[] args) : base() @@ -85,7 +85,7 @@ namespace OpenSim.Server.Base string fileName = ""; if (Assembly.GetEntryAssembly() != null) fileName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location); - string iniFile = "../config/" + fileName + ".ini"; + string iniFile = fileName + ".ini"; string logConfig = null; IConfig startupConfig = argvConfig.Configs["Startup"]; @@ -96,39 +96,31 @@ namespace OpenSim.Server.Base // Check if a prompt was given on the command line prompt = startupConfig.GetString("prompt", prompt); - + // Check for a Log4Net config file on the command line logConfig =startupConfig.GetString("logconfig", logConfig); } - // Find out of the file name is a URI and remote load it if possible. - // Load it as a local file otherwise. - Uri configUri; + Config = ReadConfigSource(iniFile); - try + List sources = new List(); + sources.Add(iniFile); + + int sourceIndex = 1; + + while (AddIncludes(Config, sources)) { - if (Uri.TryCreate(iniFile, UriKind.Absolute, out configUri) && - configUri.Scheme == Uri.UriSchemeHttp) + for ( ; sourceIndex < sources.Count ; ++sourceIndex) { - XmlReader r = XmlReader.Create(iniFile); - Config = new XmlConfigSource(r); + IConfigSource s = ReadConfigSource(sources[sourceIndex]); + Config.Merge(s); } - else - { - Config = new IniConfigSource(iniFile); - } - } - catch (Exception e) - { - System.Console.WriteLine("Error reading from config source. {0}", e.Message); - System.Diagnostics.Process.GetCurrentProcess().Kill(); -///// Environment.Exit(1); } // Merge OpSys env vars - m_log.Info("[CONFIG]: Loading environment variables for Config"); + Console.WriteLine("[CONFIG]: Loading environment variables for Config"); Util.MergeEnvironmentToConfig(Config); - + // Merge the configuration from the command line into the loaded file Config.Merge(argvConfig); @@ -140,10 +132,12 @@ namespace OpenSim.Server.Base startupConfig = Config.Configs["Startup"]; } - ConfigDirectory = startupConfig.GetString("ConfigDirectory", "."); - - prompt = startupConfig.GetString("Prompt", prompt); + if (startupConfig != null) + { + m_configDirectory = startupConfig.GetString("ConfigDirectory", m_configDirectory); + prompt = startupConfig.GetString("Prompt", prompt); + } // Allow derived classes to load config before the console is opened. ReadConfig(); @@ -193,6 +187,42 @@ namespace OpenSim.Server.Base RegisterCommonCommands(); RegisterCommonComponents(Config); +#if (_MONO) + Thread signal_thread = new Thread (delegate () + { + while (true) + { + // Wait for a signal to be delivered + int index = Mono.Unix.UnixSignal.WaitAny (signals, -1); + + //Mono.Unix.Native.Signum signal = signals [index].Signum; + ShutdownSpecific(); + m_Running = false; + Environment.Exit(0); + } + }); + + if(!Util.IsWindows()) + { + try + { + // linux mac os specifics + signals = new Mono.Unix.UnixSignal[] + { + new Mono.Unix.UnixSignal(Mono.Unix.Native.Signum.SIGTERM) + }; + ignal_thread.IsBackground = true; + signal_thread.Start(); + } + catch (Exception e) + { + m_log.Info("Could not set up UNIX signal handlers. SIGTERM will not"); + m_log.InfoFormat("shut down gracefully: {0}", e.Message); + m_log.Debug("Exception was: ", e); + } + } +#endif + // Allow derived classes to perform initialization that // needs to be done after the console has opened Initialise(); @@ -220,6 +250,9 @@ namespace OpenSim.Server.Base } } + MemoryWatchdog.Enabled = false; + Watchdog.Enabled = false; + WorkManager.Stop(); RemovePIDFile(); return 0; @@ -240,5 +273,114 @@ namespace OpenSim.Server.Base protected virtual void Initialise() { } + + /// + /// Adds the included files as ini configuration files + /// + /// List of URL strings or filename strings + private bool AddIncludes(IConfigSource configSource, List sources) + { + bool sourcesAdded = false; + + //loop over config sources + foreach (IConfig config in configSource.Configs) + { + // Look for Include-* in the key name + string[] keys = config.GetKeys(); + foreach (string k in keys) + { + if (k.StartsWith("Include-")) + { + // read the config file to be included. + string file = config.GetString(k); + if (IsUri(file)) + { + if (!sources.Contains(file)) + { + sourcesAdded = true; + sources.Add(file); + } + } + else + { + string basepath = Path.GetFullPath(m_configDirectory); + // Resolve relative paths with wildcards + string chunkWithoutWildcards = file; + string chunkWithWildcards = string.Empty; + int wildcardIndex = file.IndexOfAny(new char[] { '*', '?' }); + if (wildcardIndex != -1) + { + chunkWithoutWildcards = file.Substring(0, wildcardIndex); + chunkWithWildcards = file.Substring(wildcardIndex); + } + string path = Path.Combine(basepath, chunkWithoutWildcards); + path = Path.GetFullPath(path) + chunkWithWildcards; + string[] paths = Util.Glob(path); + + // If the include path contains no wildcards, then warn the user that it wasn't found. + if (wildcardIndex == -1 && paths.Length == 0) + { + Console.WriteLine("[CONFIG]: Could not find include file {0}", path); + } + else + { + foreach (string p in paths) + { + if (!sources.Contains(p)) + { + sourcesAdded = true; + sources.Add(p); + } + } + } + } + } + } + } + + return sourcesAdded; + } + + /// + /// Check if we can convert the string to a URI + /// + /// String uri to the remote resource + /// true if we can convert the string to a Uri object + bool IsUri(string file) + { + Uri configUri; + + return Uri.TryCreate(file, UriKind.Absolute, + out configUri) && configUri.Scheme == Uri.UriSchemeHttp; + } + + IConfigSource ReadConfigSource(string iniFile) + { + // Find out of the file name is a URI and remote load it if possible. + // Load it as a local file otherwise. + Uri configUri; + IConfigSource s = null; + + try + { + if (Uri.TryCreate(iniFile, UriKind.Absolute, out configUri) && + configUri.Scheme == Uri.UriSchemeHttp) + { + XmlReader r = XmlReader.Create(iniFile); + s = new XmlConfigSource(r); + } + else + { + s = new IniConfigSource(iniFile); + } + } + catch (Exception e) + { + System.Console.WriteLine("Error reading from config source. {0}", e.Message); + Environment.Exit(1); + } + + return s; + } } } diff --git a/OpenSim/Server/Handlers/AgentPreferences/AgentPreferencesServerPostHandler.cs b/OpenSim/Server/Handlers/AgentPreferences/AgentPreferencesServerPostHandler.cs index 713b755..b1b3c6f 100644 --- a/OpenSim/Server/Handlers/AgentPreferences/AgentPreferencesServerPostHandler.cs +++ b/OpenSim/Server/Handlers/AgentPreferences/AgentPreferencesServerPostHandler.cs @@ -106,7 +106,8 @@ namespace OpenSim.Server.Handlers.AgentPreferences return FailureResult(); AgentPrefs prefs = m_AgentPreferencesService.GetAgentPreferences(userID); Dictionary result = new Dictionary(); - result = prefs.ToKeyValuePairs(); + if (prefs != null) + result = prefs.ToKeyValuePairs(); string xmlString = ServerUtils.BuildXmlResponse(result); diff --git a/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs b/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs index ab81dd6..bad3ea2 100644 --- a/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs +++ b/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs @@ -151,27 +151,27 @@ namespace OpenSim.Server.Handlers.Asset MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid ID format", rawAssetId); return; } - + AssetBase asset = m_AssetService.Get(assetId.ToString()); if (asset == null) - { + { MainConsole.Instance.OutputFormat("ERROR: No asset found with ID {0}", assetId); - return; + return; } - + string fileName = rawAssetId; if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, fileName)) return; - + using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) { using (BinaryWriter bw = new BinaryWriter(fs)) { bw.Write(asset.Data); } - } - + } + MainConsole.Instance.OutputFormat("Asset dumped to file {0}", fileName); } diff --git a/OpenSim/Server/Handlers/Asset/AssetServerGetHandler.cs b/OpenSim/Server/Handlers/Asset/AssetServerGetHandler.cs index 91c5c54..8bfc690 100644 --- a/OpenSim/Server/Handlers/Asset/AssetServerGetHandler.cs +++ b/OpenSim/Server/Handlers/Asset/AssetServerGetHandler.cs @@ -53,7 +53,7 @@ namespace OpenSim.Server.Handlers.Asset public AssetServerGetHandler(IAssetService service) : base("GET", "/assets") { - m_AssetService = service; + m_AssetService = service; } public AssetServerGetHandler(IAssetService service, IServiceAuth auth, string redirectURL) : @@ -155,7 +155,7 @@ namespace OpenSim.Server.Handlers.Asset httpResponse.ContentType = "text/plain"; result = new byte[0]; } - + if (httpResponse.StatusCode == (int)HttpStatusCode.NotFound && !string.IsNullOrEmpty(m_RedirectURL) && !string.IsNullOrEmpty(id)) { httpResponse.StatusCode = (int)HttpStatusCode.Redirect; diff --git a/OpenSim/Server/Handlers/Asset/Tests/AssetServerPostHandlerTests.cs b/OpenSim/Server/Handlers/Asset/Tests/AssetServerPostHandlerTests.cs index faa6fb7..4d2228a 100644 --- a/OpenSim/Server/Handlers/Asset/Tests/AssetServerPostHandlerTests.cs +++ b/OpenSim/Server/Handlers/Asset/Tests/AssetServerPostHandlerTests.cs @@ -52,8 +52,8 @@ namespace OpenSim.Server.Handlers.Asset.Test UUID assetId = TestHelpers.ParseTail(0x1); - IConfigSource config = new IniConfigSource(); - config.AddConfig("AssetService"); + IConfigSource config = new IniConfigSource(); + config.AddConfig("AssetService"); config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); AssetService assetService = new AssetService(config); @@ -72,7 +72,7 @@ namespace OpenSim.Server.Handlers.Asset.Test XmlSerializer serializer = new XmlSerializer(typeof(AssetBase)); serializer.Serialize(writer, asset); writer.Flush(); - } + } buffer.Position = 0; asph.Handle(null, buffer, null, null); @@ -87,13 +87,13 @@ namespace OpenSim.Server.Handlers.Asset.Test { TestHelpers.InMethod(); - IConfigSource config = new IniConfigSource(); - config.AddConfig("AssetService"); + IConfigSource config = new IniConfigSource(); + config.AddConfig("AssetService"); config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); AssetService assetService = new AssetService(config); - AssetServerPostHandler asph = new AssetServerPostHandler(assetService); + AssetServerPostHandler asph = new AssetServerPostHandler(assetService); MemoryStream buffer = new MemoryStream(); byte[] badData = new byte[] { 0x48, 0x65, 0x6c, 0x6c, 0x6f }; diff --git a/OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs b/OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs index 6ee98b3..4f03cf4 100644 --- a/OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs @@ -82,11 +82,11 @@ namespace OpenSim.Server.Handlers.Authentication switch (p[0]) { case "plain": - StreamReader sr = new StreamReader(request); - string body = sr.ReadToEnd(); - sr.Close(); - + string body; + using(StreamReader sr = new StreamReader(request)) + body = sr.ReadToEnd(); return DoPlainMethods(body); + case "crypt": byte[] buffer = new byte[request.Length]; long length = request.Length; @@ -132,41 +132,41 @@ namespace OpenSim.Server.Handlers.Authentication case "authenticate": if (!request.ContainsKey("PASSWORD")) return FailureResult(); - + token = m_AuthenticationService.Authenticate(principalID, request["PASSWORD"].ToString(), lifetime); - + if (token != String.Empty) return SuccessResult(token); return FailureResult(); - + case "setpassword": if (!m_AllowSetPassword) return FailureResult(); if (!request.ContainsKey("PASSWORD")) return FailureResult(); - + if (m_AuthenticationService.SetPassword(principalID, request["PASSWORD"].ToString())) return SuccessResult(); else return FailureResult(); - + case "verify": if (!request.ContainsKey("TOKEN")) return FailureResult(); - + if (m_AuthenticationService.Verify(principalID, request["TOKEN"].ToString(), lifetime)) return SuccessResult(); - + return FailureResult(); - + case "release": if (!request.ContainsKey("TOKEN")) return FailureResult(); - + if (m_AuthenticationService.Release(principalID, request["TOKEN"].ToString())) return SuccessResult(); - + return FailureResult(); case "getauthinfo": diff --git a/OpenSim/Server/Handlers/Authentication/OpenIdServerConnector.cs b/OpenSim/Server/Handlers/Authentication/OpenIdServerConnector.cs index 6464399..ac8ff52 100644 --- a/OpenSim/Server/Handlers/Authentication/OpenIdServerConnector.cs +++ b/OpenSim/Server/Handlers/Authentication/OpenIdServerConnector.cs @@ -41,7 +41,7 @@ namespace OpenSim.Server.Handlers.Authentication private static readonly ILog m_log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); - + private IAuthenticationService m_AuthenticationService; private IUserAccountService m_UserAccountService; private string m_ConfigName = "OpenIdService"; diff --git a/OpenSim/Server/Handlers/Authentication/OpenIdServerHandler.cs b/OpenSim/Server/Handlers/Authentication/OpenIdServerHandler.cs index b201dc7..254b82f 100644 --- a/OpenSim/Server/Handlers/Authentication/OpenIdServerHandler.cs +++ b/OpenSim/Server/Handlers/Authentication/OpenIdServerHandler.cs @@ -178,14 +178,14 @@ namespace OpenSim.Server.Handlers.Authentication "; /// Page shown for an invalid OpenID identity - const string INVALID_OPENID_PAGE = + const string INVALID_OPENID_PAGE = @"Identity not found Invalid OpenID identity"; /// Page shown if the OpenID endpoint is requested directly const string ENDPOINT_PAGE = @"OpenID Endpoint -This is an OpenID server endpoint, not a human-readable resource. +This is an OpenID server endpoint, not a human-readable resource. For more information, see http://openid.net/. "; @@ -222,7 +222,10 @@ For more information, see http://openid.net/. try { - NameValueCollection postQuery = HttpUtility.ParseQueryString(new StreamReader(httpRequest.InputStream).ReadToEnd()); + string forPost; + using(StreamReader sr = new StreamReader(httpRequest.InputStream)) + forPost = sr.ReadToEnd(); + NameValueCollection postQuery = HttpUtility.ParseQueryString(forPost); NameValueCollection getQuery = HttpUtility.ParseQueryString(httpRequest.Url.Query); NameValueCollection openIdQuery = (postQuery.GetValues("openid.mode") != null ? postQuery : getQuery); @@ -241,7 +244,7 @@ For more information, see http://openid.net/. // Check for form POST data if (passwordValues != null && passwordValues.Length == 1) { - if (account != null && + if (account != null && (m_authenticationService.Authenticate(account.PrincipalID,Util.Md5Hash(passwordValues[0]), 30) != string.Empty)) authRequest.IsAuthenticated = true; else diff --git a/OpenSim/Server/Handlers/Authorization/AuthorizationServerPostHandler.cs b/OpenSim/Server/Handlers/Authorization/AuthorizationServerPostHandler.cs index c9b4e9b..310a542 100644 --- a/OpenSim/Server/Handlers/Authorization/AuthorizationServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Authorization/AuthorizationServerPostHandler.cs @@ -67,7 +67,7 @@ namespace OpenSim.Server.Handlers.Authorization xs = new XmlSerializer(typeof(AuthorizationResponse)); return ServerUtils.SerializeResult(xs, result); - + } } } diff --git a/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs b/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs index ff8699f..b8fdacf 100644 --- a/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs @@ -60,9 +60,9 @@ namespace OpenSim.Server.Handlers.Avatar protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); @@ -175,7 +175,7 @@ namespace OpenSim.Server.Handlers.Avatar request.Remove("METHOD"); request.Remove("UserID"); } - + byte[] SetItems(Dictionary request) { UUID user = UUID.Zero; @@ -196,7 +196,7 @@ namespace OpenSim.Server.Handlers.Avatar names = _names.ToArray(); List _values = (List)request["Values"]; values = _values.ToArray(); - + if (m_AvatarService.SetItems(user, names, values)) return SuccessResult(); @@ -227,7 +227,7 @@ namespace OpenSim.Server.Handlers.Avatar } - + private byte[] SuccessResult() { XmlDocument doc = new XmlDocument(); diff --git a/OpenSim/Server/Handlers/BakedTextures/XBakes.cs b/OpenSim/Server/Handlers/BakedTextures/XBakes.cs index abcda62..4e55433 100644 --- a/OpenSim/Server/Handlers/BakedTextures/XBakes.cs +++ b/OpenSim/Server/Handlers/BakedTextures/XBakes.cs @@ -70,9 +70,9 @@ namespace OpenSim.Server.Handlers.BakedTextures m_FSBase = assetConfig.GetString("BaseDirectory", String.Empty); if (m_FSBase == String.Empty) { - m_FSBase = "bakes"; + m_log.ErrorFormat("[BAKES]: BaseDirectory not specified"); + throw new Exception("Configuration error"); } - m_FSBase = "../caches/" + m_FSBase; m_log.Info("[BAKES]: XBakes service enabled"); } diff --git a/OpenSim/Server/Handlers/BakedTextures/XBakesHandler.cs b/OpenSim/Server/Handlers/BakedTextures/XBakesHandler.cs index 4c12967..4386a2d 100644 --- a/OpenSim/Server/Handlers/BakedTextures/XBakesHandler.cs +++ b/OpenSim/Server/Handlers/BakedTextures/XBakesHandler.cs @@ -61,7 +61,7 @@ namespace OpenSim.Server.Handlers.BakedTextures ServerUtils.LoadPlugin(assetService, args); IServiceAuth auth = ServiceAuth.Create(config, m_ConfigName); - + server.AddStreamHandler(new BakesServerGetHandler(m_BakesService, auth)); server.AddStreamHandler(new BakesServerPostHandler(m_BakesService, auth)); } diff --git a/OpenSim/Server/Handlers/BakedTextures/XBakesPostHandler.cs b/OpenSim/Server/Handlers/BakedTextures/XBakesPostHandler.cs index e38543b..d16000d 100644 --- a/OpenSim/Server/Handlers/BakedTextures/XBakesPostHandler.cs +++ b/OpenSim/Server/Handlers/BakedTextures/XBakesPostHandler.cs @@ -65,12 +65,10 @@ namespace OpenSim.Server.Handlers.BakedTextures return new byte[0]; } - StreamReader sr = new StreamReader(request); - - m_BakesService.Store(p[0], sr.ReadToEnd()); - sr.Close(); + using(StreamReader sr = new StreamReader(request)) + m_BakesService.Store(p[0],sr.ReadToEnd()); return new byte[0]; } } -} \ No newline at end of file +} diff --git a/OpenSim/Server/Handlers/Base/ServerConnector.cs b/OpenSim/Server/Handlers/Base/ServerConnector.cs index 72014db..0a4df54 100644 --- a/OpenSim/Server/Handlers/Base/ServerConnector.cs +++ b/OpenSim/Server/Handlers/Base/ServerConnector.cs @@ -72,7 +72,7 @@ namespace OpenSim.Server.Handlers.Base // We call this from our plugin module to get our configuration public IConfig GetConfig() - { + { IConfig config = null; config = ServerUtils.GetConfig(ConfigFile, ConfigName); @@ -96,12 +96,12 @@ namespace OpenSim.Server.Handlers.Base // We get our remote initial configuration for bootstrapping in case // we have no configuration in our main file or in an existing - // modular config file. This is the last resort to bootstrap the + // modular config file. This is the last resort to bootstrap the // configuration, likely a new plugin loading for the first time. private IConfigSource GetConfigSource() { IConfigSource source = null; - + source = ServerUtils.LoadInitialConfig(ConfigURL); if (source == null) diff --git a/OpenSim/Server/Handlers/Estate/EstateDataRobustConnector.cs b/OpenSim/Server/Handlers/Estate/EstateDataRobustConnector.cs index e0c2810..b7558ec 100644 --- a/OpenSim/Server/Handlers/Estate/EstateDataRobustConnector.cs +++ b/OpenSim/Server/Handlers/Estate/EstateDataRobustConnector.cs @@ -282,9 +282,10 @@ namespace OpenSim.Server.Handlers // /estates/estate/?eid=int®ion=uuid if ("estate".Equals(resource)) { - StreamReader sr = new StreamReader(request); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(request)) + body = sr.ReadToEnd(); + body = body.Trim(); Dictionary requestData = ServerUtils.ParseQueryString(body); diff --git a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs index 3aab30b..d6668ab 100644 --- a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs @@ -61,9 +61,9 @@ namespace OpenSim.Server.Handlers.Friends protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); diff --git a/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs b/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs index 346af32..2aec045 100644 --- a/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs +++ b/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs @@ -83,10 +83,10 @@ namespace OpenSim.Server.Handlers.Grid { _info["login"] = String.Format( - "http://127.0.0.1:{0}/", + "http://127.0.0.1:{0}/", netCfg.GetString( "http_listener_port", ConfigSettings.DefaultRegionHttpPort.ToString())); - + IssueWarning(); } else @@ -99,7 +99,7 @@ namespace OpenSim.Server.Handlers.Grid { _log.Warn("[GRID INFO SERVICE]: Cannot get grid info from config source, using minimal defaults"); } - + _log.DebugFormat("[GRID INFO SERVICE]: Grid info service initialized with {0} keys", _info.Count); } @@ -107,7 +107,7 @@ namespace OpenSim.Server.Handlers.Grid { _log.Warn("[GRID INFO SERVICE]: found no [GridInfo] section in your configuration files"); _log.Warn("[GRID INFO SERVICE]: trying to guess sensible defaults, you might want to provide better ones:"); - + foreach (string k in _info.Keys) { _log.WarnFormat("[GRID INFO SERVICE]: {0}: {1}", k, _info[k]); @@ -181,7 +181,7 @@ namespace OpenSim.Server.Handlers.Grid new string[] { "Startup", "Hypergrid" }, String.Empty); if (!String.IsNullOrEmpty(HomeURI)) - map["home"] = OSD.FromString(HomeURI); + map["home"] = OSD.FromString(HomeURI); else // Legacy. Remove soon! { IConfig cfg = m_Config.Configs["LoginService"]; diff --git a/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs b/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs index 86fda36..44d4654 100644 --- a/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs @@ -65,9 +65,9 @@ namespace OpenSim.Server.Handlers.Grid protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); @@ -126,7 +126,7 @@ namespace OpenSim.Server.Handlers.Grid case "get_grid_extra_features": return GetGridExtraFeatures(request); } - + m_log.DebugFormat("[GRID HANDLER]: unknown method request {0}", method); } catch (Exception e) @@ -579,33 +579,33 @@ namespace OpenSim.Server.Handlers.Grid if (request.ContainsKey("SCOPEID")) UUID.TryParse(request["SCOPEID"].ToString(), out scopeID); else - m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get neighbours"); + m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get RegionFlags"); UUID regionID = UUID.Zero; if (request.ContainsKey("REGIONID")) UUID.TryParse(request["REGIONID"].ToString(), out regionID); else - m_log.WarnFormat("[GRID HANDLER]: no regionID in request to get neighbours"); + m_log.WarnFormat("[GRID HANDLER]: no regionID in request to get RegionFlags"); int flags = m_GridService.GetRegionFlags(scopeID, regionID); // m_log.DebugFormat("[GRID HANDLER]: flags for region {0}: {1}", regionID, flags); - Dictionary result = new Dictionary(); + Dictionary result = new Dictionary(); result["result"] = flags.ToString(); string xmlString = ServerUtils.BuildXmlResponse(result); - + //m_log.DebugFormat("[GRID HANDLER]: resp string: {0}", xmlString); return Util.UTF8NoBomEncoding.GetBytes(xmlString); } - + byte[] GetGridExtraFeatures(Dictionary request) { Dictionary result = new Dictionary (); Dictionary extraFeatures = m_GridService.GetExtraFeatures (); - foreach (string key in extraFeatures.Keys) + foreach (string key in extraFeatures.Keys) { result [key] = extraFeatures [key]; } diff --git a/OpenSim/Server/Handlers/GridUser/GridUserServerConnector.cs b/OpenSim/Server/Handlers/GridUser/GridUserServerConnector.cs index 1e29378..755272b 100644 --- a/OpenSim/Server/Handlers/GridUser/GridUserServerConnector.cs +++ b/OpenSim/Server/Handlers/GridUser/GridUserServerConnector.cs @@ -56,7 +56,7 @@ namespace OpenSim.Server.Handlers.GridUser Object[] args = new Object[] { config }; m_GridUserService = ServerUtils.LoadPlugin(service, args); - IServiceAuth auth = ServiceAuth.Create(config, m_ConfigName); ; + IServiceAuth auth = ServiceAuth.Create(config, m_ConfigName); server.AddStreamHandler(new GridUserServerPostHandler(m_GridUserService, auth)); } diff --git a/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs b/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs index 9237c63..1f691d6 100644 --- a/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs +++ b/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs @@ -60,9 +60,9 @@ namespace OpenSim.Server.Handlers.GridUser protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); @@ -185,6 +185,9 @@ namespace OpenSim.Server.Handlers.GridUser GridUserInfo guinfo = m_GridUserService.GetGridUserInfo(user); + if (guinfo == null) + return FailureResult(); + Dictionary result = new Dictionary(); if (guinfo != null) result["result"] = guinfo.ToKeyValuePairs(); @@ -225,6 +228,8 @@ namespace OpenSim.Server.Handlers.GridUser int i = 0; foreach (GridUserInfo pinfo in pinfos) { + if(pinfo == null) + continue; Dictionary rinfoDict = pinfo.ToKeyValuePairs(); result["griduser" + i] = rinfoDict; i++; diff --git a/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs index 95a0510..684d1a8 100644 --- a/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs +++ b/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs @@ -52,7 +52,7 @@ namespace OpenSim.Server.Handlers.Hypergrid public class GatekeeperAgentHandler : OpenSim.Server.Handlers.Simulation.AgentPostHandler { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - + private IGatekeeperService m_GatekeeperService; public GatekeeperAgentHandler(IGatekeeperService gatekeeper, bool proxy) : base("/foreignagent") @@ -62,7 +62,7 @@ namespace OpenSim.Server.Handlers.Hypergrid } protected override bool CreateAgent(GridRegion source, GridRegion gatekeeper, GridRegion destination, - AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason) + AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, EntityTransferContext ctx, out string reason) { return m_GatekeeperService.LoginAgent(source, aCircuit, destination, out reason); } diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs index 6c79c60..870a5ef 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs @@ -48,7 +48,7 @@ namespace OpenSim.Server.Handlers.Hypergrid } // Called from standalone configurations - public HGFriendsServerConnector(IConfigSource config, IHttpServer server, string configName, IFriendsSimConnector localConn) + public HGFriendsServerConnector(IConfigSource config, IHttpServer server, string configName, IFriendsSimConnector localConn) : base(config, server, configName) { if (configName != string.Empty) diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs index 37b47ed..fc1a77d 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs @@ -61,7 +61,7 @@ namespace OpenSim.Server.Handlers.Hypergrid m_UserAgentService = uas; m_FriendsLocalSimConnector = friendsConn; - m_log.DebugFormat("[HGFRIENDS HANDLER]: HGFriendsServerPostHandler is On ({0})", + m_log.DebugFormat("[HGFRIENDS HANDLER]: HGFriendsServerPostHandler is On ({0})", (m_FriendsLocalSimConnector == null ? "robust" : "standalone")); if (m_TheService == null) @@ -71,9 +71,9 @@ namespace OpenSim.Server.Handlers.Hypergrid protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); @@ -105,24 +105,24 @@ namespace OpenSim.Server.Handlers.Hypergrid case "validate_friendship_offered": return ValidateFriendshipOffered(request); - + case "statusnotification": return StatusNotification(request); /* case "friendship_approved": return FriendshipApproved(request); - + case "friendship_denied": return FriendshipDenied(request); - + case "friendship_terminated": return FriendshipTerminated(request); - + case "grant_rights": return GrantRights(request); */ } - + m_log.DebugFormat("[HGFRIENDS HANDLER]: unknown method {0}", method); } catch (Exception e) diff --git a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs index e787f7c..367c481 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs @@ -118,7 +118,7 @@ namespace OpenSim.Server.Handlers.Hypergrid protected override bool CreateAgent(GridRegion source, GridRegion gatekeeper, GridRegion destination, - AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason) + AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, EntityTransferContext ctx, out string reason) { return m_UserAgentService.LoginAgentToGrid(source, aCircuit, gatekeeper, destination, fromLogin, out reason); } diff --git a/OpenSim/Server/Handlers/Hypergrid/HypergridHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/HypergridHandlers.cs index c7ac9be..6bd24db 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HypergridHandlers.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HypergridHandlers.cs @@ -70,13 +70,17 @@ namespace OpenSim.Server.Handlers.Hypergrid string imageURL = string.Empty; ulong regionHandle = 0; string reason = string.Empty; + int sizeX = 256; + int sizeY = 256; - bool success = m_GatekeeperService.LinkRegion(name, out regionID, out regionHandle, out externalName, out imageURL, out reason); + bool success = m_GatekeeperService.LinkRegion(name, out regionID, out regionHandle, out externalName, out imageURL, out reason, out sizeX, out sizeY); Hashtable hash = new Hashtable(); hash["result"] = success.ToString(); hash["uuid"] = regionID.ToString(); hash["handle"] = regionHandle.ToString(); + hash["size_x"] = sizeX.ToString(); + hash["size_y"] = sizeY.ToString(); hash["region_image"] = imageURL; hash["external_name"] = externalName; @@ -121,6 +125,7 @@ namespace OpenSim.Server.Handlers.Hypergrid hash["hostname"] = regInfo.ExternalHostName; hash["http_port"] = regInfo.HttpPort.ToString(); hash["internal_port"] = regInfo.InternalEndPoint.Port.ToString(); + hash["server_uri"] = regInfo.ServerURI; } if (message != null) diff --git a/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs index 8145a21..63f376d 100644 --- a/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs @@ -55,7 +55,7 @@ namespace OpenSim.Server.Handlers.Hypergrid public InstantMessageServerConnector(IConfigSource config, IHttpServer server) : this(config, server, (IInstantMessageSimConnector)null) - { + { } public InstantMessageServerConnector(IConfigSource config, IHttpServer server, string configName) : diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs index e112e0e..394b133 100644 --- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs @@ -63,14 +63,14 @@ namespace OpenSim.Server.Handlers.Hypergrid public UserAgentServerConnector(IConfigSource config, IHttpServer server) : this(config, server, (IFriendsSimConnector)null) - { + { } public UserAgentServerConnector(IConfigSource config, IHttpServer server, string configName) : this(config, server) { } - + public UserAgentServerConnector(IConfigSource config, IHttpServer server, IFriendsSimConnector friendsConnector) : base(config, server, String.Empty) { @@ -139,6 +139,7 @@ namespace OpenSim.Server.Handlers.Hypergrid hash["region_name"] = regInfo.RegionName; hash["hostname"] = regInfo.ExternalHostName; hash["http_port"] = regInfo.HttpPort.ToString(); + hash["server_uri"] = regInfo.ServerURI; hash["internal_port"] = regInfo.InternalEndPoint.Port.ToString(); hash["position"] = position.ToString(); hash["lookAt"] = lookAt.ToString(); diff --git a/OpenSim/Server/Handlers/Inventory/InventoryServerInConnector.cs b/OpenSim/Server/Handlers/Inventory/InventoryServerInConnector.cs index b295446..e90b869 100644 --- a/OpenSim/Server/Handlers/Inventory/InventoryServerInConnector.cs +++ b/OpenSim/Server/Handlers/Inventory/InventoryServerInConnector.cs @@ -61,7 +61,7 @@ namespace OpenSim.Server.Handlers.Inventory { if (configName != string.Empty) m_ConfigName = configName; - + IConfig serverConfig = config.Configs[m_ConfigName]; if (serverConfig == null) throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName)); @@ -92,7 +92,7 @@ namespace OpenSim.Server.Handlers.Inventory m_httpServer.AddStreamHandler( new RestDeserialiseSecureHandler( "POST", "/GetFolderContent/", GetFolderContent, CheckAuthSession)); - + m_httpServer.AddStreamHandler( new RestDeserialiseSecureHandler( "POST", "/UpdateFolder/", m_InventoryService.UpdateFolder, CheckAuthSession)); @@ -114,12 +114,12 @@ namespace OpenSim.Server.Handlers.Inventory "POST", "/DeleteItem/", DeleteItems, CheckAuthSession)); m_httpServer.AddStreamHandler( - new RestDeserialiseSecureHandler( - "POST", "/QueryItem/", m_InventoryService.GetItem, CheckAuthSession)); + new RestDeserialiseSecureHandler( + "POST", "/QueryItem/", GetItem, CheckAuthSession)); m_httpServer.AddStreamHandler( - new RestDeserialiseSecureHandler( - "POST", "/QueryFolder/", m_InventoryService.GetFolder, CheckAuthSession)); + new RestDeserialiseSecureHandler( + "POST", "/QueryFolder/", GetFolder, CheckAuthSession)); m_httpServer.AddStreamHandler( new RestDeserialiseTrustedHandler( @@ -151,7 +151,7 @@ namespace OpenSim.Server.Handlers.Inventory m_httpServer.AddStreamHandler(new InventoryServerMoveItemsHandler(m_InventoryService)); - + // for persistent active gestures m_httpServer.AddStreamHandler( new RestDeserialiseTrustedHandler> @@ -205,6 +205,16 @@ namespace OpenSim.Server.Handlers.Inventory return new Dictionary(); } + public InventoryItemBase GetItem(Guid guid) + { + return m_InventoryService.GetItem(UUID.Zero, new UUID(guid)); + } + + public InventoryFolderBase GetFolder(Guid guid) + { + return m_InventoryService.GetFolder(UUID.Zero, new UUID(guid)); + } + public InventoryCollection GetFolderContent(Guid guid) { return m_InventoryService.GetFolderContent(UUID.Zero, new UUID(guid)); diff --git a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs index 5c4e7a9..742d1a0 100644 --- a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs +++ b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs @@ -95,9 +95,9 @@ namespace OpenSim.Server.Handlers.Inventory protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); @@ -293,7 +293,7 @@ namespace OpenSim.Server.Handlers.Inventory result["FID"] = icoll.FolderID.ToString(); result["VERSION"] = icoll.Version.ToString(); Dictionary folders = new Dictionary(); - int i = 0; + int i = 0; if (icoll.Folders != null) { foreach (InventoryFolderBase f in icoll.Folders) @@ -407,7 +407,7 @@ namespace OpenSim.Server.Handlers.Inventory } } result["ITEMS"] = sitems; - + string xmlString = ServerUtils.BuildXmlResponse(result); //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); @@ -566,9 +566,11 @@ namespace OpenSim.Server.Handlers.Inventory Dictionary result = new Dictionary(); UUID id = UUID.Zero; UUID.TryParse(request["ID"].ToString(), out id); + UUID user = UUID.Zero; + if (request.ContainsKey("PRINCIPAL")) + UUID.TryParse(request["PRINCIPAL"].ToString(), out user); - InventoryItemBase item = new InventoryItemBase(id); - item = m_InventoryService.GetItem(item); + InventoryItemBase item = m_InventoryService.GetItem(user, id); if (item != null) result["item"] = EncodeItem(item); @@ -617,9 +619,11 @@ namespace OpenSim.Server.Handlers.Inventory Dictionary result = new Dictionary(); UUID id = UUID.Zero; UUID.TryParse(request["ID"].ToString(), out id); + UUID user = UUID.Zero; + if (request.ContainsKey("PRINCIPAL")) + UUID.TryParse(request["PRINCIPAL"].ToString(), out user); - InventoryFolderBase folder = new InventoryFolderBase(id); - folder = m_InventoryService.GetFolder(folder); + InventoryFolderBase folder = m_InventoryService.GetFolder(user, id); if (folder != null) result["folder"] = EncodeFolder(folder); diff --git a/OpenSim/Server/Handlers/Land/LandHandlers.cs b/OpenSim/Server/Handlers/Land/LandHandlers.cs index b45289a..d74077a 100644 --- a/OpenSim/Server/Handlers/Land/LandHandlers.cs +++ b/OpenSim/Server/Handlers/Land/LandHandlers.cs @@ -64,7 +64,7 @@ namespace OpenSim.Server.Handlers.Land ulong regionHandle = Convert.ToUInt64(requestData["region_handle"]); uint x = Convert.ToUInt32(requestData["x"]); uint y = Convert.ToUInt32(requestData["y"]); - m_log.DebugFormat("[LAND HANDLER]: Got request for land data at {0}, {1} for region {2}", x, y, regionHandle); +// m_log.DebugFormat("[LAND HANDLER]: Got request for land data at {0}, {1} for region {2}", x, y, regionHandle); byte regionAccess; LandData landData = m_LocalService.GetLandData(UUID.Zero, regionHandle, x, y, out regionAccess); @@ -85,6 +85,7 @@ namespace OpenSim.Server.Handlers.Land hash["SnapshotID"] = landData.SnapshotID.ToString(); hash["UserLocation"] = landData.UserLocation.ToString(); hash["RegionAccess"] = regionAccess.ToString(); + hash["Dwell"] = landData.Dwell.ToString(); } XmlRpcResponse response = new XmlRpcResponse(); diff --git a/OpenSim/Server/Handlers/Land/LandServiceInConnector.cs b/OpenSim/Server/Handlers/Land/LandServiceInConnector.cs index d368bd3..c4b339f 100644 --- a/OpenSim/Server/Handlers/Land/LandServiceInConnector.cs +++ b/OpenSim/Server/Handlers/Land/LandServiceInConnector.cs @@ -54,7 +54,7 @@ namespace OpenSim.Server.Handlers.Land m_log.Error("[LAND IN CONNECTOR]: Land service was not provided"); return; } - + //bool authentication = neighbourConfig.GetBoolean("RequireAuthentication", false); //if (authentication) // m_AuthenticationService = scene.RequestModuleInterface(); diff --git a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs index f2a5678..4e7ab00 100644 --- a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs +++ b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs @@ -53,7 +53,7 @@ namespace OpenSim.Server.Handlers.Login private ILoginService m_LocalService; private bool m_Proxy; - + public LLLoginHandlers(ILoginService service, bool hasProxy) { @@ -64,7 +64,7 @@ namespace OpenSim.Server.Handlers.Login public XmlRpcResponse HandleXMLRPCLogin(XmlRpcRequest request, IPEndPoint remoteClient) { Hashtable requestData = (Hashtable)request.Params[0]; - if (m_Proxy && request.Params[3] != null) + if (request.Params[3] != null) { IPEndPoint ep = Util.GetClientIPFromXFF((string)request.Params[3]); if (ep != null) @@ -132,8 +132,13 @@ namespace OpenSim.Server.Handlers.Login //m_log.InfoFormat("[LOGIN]: XMLRPC Login Requested for {0} {1}, starting in {2}, using {3}", first, last, startLocation, clientVersion); + + bool LibOMVclient = false; + if (request.Params.Count > 4 && (string)request.Params[4] == "gridproxy") + LibOMVclient = true; + LoginResponse reply = null; - reply = m_LocalService.Login(first, last, passwd, startLocation, scopeID, clientVersion, channel, mac, id0, remoteClient); + reply = m_LocalService.Login(first, last, passwd, startLocation, scopeID, clientVersion, channel, mac, id0, remoteClient, LibOMVclient); XmlRpcResponse response = new XmlRpcResponse(); response.Value = reply.ToHashtable(); @@ -216,7 +221,7 @@ namespace OpenSim.Server.Handlers.Login LoginResponse reply = null; reply = m_LocalService.Login(map["first"].AsString(), map["last"].AsString(), map["passwd"].AsString(), startLocation, scopeID, - map["version"].AsString(), map["channel"].AsString(), map["mac"].AsString(), map["id0"].AsString(), remoteClient); + map["version"].AsString(), map["channel"].AsString(), map["mac"].AsString(), map["id0"].AsString(), remoteClient,false); return reply.ToOSDMap(); } @@ -259,7 +264,7 @@ namespace OpenSim.Server.Handlers.Login (sender as WebSocketHttpServerHandler).GetRemoteIPEndpoint(); LoginResponse reply = null; reply = m_LocalService.Login(first, last, passwd, start, scope, version, - channel, mac, id0, endPoint); + channel, mac, id0, endPoint,false); sock.SendMessage(OSDParser.SerializeJsonString(reply.ToOSDMap())); } @@ -274,11 +279,11 @@ namespace OpenSim.Server.Handlers.Login sock.Close("success"); } }; - + sock.HandshakeAndUpgrade(); } - + private XmlRpcResponse FailedXMLRPCResponse() { diff --git a/OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs b/OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs index f60e892..56ac3c2 100644 --- a/OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs +++ b/OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs @@ -98,7 +98,7 @@ namespace OpenSim.Server.Handlers.Login m_DosProtectionOptions.ForgetTimeSpan = TimeSpan.FromMilliseconds(serverConfig.GetInt("DOSForgiveClientAfterMS", 120000)); m_DosProtectionOptions.ReportingName = "LOGINDOSPROTECTION"; - + return loginService; } @@ -106,7 +106,7 @@ namespace OpenSim.Server.Handlers.Login private void InitializeHandlers(IHttpServer server) { LLLoginHandlers loginHandlers = new LLLoginHandlers(m_LoginService, m_Proxy); - server.AddXmlRPCHandler("login_to_simulator", + server.AddXmlRPCHandler("login_to_simulator", new XmlRpcBasicDOSProtector(loginHandlers.HandleXMLRPCLogin,loginHandlers.HandleXMLRPCLoginBlocked, m_DosProtectionOptions).Process, false); server.AddXmlRPCHandler("set_login_level", loginHandlers.HandleXMLRPCSetLoginLevel, false); diff --git a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs index 649a27e..331dabf 100644 --- a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs +++ b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs @@ -104,9 +104,9 @@ namespace OpenSim.Server.Handlers.MapImage protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { // m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: Received {0}", path); - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); try @@ -118,9 +118,13 @@ namespace OpenSim.Server.Handlers.MapImage httpResponse.StatusCode = (int)OSHttpStatusCode.ClientErrorBadRequest; return FailureResult("Bad request."); } - uint x = 0, y = 0; - UInt32.TryParse(request["X"].ToString(), out x); - UInt32.TryParse(request["Y"].ToString(), out y); + int x = 0, y = 0; +// UUID scopeID = new UUID("07f8d88e-cd5e-4239-a0ed-843f75d09992"); + UUID scopeID = UUID.Zero; + Int32.TryParse(request["X"].ToString(), out x); + Int32.TryParse(request["Y"].ToString(), out y); + if (request.ContainsKey("SCOPE")) + UUID.TryParse(request["SCOPE"].ToString(), out scopeID); m_log.DebugFormat("[MAP ADD SERVER CONNECTOR]: Received map data for region at {0}-{1}", x, y); @@ -132,7 +136,7 @@ namespace OpenSim.Server.Handlers.MapImage if (m_GridService != null) { System.Net.IPAddress ipAddr = GetCallerIP(httpRequest); - GridRegion r = m_GridService.GetRegionByPosition(UUID.Zero, (int)Util.RegionToWorldLoc(x), (int)Util.RegionToWorldLoc(y)); + GridRegion r = m_GridService.GetRegionByPosition(UUID.Zero, (int)Util.RegionToWorldLoc((uint)x), (int)Util.RegionToWorldLoc((uint)y)); if (r != null) { if (r.ExternalEndPoint.Address.ToString() != ipAddr.ToString()) @@ -144,7 +148,7 @@ namespace OpenSim.Server.Handlers.MapImage } else { - m_log.WarnFormat("[MAP IMAGE HANDLER]: IP address {0} may be rogue. Region not found at coordinates {1}-{2}", + m_log.WarnFormat("[MAP IMAGE HANDLER]: IP address {0} may be rogue. Region not found at coordinates {1}-{2}", ipAddr, x, y); return FailureResult("Region not found at given coordinates"); } @@ -153,7 +157,8 @@ namespace OpenSim.Server.Handlers.MapImage byte[] data = Convert.FromBase64String(request["DATA"].ToString()); string reason = string.Empty; - bool result = m_MapService.AddMapTile((int)x, (int)y, data, out reason); + + bool result = m_MapService.AddMapTile((int)x, (int)y, data, scopeID, out reason); if (result) return SuccessResult(); @@ -220,8 +225,8 @@ namespace OpenSim.Server.Handlers.MapImage private System.Net.IPAddress GetCallerIP(IOSHttpRequest request) { - if (!m_Proxy) - return request.RemoteIPEndPoint.Address; +// if (!m_Proxy) +// return request.RemoteIPEndPoint.Address; // We're behind a proxy string xff = "X-Forwarded-For"; @@ -231,7 +236,7 @@ namespace OpenSim.Server.Handlers.MapImage if (xffValue == null || (xffValue != null && xffValue == string.Empty)) { - m_log.WarnFormat("[MAP IMAGE HANDLER]: No XFF header"); +// m_log.WarnFormat("[MAP IMAGE HANDLER]: No XFF header"); return request.RemoteIPEndPoint.Address; } diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs index 7bb2f39..1ae669c 100644 --- a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs +++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs @@ -29,6 +29,7 @@ using System; using System.IO; using System.Net; using System.Reflection; +using System.Threading; using Nini.Config; using log4net; @@ -37,6 +38,7 @@ using OpenSim.Server.Base; using OpenSim.Services.Interfaces; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Server.Handlers.Base; +using OpenMetaverse; namespace OpenSim.Server.Handlers.MapImage { @@ -70,6 +72,8 @@ namespace OpenSim.Server.Handlers.MapImage class MapServerGetHandler : BaseStreamHandler { + public static ManualResetEvent ev = new ManualResetEvent(true); + // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private IMapImageService m_MapService; @@ -82,10 +86,25 @@ namespace OpenSim.Server.Handlers.MapImage protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - byte[] result = new byte[0]; + ev.WaitOne(); + lock (ev) + { + ev.Reset(); + } + byte[] result = new byte[0]; string format = string.Empty; - result = m_MapService.GetMapTile(path.Trim('/'), out format); + +// UUID scopeID = new UUID("07f8d88e-cd5e-4239-a0ed-843f75d09992"); + UUID scopeID = UUID.Zero; + + string[] bits = path.Trim('/').Split(new char[] {'/'}); + if (bits.Length > 1) + { + scopeID = new UUID(bits[0]); + path = bits[1]; + } + result = m_MapService.GetMapTile(path.Trim('/'), scopeID, out format); if (result.Length > 0) { httpResponse.StatusCode = (int)HttpStatusCode.OK; @@ -100,6 +119,11 @@ namespace OpenSim.Server.Handlers.MapImage httpResponse.ContentType = "text/plain"; } + lock (ev) + { + ev.Set(); + } + return result; } diff --git a/OpenSim/Server/Handlers/Map/MapRemoveServerConnector.cs b/OpenSim/Server/Handlers/Map/MapRemoveServerConnector.cs new file mode 100644 index 0000000..9daeb73 --- /dev/null +++ b/OpenSim/Server/Handlers/Map/MapRemoveServerConnector.cs @@ -0,0 +1,256 @@ +/* + * 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.IO; +using System.Reflection; +using System.Xml; + +using Nini.Config; +using log4net; +using OpenMetaverse; + +using OpenSim.Framework; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; + +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +namespace OpenSim.Server.Handlers.MapImage +{ + public class MapRemoveServiceConnector : ServiceConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IMapImageService m_MapService; + private IGridService m_GridService; + private string m_ConfigName = "MapImageService"; + + public MapRemoveServiceConnector(IConfigSource config, IHttpServer server, string configName) : + base(config, server, configName) + { + IConfig serverConfig = config.Configs[m_ConfigName]; + if (serverConfig == null) + throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); + + string mapService = serverConfig.GetString("LocalServiceModule", + String.Empty); + + if (mapService == String.Empty) + throw new Exception("No LocalServiceModule in config file"); + + Object[] args = new Object[] { config }; + m_MapService = ServerUtils.LoadPlugin(mapService, args); + + string gridService = serverConfig.GetString("GridService", String.Empty); + if (gridService != string.Empty) + m_GridService = ServerUtils.LoadPlugin(gridService, args); + + if (m_GridService != null) + m_log.InfoFormat("[MAP IMAGE HANDLER]: GridService check is ON"); + else + m_log.InfoFormat("[MAP IMAGE HANDLER]: GridService check is OFF"); + + bool proxy = serverConfig.GetBoolean("HasProxy", false); + server.AddStreamHandler(new MapServerRemoveHandler(m_MapService, m_GridService, proxy)); + + } + } + + class MapServerRemoveHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private IMapImageService m_MapService; + private IGridService m_GridService; + bool m_Proxy; + + public MapServerRemoveHandler(IMapImageService service, IGridService grid, bool proxy) : + base("POST", "/removemap") + { + m_MapService = service; + m_GridService = grid; + m_Proxy = proxy; + } + + public override byte[] Handle(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { +// m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: Received {0}", path); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); + body = body.Trim(); + + try + { + Dictionary request = ServerUtils.ParseQueryString(body); + + if (!request.ContainsKey("X") || !request.ContainsKey("Y")) + { + httpResponse.StatusCode = (int)OSHttpStatusCode.ClientErrorBadRequest; + return FailureResult("Bad request."); + } + int x = 0, y = 0; + Int32.TryParse(request["X"].ToString(), out x); + Int32.TryParse(request["Y"].ToString(), out y); +// UUID scopeID = new UUID("07f8d88e-cd5e-4239-a0ed-843f75d09992"); + UUID scopeID = UUID.Zero; + if (request.ContainsKey("SCOPE")) + UUID.TryParse(request["SCOPE"].ToString(), out scopeID); + + m_log.DebugFormat("[MAP REMOVE SERVER CONNECTOR]: Received position data for region at {0}-{1}", x, y); + + if (m_GridService != null) + { + System.Net.IPAddress ipAddr = GetCallerIP(httpRequest); + GridRegion r = m_GridService.GetRegionByPosition(UUID.Zero, (int)Util.RegionToWorldLoc((uint)x), (int)Util.RegionToWorldLoc((uint)y)); + if (r != null) + { + if (r.ExternalEndPoint.Address.ToString() != ipAddr.ToString()) + { + m_log.WarnFormat("[MAP IMAGE HANDLER]: IP address {0} may be trying to impersonate region in IP {1}", ipAddr, r.ExternalEndPoint.Address); + return FailureResult("IP address of caller does not match IP address of registered region"); + } + + } + else + { + m_log.WarnFormat("[MAP IMAGE HANDLER]: IP address {0} may be rogue. Region not found at coordinates {1}-{2}", + ipAddr, x, y); + return FailureResult("Region not found at given coordinates"); + } + } + + string reason = string.Empty; + bool result = m_MapService.RemoveMapTile(x, y, scopeID, out reason); + + if (result) + return SuccessResult(); + else + return FailureResult(reason); + + } + catch (Exception e) + { + m_log.ErrorFormat("[MAP SERVICE IMAGE HANDLER]: Exception {0} {1}", e.Message, e.StackTrace); + } + + return FailureResult("Unexpected server error"); + } + + private byte[] SuccessResult() + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "Result", ""); + result.AppendChild(doc.CreateTextNode("Success")); + + rootElement.AppendChild(result); + + return DocToBytes(doc); + } + + private byte[] FailureResult(string msg) + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "Result", ""); + result.AppendChild(doc.CreateTextNode("Failure")); + + rootElement.AppendChild(result); + + XmlElement message = doc.CreateElement("", "Message", ""); + message.AppendChild(doc.CreateTextNode(msg)); + + rootElement.AppendChild(message); + + return DocToBytes(doc); + } + + private byte[] DocToBytes(XmlDocument doc) + { + using(MemoryStream ms = new MemoryStream()) + { + using(XmlTextWriter xw = new XmlTextWriter(ms,null)) + { + xw.Formatting = Formatting.Indented; + doc.WriteTo(xw); + xw.Flush(); + } + return ms.ToArray(); + } + } + + private System.Net.IPAddress GetCallerIP(IOSHttpRequest request) + { +// if (!m_Proxy) +// return request.RemoteIPEndPoint.Address; + + // We're behind a proxy + string xff = "X-Forwarded-For"; + string xffValue = request.Headers[xff.ToLower()]; + if (xffValue == null || (xffValue != null && xffValue == string.Empty)) + xffValue = request.Headers[xff]; + + if (xffValue == null || (xffValue != null && xffValue == string.Empty)) + { +// m_log.WarnFormat("[MAP IMAGE HANDLER]: No XFF header"); + return request.RemoteIPEndPoint.Address; + } + + System.Net.IPEndPoint ep = Util.GetClientIPFromXFF(xffValue); + if (ep != null) + return ep.Address; + + // Oops + return request.RemoteIPEndPoint.Address; + } + + } +} diff --git a/OpenSim/Server/Handlers/MuteList/MuteListServerConnector.cs b/OpenSim/Server/Handlers/MuteList/MuteListServerConnector.cs new file mode 100644 index 0000000..8d27f07 --- /dev/null +++ b/OpenSim/Server/Handlers/MuteList/MuteListServerConnector.cs @@ -0,0 +1,63 @@ +/* + * 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 Nini.Config; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.ServiceAuth; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; + +namespace OpenSim.Server.Handlers.GridUser +{ + public class MuteListServiceConnector : ServiceConnector + { + private IMuteListService m_MuteListService; + private string m_ConfigName = "MuteListService"; + + public MuteListServiceConnector(IConfigSource config, IHttpServer server, string configName) : + base(config, server, configName) + { + IConfig serverConfig = config.Configs[m_ConfigName]; + if (serverConfig == null) + throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); + + string service = serverConfig.GetString("LocalServiceModule", String.Empty); + + if (service == String.Empty) + throw new Exception("LocalServiceModule not present in MuteListService config file MuteListService section"); + + Object[] args = new Object[] { config }; + m_MuteListService = ServerUtils.LoadPlugin(service, args); + + IServiceAuth auth = ServiceAuth.Create(config, m_ConfigName); + + server.AddStreamHandler(new MuteListServerPostHandler(m_MuteListService, auth)); + } + } +} diff --git a/OpenSim/Server/Handlers/MuteList/MuteListServerPostHandler.cs b/OpenSim/Server/Handlers/MuteList/MuteListServerPostHandler.cs new file mode 100644 index 0000000..26c4093 --- /dev/null +++ b/OpenSim/Server/Handlers/MuteList/MuteListServerPostHandler.cs @@ -0,0 +1,240 @@ +/* + * 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 Nini.Config; +using log4net; +using System; +using System.Reflection; +using System.IO; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml; +using System.Xml.Serialization; +using System.Collections.Generic; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework; +using OpenSim.Framework.ServiceAuth; +using OpenSim.Framework.Servers.HttpServer; +using OpenMetaverse; + +namespace OpenSim.Server.Handlers.GridUser +{ + public class MuteListServerPostHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IMuteListService m_service; + + public MuteListServerPostHandler(IMuteListService service, IServiceAuth auth) : + base("POST", "/mutelist", auth) + { + m_service = service; + } + + protected override byte[] ProcessRequest(string path, Stream requestData, + IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); + body = body.Trim(); + + //m_log.DebugFormat("[XXX]: query String: {0}", body); + string method = string.Empty; + + try + { + Dictionary request = + ServerUtils.ParseQueryString(body); + + if (!request.ContainsKey("METHOD")) + return FailureResult(); + + method = request["METHOD"].ToString(); + + switch (method) + { + case "get": + return getmutes(request); + case "update": + return updatemute(request); + case "delete": + return deletemute(request); + } + m_log.DebugFormat("[MUTELIST HANDLER]: unknown method request: {0}", method); + } + catch (Exception e) + { + m_log.DebugFormat("[MUTELIST HANDLER]: Exception in method {0}: {1}", method, e); + } + + return FailureResult(); + } + + byte[] getmutes(Dictionary request) + { + if(!request.ContainsKey("agentid") || !request.ContainsKey("mutecrc")) + return FailureResult(); + + UUID agentID; + if(!UUID.TryParse(request["agentid"].ToString(), out agentID)) + return FailureResult(); + + uint mutecrc; + if(!UInt32.TryParse(request["mutecrc"].ToString(), out mutecrc)) + return FailureResult(); + + byte[] data = m_service.MuteListRequest(agentID, mutecrc); + + Dictionary result = new Dictionary(); + result["result"] = Convert.ToBase64String(data); + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[GRID USER HANDLER]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] updatemute(Dictionary request) + { + if(!request.ContainsKey("agentid") || !request.ContainsKey("muteid")) + return FailureResult(); + + MuteData mute = new MuteData(); + + if( !UUID.TryParse(request["agentid"].ToString(), out mute.AgentID)) + return FailureResult(); + + if(!UUID.TryParse(request["muteid"].ToString(), out mute.MuteID)) + return FailureResult(); + + if(request.ContainsKey("mutename")) + { + mute.MuteName = request["mutename"].ToString(); + } + else + mute.MuteName = String.Empty; + + if(request.ContainsKey("mutetype")) + { + if(!Int32.TryParse(request["mutetype"].ToString(), out mute.MuteType)) + return FailureResult(); + } + else + mute.MuteType = 0; + + if(request.ContainsKey("muteflags")) + { + if(!Int32.TryParse(request["muteflags"].ToString(), out mute.MuteFlags)) + return FailureResult(); + } + else + mute.MuteFlags = 0; + + if(request.ContainsKey("mutestamp")) + { + if(!Int32.TryParse(request["mutestamp"].ToString(), out mute.Stamp)) + return FailureResult(); + } + else + mute.Stamp = Util.UnixTimeSinceEpoch(); + + return m_service.UpdateMute(mute) ? SuccessResult() : FailureResult(); + } + + byte[] deletemute(Dictionary request) + { + if(!request.ContainsKey("agentid") || !request.ContainsKey("muteid")) + return FailureResult(); + + UUID agentID; + if( !UUID.TryParse(request["agentid"].ToString(), out agentID)) + return FailureResult(); + + UUID muteID; + if(!UUID.TryParse(request["muteid"].ToString(), out muteID)) + return FailureResult(); + + string muteName; + if(request.ContainsKey("mutename")) + { + muteName = request["mutename"].ToString(); + + } + else + muteName = String.Empty; + + return m_service.RemoveMute(agentID, muteID, muteName) ? SuccessResult() : FailureResult(); + } + + private byte[] SuccessResult() + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "result", ""); + result.AppendChild(doc.CreateTextNode("Success")); + + rootElement.AppendChild(result); + + return Util.DocToBytes(doc); + } + + private byte[] FailureResult() + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "result", ""); + result.AppendChild(doc.CreateTextNode("Failure")); + + rootElement.AppendChild(result); + + return Util.DocToBytes(doc); + } + } +} diff --git a/OpenSim/Server/Handlers/Neighbour/NeighbourHandlers.cs b/OpenSim/Server/Handlers/Neighbour/NeighbourHandlers.cs index 3525a01..e3ee467 100644 --- a/OpenSim/Server/Handlers/Neighbour/NeighbourHandlers.cs +++ b/OpenSim/Server/Handlers/Neighbour/NeighbourHandlers.cs @@ -150,7 +150,7 @@ namespace OpenSim.Server.Handlers.Neighbour // Finally! GridRegion thisRegion = m_NeighbourService.HelloNeighbour(regionhandle, aRegion); - + OSDMap resp = new OSDMap(1); if (thisRegion != null) diff --git a/OpenSim/Server/Handlers/Neighbour/NeighbourServiceInConnector.cs b/OpenSim/Server/Handlers/Neighbour/NeighbourServiceInConnector.cs index ac2e75f..65ac4e6 100644 --- a/OpenSim/Server/Handlers/Neighbour/NeighbourServiceInConnector.cs +++ b/OpenSim/Server/Handlers/Neighbour/NeighbourServiceInConnector.cs @@ -55,7 +55,7 @@ namespace OpenSim.Server.Handlers.Neighbour m_log.Error("[NEIGHBOUR IN CONNECTOR]: neighbour service was not provided"); return; } - + //bool authentication = neighbourConfig.GetBoolean("RequireAuthentication", false); //if (authentication) // m_AuthenticationService = scene.RequestModuleInterface(); diff --git a/OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs b/OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs index 49dbcb5..be16e17 100644 --- a/OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs @@ -158,7 +158,7 @@ namespace OpenSim.Server.Handlers.Presence return FailureResult(); } - + byte[] Report(Dictionary request) { UUID session = UUID.Zero; @@ -241,7 +241,7 @@ namespace OpenSim.Server.Handlers.Presence } string xmlString = ServerUtils.BuildXmlResponse(result); - + //m_log.DebugFormat("[GRID HANDLER]: resp string: {0}", xmlString); return Util.UTF8NoBomEncoding.GetBytes(xmlString); } diff --git a/OpenSim/Server/Handlers/Profiles/UserProfilesConnector.cs b/OpenSim/Server/Handlers/Profiles/UserProfilesConnector.cs index 2dfb862..eecb370 100644 --- a/OpenSim/Server/Handlers/Profiles/UserProfilesConnector.cs +++ b/OpenSim/Server/Handlers/Profiles/UserProfilesConnector.cs @@ -39,8 +39,8 @@ namespace OpenSim.Server.Handlers.Profiles { public class UserProfilesConnector: ServiceConnector { -// static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - +// static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + // Our Local Module public IUserProfilesService ServiceModule { @@ -83,7 +83,7 @@ namespace OpenSim.Server.Handlers.Profiles Object[] args = new Object[] { config, ConfigName }; ServiceModule = ServerUtils.LoadPlugin(service, args); - + JsonRpcProfileHandlers handler = new JsonRpcProfileHandlers(ServiceModule); Server.AddJsonRPCHandler("avatarclassifiedsrequest", handler.AvatarClassifiedsRequest); diff --git a/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs b/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs index 49aa8ba..f23a981 100644 --- a/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs +++ b/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs @@ -48,17 +48,17 @@ namespace OpenSim.Server.Handlers static readonly ILog m_log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); - + public IUserProfilesService Service { get; private set; } - + public JsonRpcProfileHandlers(IUserProfilesService service) { Service = service; } - + #region Classifieds /// /// Request avatar's classified ads. @@ -80,17 +80,17 @@ namespace OpenSim.Server.Handlers m_log.DebugFormat ("Classified Request"); return false; } - + OSDMap request = (OSDMap)json["params"]; UUID creatorId = new UUID(request["creatorId"].AsString()); - - + + OSDArray data = (OSDArray) Service.AvatarClassifiedsRequest(creatorId); response.Result = data; - + return true; } - + public bool ClassifiedUpdate(OSDMap json, ref JsonRpcResponse response) { if(!json.ContainsKey("params")) @@ -100,7 +100,7 @@ namespace OpenSim.Server.Handlers m_log.DebugFormat ("Classified Update Request"); return false; } - + string result = string.Empty; UserClassifiedAdd ad = new UserClassifiedAdd(); object Ad = (object)ad; @@ -110,12 +110,12 @@ namespace OpenSim.Server.Handlers response.Result = OSD.SerializeMembers(ad); return true; } - + response.Error.Code = ErrorCode.InternalError; response.Error.Message = string.Format("{0}", result); return false; } - + public bool ClassifiedDelete(OSDMap json, ref JsonRpcResponse response) { if(!json.ContainsKey("params")) @@ -124,10 +124,10 @@ namespace OpenSim.Server.Handlers m_log.DebugFormat ("Classified Delete Request"); return false; } - + OSDMap request = (OSDMap)json["params"]; UUID classifiedId = new UUID(request["classifiedId"].AsString()); - + if (Service.ClassifiedDelete(classifiedId)) return true; @@ -135,7 +135,7 @@ namespace OpenSim.Server.Handlers response.Error.Message = "data error removing record"; return false; } - + public bool ClassifiedInfoRequest(OSDMap json, ref JsonRpcResponse response) { if(!json.ContainsKey("params")) @@ -145,7 +145,7 @@ namespace OpenSim.Server.Handlers m_log.DebugFormat ("Classified Info Request"); return false; } - + string result = string.Empty; UserClassifiedAdd ad = new UserClassifiedAdd(); object Ad = (object)ad; @@ -155,13 +155,13 @@ namespace OpenSim.Server.Handlers response.Result = OSD.SerializeMembers(ad); return true; } - + response.Error.Code = ErrorCode.InternalError; response.Error.Message = string.Format("{0}", result); return false; } #endregion Classifieds - + #region Picks public bool AvatarPicksRequest(OSDMap json, ref JsonRpcResponse response) { @@ -171,17 +171,17 @@ namespace OpenSim.Server.Handlers m_log.DebugFormat ("Avatar Picks Request"); return false; } - + OSDMap request = (OSDMap)json["params"]; UUID creatorId = new UUID(request["creatorId"].AsString()); - - + + OSDArray data = (OSDArray) Service.AvatarPicksRequest(creatorId); response.Result = data; - + return true; } - + public bool PickInfoRequest(OSDMap json, ref JsonRpcResponse response) { if(!json.ContainsKey("params")) @@ -191,7 +191,7 @@ namespace OpenSim.Server.Handlers m_log.DebugFormat ("Avatar Picks Info Request"); return false; } - + string result = string.Empty; UserProfilePick pick = new UserProfilePick(); object Pick = (object)pick; @@ -201,12 +201,12 @@ namespace OpenSim.Server.Handlers response.Result = OSD.SerializeMembers(pick); return true; } - + response.Error.Code = ErrorCode.InternalError; response.Error.Message = string.Format("{0}", result); return false; } - + public bool PicksUpdate(OSDMap json, ref JsonRpcResponse response) { if(!json.ContainsKey("params")) @@ -216,7 +216,7 @@ namespace OpenSim.Server.Handlers m_log.DebugFormat ("Avatar Picks Update Request"); return false; } - + string result = string.Empty; UserProfilePick pick = new UserProfilePick(); object Pick = (object)pick; @@ -226,13 +226,13 @@ namespace OpenSim.Server.Handlers response.Result = OSD.SerializeMembers(pick); return true; } - + response.Error.Code = ErrorCode.InternalError; response.Error.Message = "unable to update pick"; - + return false; } - + public bool PicksDelete(OSDMap json, ref JsonRpcResponse response) { if(!json.ContainsKey("params")) @@ -241,18 +241,18 @@ namespace OpenSim.Server.Handlers m_log.DebugFormat ("Avatar Picks Delete Request"); return false; } - + OSDMap request = (OSDMap)json["params"]; UUID pickId = new UUID(request["pickId"].AsString()); if(Service.PicksDelete(pickId)) return true; - + response.Error.Code = ErrorCode.InternalError; response.Error.Message = "data error removing record"; return false; } #endregion Picks - + #region Notes public bool AvatarNotesRequest(OSDMap json, ref JsonRpcResponse response) { @@ -277,7 +277,7 @@ namespace OpenSim.Server.Handlers response.Error.Message = "Error reading notes"; return false; } - + public bool NotesUpdate(OSDMap json, ref JsonRpcResponse response) { if(!json.ContainsKey("params")) @@ -287,7 +287,7 @@ namespace OpenSim.Server.Handlers m_log.DebugFormat ("Avatar Notes Update Request"); return false; } - + string result = string.Empty; UserProfileNotes note = new UserProfileNotes(); object Notes = (object) note; @@ -300,7 +300,7 @@ namespace OpenSim.Server.Handlers return true; } #endregion Notes - + #region Profile Properties public bool AvatarPropertiesRequest(OSDMap json, ref JsonRpcResponse response) { @@ -311,7 +311,7 @@ namespace OpenSim.Server.Handlers m_log.DebugFormat ("Avatar Properties Request"); return false; } - + string result = string.Empty; UserProfileProperties props = new UserProfileProperties(); object Props = (object)props; @@ -321,12 +321,12 @@ namespace OpenSim.Server.Handlers response.Result = OSD.SerializeMembers(props); return true; } - + response.Error.Code = ErrorCode.InternalError; response.Error.Message = string.Format("{0}", result); return false; } - + public bool AvatarPropertiesUpdate(OSDMap json, ref JsonRpcResponse response) { if(!json.ContainsKey("params")) @@ -336,7 +336,7 @@ namespace OpenSim.Server.Handlers m_log.DebugFormat ("Avatar Properties Update Request"); return false; } - + string result = string.Empty; UserProfileProperties props = new UserProfileProperties(); object Props = (object)props; @@ -346,13 +346,13 @@ namespace OpenSim.Server.Handlers response.Result = OSD.SerializeMembers(props); return true; } - + response.Error.Code = ErrorCode.InternalError; response.Error.Message = string.Format("{0}", result); return false; } #endregion Profile Properties - + #region Interests public bool AvatarInterestsUpdate(OSDMap json, ref JsonRpcResponse response) { @@ -363,7 +363,7 @@ namespace OpenSim.Server.Handlers m_log.DebugFormat ("Avatar Interests Update Request"); return false; } - + string result = string.Empty; UserProfileProperties props = new UserProfileProperties(); object Props = (object)props; @@ -373,7 +373,7 @@ namespace OpenSim.Server.Handlers response.Result = OSD.SerializeMembers(props); return true; } - + response.Error.Code = ErrorCode.InternalError; response.Error.Message = string.Format("{0}", result); return false; @@ -399,7 +399,7 @@ namespace OpenSim.Server.Handlers response.Result = OSD.SerializeMembers(prefs); return true; } - + response.Error.Code = ErrorCode.InternalError; response.Error.Message = string.Format("{0}", result); // m_log.InfoFormat("[PROFILES]: User preferences request error - {0}", response.Error.Message); @@ -415,7 +415,7 @@ namespace OpenSim.Server.Handlers m_log.DebugFormat ("User Preferences Update Request"); return false; } - + string result = string.Empty; UserPreferences prefs = new UserPreferences(); object Prefs = (object)prefs; @@ -425,7 +425,7 @@ namespace OpenSim.Server.Handlers response.Result = OSD.SerializeMembers(prefs); return true; } - + response.Error.Code = ErrorCode.InternalError; response.Error.Message = string.Format("{0}", result); m_log.InfoFormat("[PROFILES]: User preferences update error - {0}", response.Error.Message); @@ -433,6 +433,7 @@ namespace OpenSim.Server.Handlers } #endregion User Preferences + #region Utility public bool AvatarImageAssetsRequest(OSDMap json, ref JsonRpcResponse response) { @@ -442,13 +443,13 @@ namespace OpenSim.Server.Handlers m_log.DebugFormat ("Avatar Image Assets Request"); return false; } - + OSDMap request = (OSDMap)json["params"]; UUID avatarId = new UUID(request["avatarId"].AsString()); OSDArray data = (OSDArray) Service.AvatarImageAssetsRequest(avatarId); response.Result = data; - + return true; } #endregion Utiltiy @@ -463,7 +464,7 @@ namespace OpenSim.Server.Handlers m_log.DebugFormat ("User Application Service URL Request: No Parameters!"); return false; } - + string result = string.Empty; UserAppData props = new UserAppData(); object Props = (object)props; @@ -474,15 +475,15 @@ namespace OpenSim.Server.Handlers res["result"] = OSD.FromString("success"); res["token"] = OSD.FromString (result); response.Result = res; - + return true; } - + response.Error.Code = ErrorCode.InternalError; response.Error.Message = string.Format("{0}", result); return false; } - + public bool UpdateUserAppData(OSDMap json, ref JsonRpcResponse response) { if(!json.ContainsKey("params")) @@ -492,7 +493,7 @@ namespace OpenSim.Server.Handlers m_log.DebugFormat ("User App Data Update Request"); return false; } - + string result = string.Empty; UserAppData props = new UserAppData(); object Props = (object)props; @@ -502,7 +503,7 @@ namespace OpenSim.Server.Handlers response.Result = OSD.SerializeMembers(props); return true; } - + response.Error.Code = ErrorCode.InternalError; response.Error.Message = string.Format("{0}", result); return false; diff --git a/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs b/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs index f0b36c1..4d6402f 100644 --- a/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs +++ b/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs @@ -2,7 +2,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following +// General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("OpenSim.Server.Handlers")] @@ -14,8 +14,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] @@ -25,9 +25,9 @@ using System.Runtime.InteropServices; // Version information for an assembly consists of the following four values: // // Major Version -// Minor Version +// Minor Version // Build Number // Revision // -[assembly: AssemblyVersion("0.8.3.*")] +[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)] diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs index 98c5312..c52a1ab 100644 --- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs +++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs @@ -120,6 +120,10 @@ namespace OpenSim.Server.Handlers.Simulation protected virtual void DoQueryAccess(Hashtable request, Hashtable responsedata, UUID agentID, UUID regionID) { + Culture.SetCurrentCulture(); + + EntityTransferContext ctx = new EntityTransferContext(); + if (m_SimulationService == null) { m_log.Debug("[AGENT HANDLER]: Agent QUERY called. Harmless but useless."); @@ -155,6 +159,9 @@ namespace OpenSim.Server.Handlers.Simulation theirVersion = float.Parse(parts[1]); } + if (args.ContainsKey("context")) + ctx.Unpack((OSDMap)args["context"]); + // Decode the new versioning data float minVersionRequired = 0f; float maxVersionRequired = 0f; @@ -183,7 +190,7 @@ namespace OpenSim.Server.Handlers.Simulation { // If there is no version in the packet at all we're looking at 0.6 or // even more ancient. Refuse it. - if(theirVersion == 0f) + if(theirVersion == 0f) { resp["success"] = OSD.FromBoolean(false); resp["reason"] = OSD.FromString("Your region is running a old version of opensim no longer supported. Consider updating it"); @@ -192,8 +199,8 @@ namespace OpenSim.Server.Handlers.Simulation } version = theirVersion; - - if (version < VersionInfo.SimulationServiceVersionAcceptedMin || + + if (version < VersionInfo.SimulationServiceVersionAcceptedMin || version > VersionInfo.SimulationServiceVersionAcceptedMax ) { resp["success"] = OSD.FromBoolean(false); @@ -245,7 +252,6 @@ namespace OpenSim.Server.Handlers.Simulation string reason; // We're sending the version numbers down to the local connector to do the varregion check. - EntityTransferContext ctx = new EntityTransferContext(); ctx.InboundVersion = inboundVersion; ctx.OutboundVersion = outboundVersion; if (minVersionProvided == 0f) @@ -255,6 +261,8 @@ namespace OpenSim.Server.Handlers.Simulation } bool result = m_SimulationService.QueryAccess(destination, agentID, agentHomeURI, viaTeleport, position, features, ctx, out reason); + m_log.DebugFormat("[AGENT HANDLER]: QueryAccess returned {0} ({1}). Version={2}, {3}/{4}", + result, reason, version, inboundVersion, outboundVersion); resp["success"] = OSD.FromBoolean(result); resp["reason"] = OSD.FromString(reason); @@ -262,12 +270,11 @@ namespace OpenSim.Server.Handlers.Simulation resp["version"] = OSD.FromString(legacyVersion); resp["negotiated_inbound_version"] = OSD.FromReal(inboundVersion); resp["negotiated_outbound_version"] = OSD.FromReal(outboundVersion); - resp["variable_wearables_count_supported"] = OSD.FromBoolean(true); OSDArray featuresWanted = new OSDArray(); foreach (UUID feature in features) featuresWanted.Add(OSD.FromString(feature.ToString())); - + resp["features"] = featuresWanted; // We must preserve defaults here, otherwise a false "success" will not be put into the JSON map! @@ -407,6 +414,8 @@ namespace OpenSim.Server.Handlers.Simulation protected void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id) { + EntityTransferContext ctx = new EntityTransferContext(); + OSDMap args = Utils.GetOSDMap((string)request["body"]); if (args == null) { @@ -415,6 +424,9 @@ namespace OpenSim.Server.Handlers.Simulation return; } + if (args.ContainsKey("context")) + ctx.Unpack((OSDMap)args["context"]); + AgentDestinationData data = CreateAgentDestinationData(); UnpackData(args, data, request); @@ -448,7 +460,7 @@ namespace OpenSim.Server.Handlers.Simulation source.RegionLocY = Int32.Parse(args["source_y"].AsString()); source.RegionName = args["source_name"].AsString(); source.RegionID = UUID.Parse(args["source_uuid"].AsString()); - + if (args.ContainsKey("source_server_uri")) source.RawServerURI = args["source_server_uri"].AsString(); else @@ -461,7 +473,8 @@ namespace OpenSim.Server.Handlers.Simulation // This is the meaning of POST agent //m_regionClient.AdjustUserInformation(aCircuit); //bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason); - bool result = CreateAgent(source, gatekeeper, destination, aCircuit, data.flags, data.fromLogin, out reason); + + bool result = CreateAgent(source, gatekeeper, destination, aCircuit, data.flags, data.fromLogin, ctx, out reason); resp["reason"] = OSD.FromString(reason); resp["success"] = OSD.FromBoolean(result); @@ -504,41 +517,62 @@ namespace OpenSim.Server.Handlers.Simulation protected string GetCallerIP(Hashtable request) { - if (!m_Proxy) - return Util.GetCallerIP(request); - - // We're behind a proxy - Hashtable headers = (Hashtable)request["headers"]; + if (request.ContainsKey("headers")) + { + Hashtable headers = (Hashtable)request["headers"]; - //// DEBUG - //foreach (object o in headers.Keys) - // m_log.DebugFormat("XXX {0} = {1}", o.ToString(), (headers[o] == null? "null" : headers[o].ToString())); + //// DEBUG + //foreach (object o in headers.Keys) + // m_log.DebugFormat("XXX {0} = {1}", o.ToString(), (headers[o] == null? "null" : headers[o].ToString())); - string xff = "X-Forwarded-For"; - if (headers.ContainsKey(xff.ToLower())) - xff = xff.ToLower(); + string xff = "X-Forwarded-For"; + if (!headers.ContainsKey(xff)) + xff = xff.ToLower(); - if (!headers.ContainsKey(xff) || headers[xff] == null) - { - m_log.WarnFormat("[AGENT HANDLER]: No XFF header"); - return Util.GetCallerIP(request); - } - - m_log.DebugFormat("[AGENT HANDLER]: XFF is {0}", headers[xff]); + if (!headers.ContainsKey(xff) || headers[xff] == null) + { +// m_log.WarnFormat("[AGENT HANDLER]: No XFF header"); + return Util.GetCallerIP(request); + } - IPEndPoint ep = Util.GetClientIPFromXFF((string)headers[xff]); - if (ep != null) - return ep.Address.ToString(); +// m_log.DebugFormat("[AGENT HANDLER]: XFF is {0}", headers[xff]); + IPEndPoint ep = Util.GetClientIPFromXFF((string)headers[xff]); + if (ep != null) + return ep.Address.ToString(); + } // Oops return Util.GetCallerIP(request); } // subclasses can override this protected virtual bool CreateAgent(GridRegion source, GridRegion gatekeeper, GridRegion destination, - AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason) + AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, EntityTransferContext ctx, out string reason) { - return m_SimulationService.CreateAgent(source, destination, aCircuit, teleportFlags, out reason); + reason = String.Empty; + // The data and protocols are already defined so this is just a dummy to satisfy the interface + // TODO: make this end-to-end + +/* this needs to be sync + if ((teleportFlags & (uint)TeleportFlags.ViaLogin) == 0) + { + Util.FireAndForget(x => + { + string r; + m_SimulationService.CreateAgent(source, destination, aCircuit, teleportFlags, ctx, out r); + m_log.DebugFormat("[AGENT HANDLER]: ASYNC CreateAgent {0}", r); + }); + + return true; + } + else + { +*/ + + bool ret = m_SimulationService.CreateAgent(source, destination, aCircuit, teleportFlags, ctx, out reason); +// m_log.DebugFormat("[AGENT HANDLER]: SYNC CreateAgent {0} {1}", ret.ToString(), reason); + return ret; +// } } } @@ -639,6 +673,9 @@ namespace OpenSim.Server.Handlers.Simulation protected void DoAgentPut(Hashtable request, Hashtable responsedata) { + // TODO: Encode the ENtityTransferContext + EntityTransferContext ctx = new EntityTransferContext(); + OSDMap args = Utils.GetOSDMap((string)request["body"]); if (args == null) { @@ -659,6 +696,8 @@ namespace OpenSim.Server.Handlers.Simulation UUID.TryParse(args["destination_uuid"].AsString(), out uuid); if (args.ContainsKey("destination_name") && args["destination_name"] != null) regionname = args["destination_name"].ToString(); + if (args.ContainsKey("context")) + ctx.Unpack((OSDMap)args["context"]); GridRegion destination = new GridRegion(); destination.RegionID = uuid; @@ -681,7 +720,7 @@ namespace OpenSim.Server.Handlers.Simulation AgentData agent = new AgentData(); try { - agent.Unpack(args, m_SimulationService.GetScene(destination.RegionID)); + agent.Unpack(args, m_SimulationService.GetScene(destination.RegionID), ctx); } catch (Exception ex) { @@ -700,7 +739,7 @@ namespace OpenSim.Server.Handlers.Simulation AgentPosition agent = new AgentPosition(); try { - agent.Unpack(args, m_SimulationService.GetScene(destination.RegionID)); + agent.Unpack(args, m_SimulationService.GetScene(destination.RegionID), ctx); } catch (Exception ex) { @@ -721,7 +760,10 @@ namespace OpenSim.Server.Handlers.Simulation // subclasses can override this protected virtual bool UpdateAgent(GridRegion destination, AgentData agent) { - return m_SimulationService.UpdateAgent(destination, agent); + // The data and protocols are already defined so this is just a dummy to satisfy the interface + // TODO: make this end-to-end + EntityTransferContext ctx = new EntityTransferContext(); + return m_SimulationService.UpdateAgent(destination, agent, ctx); } } diff --git a/OpenSim/Server/Handlers/Simulation/ObjectHandlers.cs b/OpenSim/Server/Handlers/Simulation/ObjectHandlers.cs index dbb1a15..1b545ac 100644 --- a/OpenSim/Server/Handlers/Simulation/ObjectHandlers.cs +++ b/OpenSim/Server/Handlers/Simulation/ObjectHandlers.cs @@ -69,6 +69,8 @@ namespace OpenSim.Server.Handlers.Simulation //m_log.Debug(" >> http-method=" + request["http-method"]); //m_log.Debug("---------------------------\n"); + Culture.SetCurrentCulture(); + Hashtable responsedata = new Hashtable(); responsedata["content_type"] = "text/html"; diff --git a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs index 21eb790..bc12ef9 100644 --- a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs +++ b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs @@ -72,9 +72,9 @@ namespace OpenSim.Server.Handlers.UserAccounts protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); // We need to check the authorization header @@ -98,16 +98,18 @@ namespace OpenSim.Server.Handlers.UserAccounts if (m_AllowCreateUser) return CreateUser(request); else - break; + return FailureResult(); case "getaccount": return GetAccount(request); case "getaccounts": return GetAccounts(request); + case "getmultiaccounts": + return GetMultiAccounts(request); case "setaccount": if (m_AllowSetAccount) return StoreAccount(request); else - break; + return FailureResult(); } m_log.DebugFormat("[USER SERVICE HANDLER]: unknown method request: {0}", method); @@ -201,6 +203,52 @@ namespace OpenSim.Server.Handlers.UserAccounts return Util.UTF8NoBomEncoding.GetBytes(xmlString); } + byte[] GetMultiAccounts(Dictionary request) + { + UUID scopeID = UUID.Zero; + if (request.ContainsKey("ScopeID") && !UUID.TryParse(request["ScopeID"].ToString(), out scopeID)) + return FailureResult(); + + if (!request.ContainsKey("IDS")) + { + m_log.DebugFormat("[USER SERVICE HANDLER]: GetMultiAccounts called without required uuids argument"); + return FailureResult(); + } + + if (!(request["IDS"] is List)) + { + m_log.DebugFormat("[USER SERVICE HANDLER]: GetMultiAccounts input argument was of unexpected type {0}", request["IDS"].GetType().ToString()); + return FailureResult(); + } + + List userIDs = (List)request["IDS"]; + + List accounts = m_UserAccountService.GetUserAccounts(scopeID, userIDs); + + Dictionary result = new Dictionary(); + if ((accounts == null) || ((accounts != null) && (accounts.Count == 0))) + { + result["result"] = "null"; + } + else + { + int i = 0; + foreach (UserAccount acc in accounts) + { + if(acc == null) + continue; + Dictionary rinfoDict = acc.ToKeyValuePairs(); + result["account" + i] = rinfoDict; + i++; + } + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[GRID HANDLER]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + byte[] StoreAccount(Dictionary request) { UUID principalID = UUID.Zero; @@ -280,12 +328,16 @@ namespace OpenSim.Server.Handlers.UserAccounts if (request.ContainsKey("Email")) email = request["Email"].ToString(); + string model = ""; + if (request.ContainsKey("Model")) + model = request["Model"].ToString(); + UserAccount createdUserAccount = null; if (m_UserAccountService is UserAccountService) createdUserAccount = ((UserAccountService)m_UserAccountService).CreateUser( - scopeID, principalID, firstName, lastName, password, email); + scopeID, principalID, firstName, lastName, password, email, model); if (createdUserAccount == null) return FailureResult(); @@ -345,4 +397,4 @@ namespace OpenSim.Server.Handlers.UserAccounts return Util.UTF8NoBomEncoding.GetBytes(xmlString); } } -} \ No newline at end of file +} diff --git a/OpenSim/Server/Properties/AssemblyInfo.cs b/OpenSim/Server/Properties/AssemblyInfo.cs index ee45e10..6d15078 100644 --- a/OpenSim/Server/Properties/AssemblyInfo.cs +++ b/OpenSim/Server/Properties/AssemblyInfo.cs @@ -2,7 +2,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following +// General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Robust")] @@ -14,8 +14,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] @@ -25,7 +25,7 @@ using System.Runtime.InteropServices; // Version information for an assembly consists of the following four values: // // Major Version -// Minor Version +// Minor Version // Build Number // Revision // diff --git a/OpenSim/Server/ServerMain.cs b/OpenSim/Server/ServerMain.cs index 65e9287..69d0b74 100644 --- a/OpenSim/Server/ServerMain.cs +++ b/OpenSim/Server/ServerMain.cs @@ -29,7 +29,9 @@ using Nini.Config; using log4net; using System.Reflection; using System; +using System.Net; using System.Collections.Generic; +using OpenSim.Framework; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Server.Base; @@ -53,8 +55,14 @@ namespace OpenSim.Server public static int Main(string[] args) { + ServicePointManager.DefaultConnectionLimit = 64; + ServicePointManager.Expect100Continue = false; + ServicePointManager.UseNagleAlgorithm = false; + + try { ServicePointManager.DnsRefreshTimeout = 300000; } catch { } + m_Server = new HttpServerBase("R.O.B.U.S.T.", args); - + string registryLocation; IConfig serverConfig = m_Server.Config.Configs["Startup"]; @@ -65,7 +73,7 @@ namespace OpenSim.Server } string connList = serverConfig.GetString("ServiceConnectors", String.Empty); - + registryLocation = serverConfig.GetString("RegistryLocation","."); IConfig servicesConfig = m_Server.Config.Configs["ServiceList"]; @@ -153,6 +161,11 @@ namespace OpenSim.Server int res = m_Server.Run(); + if(m_Server != null) + m_Server.Shutdown(); + + Util.StopThreadPool(); + Environment.Exit(res); return 0; -- cgit v1.1 From 295e91b8f44a356ab742dedd27c1b7edfe7b1157 Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 19 May 2019 22:15:41 +1000 Subject: Move cache, config, logs out of tree, and various related clean ups. --- OpenSim/Server/Base/ServicesServerBase.cs | 2 +- OpenSim/Server/Handlers/BakedTextures/XBakes.cs | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs index 176e876..1484ee0 100644 --- a/OpenSim/Server/Base/ServicesServerBase.cs +++ b/OpenSim/Server/Base/ServicesServerBase.cs @@ -85,7 +85,7 @@ namespace OpenSim.Server.Base string fileName = ""; if (Assembly.GetEntryAssembly() != null) fileName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location); - string iniFile = fileName + ".ini"; + string iniFile = Util.configDir() + fileName + ".ini"; string logConfig = null; IConfig startupConfig = argvConfig.Configs["Startup"]; diff --git a/OpenSim/Server/Handlers/BakedTextures/XBakes.cs b/OpenSim/Server/Handlers/BakedTextures/XBakes.cs index 4e55433..0c74564 100644 --- a/OpenSim/Server/Handlers/BakedTextures/XBakes.cs +++ b/OpenSim/Server/Handlers/BakedTextures/XBakes.cs @@ -67,12 +67,7 @@ namespace OpenSim.Server.Handlers.BakedTextures throw new Exception("No BakedTextureService configuration"); } - m_FSBase = assetConfig.GetString("BaseDirectory", String.Empty); - if (m_FSBase == String.Empty) - { - m_log.ErrorFormat("[BAKES]: BaseDirectory not specified"); - throw new Exception("Configuration error"); - } + m_FSBase = assetConfig.GetString("BaseDirectory", Util.cacheDir() + "/bakes"); m_log.Info("[BAKES]: XBakes service enabled"); } -- cgit v1.1 From 19bf45d261a8df40af85b110c96190dcf2efdaad Mon Sep 17 00:00:00 2001 From: onefang Date: Thu, 4 Jul 2019 16:31:53 +1000 Subject: Properly combine Robust.ini path. --- OpenSim/Server/Base/ServicesServerBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs index 1484ee0..472998a 100644 --- a/OpenSim/Server/Base/ServicesServerBase.cs +++ b/OpenSim/Server/Base/ServicesServerBase.cs @@ -85,7 +85,7 @@ namespace OpenSim.Server.Base string fileName = ""; if (Assembly.GetEntryAssembly() != null) fileName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location); - string iniFile = Util.configDir() + fileName + ".ini"; + string iniFile = Path.Combine(Util.configDir(), fileName + ".ini"); string logConfig = null; IConfig startupConfig = argvConfig.Configs["Startup"]; -- cgit v1.1 From 85fcb4e75c94ff7b5b45609826df5113f32aacc0 Mon Sep 17 00:00:00 2001 From: onefang Date: Fri, 2 Aug 2019 21:20:11 +1000 Subject: Another attempt at sorting out the auto group chicken and egg problems. Are you a local? Asking for a friend. --- .../Server/Handlers/Authorization/AuthorizationServerPostHandler.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Authorization/AuthorizationServerPostHandler.cs b/OpenSim/Server/Handlers/Authorization/AuthorizationServerPostHandler.cs index 310a542..07e09bc 100644 --- a/OpenSim/Server/Handlers/Authorization/AuthorizationServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Authorization/AuthorizationServerPostHandler.cs @@ -61,7 +61,8 @@ namespace OpenSim.Server.Handlers.Authorization AuthorizationRequest Authorization = (AuthorizationRequest) xs.Deserialize(request); string message = String.Empty; - bool authorized = m_AuthorizationService.IsAuthorizedForRegion(Authorization.ID, Authorization.FirstName, Authorization.SurName, Authorization.RegionID, out message); + bool isLocal = false; + bool authorized = m_AuthorizationService.IsAuthorizedForRegion(Authorization.ID, Authorization.FirstName, Authorization.SurName, Authorization.RegionID, out message, out isLocal); AuthorizationResponse result = new AuthorizationResponse(authorized, Authorization.ID + " has been authorized"); -- cgit v1.1 From bf27216a290c125f565d08700bb6693387fac9bf Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 4 Aug 2019 10:30:42 +1000 Subject: Add a basic generic web server, and a login page, plus stubs for the other basic pages. And update everyone to suit. --- .../Server/Handlers/Web/WebServerInConnector.cs | 107 +++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 OpenSim/Server/Handlers/Web/WebServerInConnector.cs (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs new file mode 100644 index 0000000..94c636f --- /dev/null +++ b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs @@ -0,0 +1,107 @@ +/* + * 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.IO; +using System.Net; +using System.Reflection; +using System.Security; +using System.Text; +using log4net; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; + +namespace OpenSim.Server.Handlers.Web +{ + public class WebServerInConnector : ServiceConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private IConfigSource m_Config; + private Hashtable mime = new Hashtable(); + + public WebServerInConnector(IConfigSource config, IHttpServer server, string configName) : base(config, server, configName) + { + m_Config = config; + mime.Add(".html", "text/html"); + mime.Add(".htm", "text/html"); + mime.Add(".shtml", "text/html"); + mime.Add(".txt", "text/plain"); + mime.Add(".css", "text/css"); + mime.Add(".js", "application/javascript"); + mime.Add(".png", "image/png"); + mime.Add(".jpeg", "image/jpeg"); + server.AddHTTPHandler("/web/", WebRequestHandler); + } + + private Hashtable WebRequestHandler(Hashtable request) + { + Hashtable reply = new Hashtable(); + + string reqpath = (string) request["uri"]; + string[] query = (string[]) request["querystringkeys"]; + Hashtable headers = (Hashtable) request["headers"]; + string method = (string) request["http-method"]; + string type = (string) request["content-type"]; + string body = (string) request["body"]; + string file = Path.Combine(Util.webDir(), reqpath.Remove(0, 5)); + + reply["int_response_code"] = 200; + if (File.Exists(file)) + { + string m = (string) mime[Path.GetExtension(file)]; + reply["content_type"] = m; + if (("image/jpeg" == m) || ("image/png" == m)) + { + reply["bin_response_data"] = File.ReadAllBytes(file); + } + else + { + StreamReader csr = File.OpenText(file); + reply["str_response_string"] = csr.ReadToEnd(); + csr.Close(); + } + } + else + { + m_log.ErrorFormat("[WEB SERVICE]: Unable to read {0}.", file); + reply["int_response_code"] = 404; + reply["content_type"] = "text/html"; + reply["str_response_string"] = "404 Unknown page" + + "404 error, can't find the " + reqpath + " page.

 

"; + } + + return reply; + } + + } +} -- cgit v1.1 From 5fae30eb8863f3f39e6853584fd49197c52e8835 Mon Sep 17 00:00:00 2001 From: onefang Date: Mon, 5 Aug 2019 01:41:34 +1000 Subject: More basic web server. --- .../Server/Handlers/Web/WebServerInConnector.cs | 53 +++++++++++++++++++--- 1 file changed, 46 insertions(+), 7 deletions(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs index 94c636f..e7fb2fc 100644 --- a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs @@ -45,27 +45,60 @@ namespace OpenSim.Server.Handlers.Web { public class WebServerInConnector : ServiceConnector { + // This is all slow and clunky, it's not a real web server, just something to use if you don't want a real one. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private IConfigSource m_Config; private Hashtable mime = new Hashtable(); + private Hashtable ssi = new Hashtable(); public WebServerInConnector(IConfigSource config, IHttpServer server, string configName) : base(config, server, configName) { m_Config = config; + mime.Add(".gz", "application/gzip"); + mime.Add(".js", "application/javascript"); + mime.Add(".json", "application/json"); + mime.Add(".pdf", "application/pdf"); + mime.Add(".rtf", "application/rtf"); + mime.Add(".zip", "application/zip"); + mime.Add(".xz", "application/x-xz"); + mime.Add(".gif", "image/gif"); + mime.Add(".png", "image/png"); + mime.Add(".jp2", "image/jp2"); + mime.Add(".jpg2", "image/jp2"); + mime.Add(".jpe", "image/jpeg"); + mime.Add(".jpg", "image/jpeg"); + mime.Add(".jpeg", "image/jpeg"); + mime.Add(".svg", "image/svg+xml"); + mime.Add(".svgz", "image/svg+xml"); + mime.Add(".tif", "image/tiff"); + mime.Add(".tiff", "image/tiff"); + mime.Add(".css", "text/css"); mime.Add(".html", "text/html"); mime.Add(".htm", "text/html"); mime.Add(".shtml", "text/html"); +// mime.Add(".md", "text/markdown"); +// mime.Add(".markdown","text/markdown"); mime.Add(".txt", "text/plain"); - mime.Add(".css", "text/css"); - mime.Add(".js", "application/javascript"); - mime.Add(".png", "image/png"); - mime.Add(".jpeg", "image/jpeg"); + + IConfig cfg = m_Config.Configs["GridInfoService"]; + string HomeURI = Util.GetConfigVarFromSections(m_Config, "HomeURI", new string[] { "Startup", "Hypergrid" }, String.Empty); + ssi.Add("grid", cfg.GetString("gridname", "my grid")); + ssi.Add("uri", cfg.GetString("login", HomeURI)); + ssi.Add("version", VersionInfo.Version); server.AddHTTPHandler("/web/", WebRequestHandler); } private Hashtable WebRequestHandler(Hashtable request) { Hashtable reply = new Hashtable(); + // Looks like we have to jump through hoops to do simple database queries. B-( + ssi["members"] = "?"; // SELECT COUNT(PrincipalID) FROM UserAccounts + ssi["inworld"] = "?"; // SELECT COUNT(UserID) FROM presence_culled; Includes locals and HGers in world, but not locals HGing. + // SELECT COUNT(UserID) FROM users_online; Includes local online only. + ssi["outworld"] = "?"; // SELECT COUNT(UserID) FROM hg_traveling_data WHERE GridExternalName != ssi["uri"]; Includes locals that are HGing. +// ssi["hgers"] = "?"; // This is complex. + ssi["sims"] = "?"; // SELECT COUNT(uuid) FROM regions +// ssi["month"] = "?"; // SELECT COUNT(UserID) FROM Presence WHERE LastSeen < one month ago 2017-11-28 09:01:51; Includes external HGers, and locals on now. string reqpath = (string) request["uri"]; string[] query = (string[]) request["querystringkeys"]; @@ -78,16 +111,22 @@ namespace OpenSim.Server.Handlers.Web reply["int_response_code"] = 200; if (File.Exists(file)) { - string m = (string) mime[Path.GetExtension(file)]; + string m = (string) mime[Path.GetExtension(file).ToLower()]; reply["content_type"] = m; - if (("image/jpeg" == m) || ("image/png" == m)) + if ((null == m) || ("text/" != m.Substring(0, 5))) { reply["bin_response_data"] = File.ReadAllBytes(file); } else { StreamReader csr = File.OpenText(file); - reply["str_response_string"] = csr.ReadToEnd(); + string content = csr.ReadToEnd(); + // Slow and wasteful, but I'm expecting only tiny web files, not accessed very often. + foreach (DictionaryEntry v in ssi) + { + content = content.Replace("", (string) v.Value); + } + reply["str_response_string"] = content; csr.Close(); } } -- cgit v1.1 From eda035228d8206fd593cfd0ab98cf3c84229a365 Mon Sep 17 00:00:00 2001 From: onefang Date: Mon, 5 Aug 2019 04:18:18 +1000 Subject: ROBUST now reports INITIALIZATION COMPLETE FOR ROBUST. --- OpenSim/Server/ServerMain.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/ServerMain.cs b/OpenSim/Server/ServerMain.cs index 69d0b74..30e9297 100644 --- a/OpenSim/Server/ServerMain.cs +++ b/OpenSim/Server/ServerMain.cs @@ -159,6 +159,8 @@ namespace OpenSim.Server loader = new PluginLoader(m_Server.Config, registryLocation); + m_log.InfoFormat("[SERVER]: INITIALIZATION COMPLETE FOR ROBUST"); + int res = m_Server.Run(); if(m_Server != null) -- cgit v1.1 From 659229c0777f381c66462fd7a4f2dfddbe3e1ef6 Mon Sep 17 00:00:00 2001 From: onefang Date: Tue, 6 Aug 2019 01:08:51 +1000 Subject: Add actual grid stats to the web page. Except HGers, still trying to sort that one out. --- .../Server/Handlers/Web/WebServerInConnector.cs | 48 ++++++++++++++++++---- 1 file changed, 40 insertions(+), 8 deletions(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs index e7fb2fc..01c74fe 100644 --- a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs @@ -38,6 +38,7 @@ using OpenMetaverse; using OpenMetaverse.StructuredData; using Nini.Config; using OpenSim.Framework; +using OpenSim.Data.MySQL; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Server.Handlers.Base; @@ -48,12 +49,39 @@ namespace OpenSim.Server.Handlers.Web // This is all slow and clunky, it's not a real web server, just something to use if you don't want a real one. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private IConfigSource m_Config; + protected MySQLGenericHandler m_Database = null; private Hashtable mime = new Hashtable(); private Hashtable ssi = new Hashtable(); public WebServerInConnector(IConfigSource config, IHttpServer server, string configName) : base(config, server, configName) { m_Config = config; + + string dllName = String.Empty; + string connString = String.Empty; + + // + // Try reading the [DatabaseService] section, if it exists + // + IConfig dbConfig = m_Config.Configs["DatabaseService"]; + if (dbConfig != null) + { + if (dllName == String.Empty) + dllName = dbConfig.GetString("StorageProvider", String.Empty); + if (connString == String.Empty) + connString = dbConfig.GetString("ConnectionString", String.Empty); + } + + if (dllName.Equals(String.Empty)) + throw new Exception("No StorageProvider configured"); + +//// TODO - Should do the plugin thing to pick between database backends. +// m_Database = LoadPlugin(dllName, new Object[] { connString }); + m_Database = new MySQLGenericHandler(connString); + if (m_Database == null) + throw new Exception("Could not find a storage interface in the given module " + dllName); + + mime.Add(".gz", "application/gzip"); mime.Add(".js", "application/javascript"); mime.Add(".json", "application/json"); @@ -90,15 +118,19 @@ namespace OpenSim.Server.Handlers.Web private Hashtable WebRequestHandler(Hashtable request) { + long locIn = m_Database.GetCount("Presence", "RegionID != '00000000-0000-0000-0000-000000000000'"); // Locals online but not HGing. +// long HGin = m_Database.GetCount("hg_traveling_data", "GridExternalName = '" + ssi["uri"] + "'"); // HGers in world, and locals not HGing, sometimes more than once. + long locOut = m_Database.GetCount("hg_traveling_data", "GridExternalName != '" + ssi["uri"] + "'"); // Locals that are HGing. Hashtable reply = new Hashtable(); - // Looks like we have to jump through hoops to do simple database queries. B-( - ssi["members"] = "?"; // SELECT COUNT(PrincipalID) FROM UserAccounts - ssi["inworld"] = "?"; // SELECT COUNT(UserID) FROM presence_culled; Includes locals and HGers in world, but not locals HGing. - // SELECT COUNT(UserID) FROM users_online; Includes local online only. - ssi["outworld"] = "?"; // SELECT COUNT(UserID) FROM hg_traveling_data WHERE GridExternalName != ssi["uri"]; Includes locals that are HGing. -// ssi["hgers"] = "?"; // This is complex. - ssi["sims"] = "?"; // SELECT COUNT(uuid) FROM regions -// ssi["month"] = "?"; // SELECT COUNT(UserID) FROM Presence WHERE LastSeen < one month ago 2017-11-28 09:01:51; Includes external HGers, and locals on now. + ssi["members"] = m_Database.GetCount("UserAccounts").ToString(); + ssi["sims"] = m_Database.GetCount("regions").ToString(); + ssi["inworld"] = locIn.ToString(); + ssi["outworld"] = locOut.ToString(); +// ssi["hgers"] = HGin.ToString(); + ssi["hgers"] = "?"; + ssi["month"] = m_Database.GetCount("GridUser", "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200))").ToString(); + // SELECT COUNT(UserID) FROM Presence WHERE LastSeen < one month ago 2017-11-28 09:01:51; This is not accurate, and never has been. + // SELECT COUNT(UserID) FROM {GridUser} WHERE Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200) string reqpath = (string) request["uri"]; string[] query = (string[]) request["querystringkeys"]; -- cgit v1.1 From 46ee03817c719d035676e7611487f77863f59c6a Mon Sep 17 00:00:00 2001 From: onefang Date: Tue, 6 Aug 2019 02:28:30 +1000 Subject: Maybe now we can properly count locals and hypergridders on the web page? --- OpenSim/Server/Handlers/Web/WebServerInConnector.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs index 01c74fe..52ee9ae 100644 --- a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs @@ -118,19 +118,16 @@ namespace OpenSim.Server.Handlers.Web private Hashtable WebRequestHandler(Hashtable request) { - long locIn = m_Database.GetCount("Presence", "RegionID != '00000000-0000-0000-0000-000000000000'"); // Locals online but not HGing. -// long HGin = m_Database.GetCount("hg_traveling_data", "GridExternalName = '" + ssi["uri"] + "'"); // HGers in world, and locals not HGing, sometimes more than once. + long locIn = m_Database.GetCount("Presence", "RegionID != '00000000-0000-0000-0000-000000000000'"); // Locals online but not HGing, and HGers in world. + long HGin = m_Database.GetCount("Presence", "UserID NOT IN (SELECT PrincipalID FROM UserAccounts)"); // HGers in world. long locOut = m_Database.GetCount("hg_traveling_data", "GridExternalName != '" + ssi["uri"] + "'"); // Locals that are HGing. Hashtable reply = new Hashtable(); ssi["members"] = m_Database.GetCount("UserAccounts").ToString(); ssi["sims"] = m_Database.GetCount("regions").ToString(); - ssi["inworld"] = locIn.ToString(); + ssi["inworld"] = (locIn - HGin).ToString(); ssi["outworld"] = locOut.ToString(); -// ssi["hgers"] = HGin.ToString(); - ssi["hgers"] = "?"; + ssi["hgers"] = HGin.ToString(); ssi["month"] = m_Database.GetCount("GridUser", "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200))").ToString(); - // SELECT COUNT(UserID) FROM Presence WHERE LastSeen < one month ago 2017-11-28 09:01:51; This is not accurate, and never has been. - // SELECT COUNT(UserID) FROM {GridUser} WHERE Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200) string reqpath = (string) request["uri"]; string[] query = (string[]) request["querystringkeys"]; -- cgit v1.1 From 836189329de43906169ab26fa44396b53b91b713 Mon Sep 17 00:00:00 2001 From: onefang Date: Wed, 7 Aug 2019 00:12:46 +1000 Subject: The beginnings of an account management web page. Just some simple dynamic pages that don't actually do anything. --- .../Server/Handlers/Web/WebServerInConnector.cs | 207 ++++++++++++++++++--- 1 file changed, 183 insertions(+), 24 deletions(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs index 52ee9ae..8c14fde 100644 --- a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs @@ -51,7 +51,7 @@ namespace OpenSim.Server.Handlers.Web private IConfigSource m_Config; protected MySQLGenericHandler m_Database = null; private Hashtable mime = new Hashtable(); - private Hashtable ssi = new Hashtable(); + private Hashtable ssi = new Hashtable(); public WebServerInConnector(IConfigSource config, IHttpServer server, string configName) : base(config, server, configName) { @@ -76,12 +76,12 @@ namespace OpenSim.Server.Handlers.Web throw new Exception("No StorageProvider configured"); //// TODO - Should do the plugin thing to pick between database backends. +//// Or not, we are all using MariaDB anyway. // m_Database = LoadPlugin(dllName, new Object[] { connString }); m_Database = new MySQLGenericHandler(connString); if (m_Database == null) throw new Exception("Could not find a storage interface in the given module " + dllName); - mime.Add(".gz", "application/gzip"); mime.Add(".js", "application/javascript"); mime.Add(".json", "application/json"); @@ -135,41 +135,200 @@ namespace OpenSim.Server.Handlers.Web string method = (string) request["http-method"]; string type = (string) request["content-type"]; string body = (string) request["body"]; - string file = Path.Combine(Util.webDir(), reqpath.Remove(0, 5)); + string file = reqpath.Remove(0, 5); + string path = Path.Combine(Util.webDir(), file); + + m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} type {2} body {3}.", method, reqpath, type, body); + foreach (DictionaryEntry h in headers) + m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} header {2} = {3}", method, reqpath, (string) h.Key, (string) h.Value); + foreach (String q in query) + m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} query {2}", method, reqpath, q); reply["int_response_code"] = 200; - if (File.Exists(file)) - { - string m = (string) mime[Path.GetExtension(file).ToLower()]; - reply["content_type"] = m; - if ((null == m) || ("text/" != m.Substring(0, 5))) - { - reply["bin_response_data"] = File.ReadAllBytes(file); - } - else + if ("GET" == method) + { + if (File.Exists(path)) { - StreamReader csr = File.OpenText(file); - string content = csr.ReadToEnd(); - // Slow and wasteful, but I'm expecting only tiny web files, not accessed very often. - foreach (DictionaryEntry v in ssi) + string m = (string) mime[Path.GetExtension(path).ToLower()]; + reply["content_type"] = m; + if ((null == m) || ("text/" != m.Substring(0, 5))) + reply["bin_response_data"] = File.ReadAllBytes(path); + else { - content = content.Replace("", (string) v.Value); + StreamReader csr = File.OpenText(path); + string content = csr.ReadToEnd(); + // Slow and wasteful, but I'm expecting only tiny web files, not accessed very often. + foreach (DictionaryEntry v in ssi) + { + content = content.Replace("", (string) v.Value); + } + reply["str_response_string"] = content; + csr.Close(); } - reply["str_response_string"] = content; - csr.Close(); } - } - else + else + { + if ("account.html" == file) + reply["str_response_string"] = loginPage(null, ""); + else + { + m_log.ErrorFormat("[WEB SERVICE]: Unable to read {0}.", path); + reply["int_response_code"] = 404; + reply["content_type"] = "text/html"; + reply["str_response_string"] = "404 Unknown page" + + "404 error, can't find the " + reqpath + " page.

 

"; + } + } + } + else if ("POST" == method) { - m_log.ErrorFormat("[WEB SERVICE]: Unable to read {0}.", file); + Hashtable fields = new Hashtable(); + string[] bdy = body.Split('&'); + body = ""; + foreach (String bd in bdy) + { + string[] b = bd.Split('='); + if (b.Length == 0) + continue; + String n = System.Web.HttpUtility.UrlDecode(b[0]); + String v = ""; + if (b.Length > 1) + v = System.Web.HttpUtility.UrlDecode(b[1]); + fields[n] = v; + body = body + "

" + n + " = " + v + "

\n"; + } + + if ("account.html" == file) + { + if ("logout" == fields["doit"].ToString()) + reply["str_response_string"] = loginPage(null, "Logged out."); + else if ("create" == fields["doit"].ToString()) + { + if ("" == fields["email"].ToString()) + reply["str_response_string"] = loginPage(fields, "Please supply an email address when creating an account."); + else + { + reply["str_response_string"] = loggedOnPage(body, fields); + } + } + else + { + reply["str_response_string"] = loggedOnPage(body, fields); + } + } + else + { + m_log.ErrorFormat("[WEB SERVICE]: No such POST target {0}.", path); + reply["int_response_code"] = 404; + reply["content_type"] = "text/html"; + reply["str_response_string"] = "404 Unknown page" + + "404 error, can't find the " + reqpath + " page.

 

"; + } + } + else + { + m_log.ErrorFormat("[WEB SERVICE]: UNKNOWN method {0} path {1}.", method, reqpath); reply["int_response_code"] = 404; reply["content_type"] = "text/html"; - reply["str_response_string"] = "404 Unknown page" + - "404 error, can't find the " + reqpath + " page.

 

"; + reply["str_response_string"] = "Unknown method" + + "HUH! For " + reqpath + " page.

 

"; } + m_log.Info("[WEB SERVICE]: "); return reply; } + private string loginPage(Hashtable fields, string message) + { + string f = ""; + string l = ""; + string e = ""; + if (null != fields) + { + f = fields["firstName"].ToString(); + l = fields["lastName"].ToString(); + e = fields["email"].ToString(); + } + return header(ssi["grid"] + " account") + + form("account.html", "", + text("text", "first name", "firstName", f, 16, true) + + text("text", "last name", "lastName", l, 16, true) + + text("email", "email", "email", e, 0, false) + + text("password", "password", "password", "", 14,true) + + button("create") + + button("login") + ) + + "

" + message + "

" + + footer(); + } + + private string loggedOnPage(string body, Hashtable fields) + { + return header(ssi["grid"] + " account") + + "

" + ssi["grid"] + " account for " + fields["firstName"].ToString() + " " + fields["lastName"].ToString() + "

" + + form("account.html", fields["token"].ToString(), + hidden("firstName", fields["firstName"].ToString()) + + hidden("lastName", fields["lastName"].ToString()) + + text("email", "email", "email", fields["email"].ToString(), 0, false) + + text("password", "password", "password", "", 14, false) + + select("type", "type", + option("", false) + + option("approved", true) + + option("disabled", false) + + option("god", false) + ) + + button("delete") + + button("list") + + button("logout") +// + button("read") + + button("update") + ) + + body + + footer(); + } + + private string header(string title) + { + return "\n \n " + title + "\n \n \n"; + } + private string form(string action, string token, string form) + { + return "
\n" + hidden("token", token) + form + "
\n"; + } + private string hidden(string name, string val) + { + return " \n"; + } + private string text(string type, string title, string name, string val, int max, bool required) + { + string extra = ""; + if (0 < max) + extra = extra + " maxlength=\"" + max.ToString() + "\""; + if (required) + extra = extra + " required"; + if ("" != val) + val = "value=\"" + val + "\""; + return "

" + title + " :

\n"; + } + private string select(string title, string name, string options) + { + return "

" + title + " : \n \n

\n"; + } + private string option(string title, bool selected) + { + string sel = ""; + if (selected) + sel = " selected"; + return " \n"; + } + private string button(string title) + { + return " \n"; + } + private string footer() + { + return " \n\n"; + } + } } -- cgit v1.1 From 1613ca58be0cc3a4c53e72b63899b7fa4492ed7b Mon Sep 17 00:00:00 2001 From: onefang Date: Wed, 7 Aug 2019 07:44:25 +1000 Subject: Swap out MySQLGenericHandler and swap in MySQLRaw. Smaller, simpler, works better. --- OpenSim/Server/Handlers/Web/WebServerInConnector.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs index 8c14fde..bc34bae 100644 --- a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs @@ -49,7 +49,7 @@ namespace OpenSim.Server.Handlers.Web // This is all slow and clunky, it's not a real web server, just something to use if you don't want a real one. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private IConfigSource m_Config; - protected MySQLGenericHandler m_Database = null; + protected MySQLRaw m_database = null; private Hashtable mime = new Hashtable(); private Hashtable ssi = new Hashtable(); @@ -78,8 +78,9 @@ namespace OpenSim.Server.Handlers.Web //// TODO - Should do the plugin thing to pick between database backends. //// Or not, we are all using MariaDB anyway. // m_Database = LoadPlugin(dllName, new Object[] { connString }); - m_Database = new MySQLGenericHandler(connString); - if (m_Database == null) + + m_database = new MySQLRaw(connString); + if (m_database == null) throw new Exception("Could not find a storage interface in the given module " + dllName); mime.Add(".gz", "application/gzip"); @@ -118,16 +119,16 @@ namespace OpenSim.Server.Handlers.Web private Hashtable WebRequestHandler(Hashtable request) { - long locIn = m_Database.GetCount("Presence", "RegionID != '00000000-0000-0000-0000-000000000000'"); // Locals online but not HGing, and HGers in world. - long HGin = m_Database.GetCount("Presence", "UserID NOT IN (SELECT PrincipalID FROM UserAccounts)"); // HGers in world. - long locOut = m_Database.GetCount("hg_traveling_data", "GridExternalName != '" + ssi["uri"] + "'"); // Locals that are HGing. + long locIn = m_database.Count("Presence", "RegionID != '00000000-0000-0000-0000-000000000000'"); // Locals online but not HGing, and HGers in world. + long HGin = m_database.Count("Presence", "UserID NOT IN (SELECT PrincipalID FROM UserAccounts)"); // HGers in world. + long locOut = m_database.Count("hg_traveling_data", "GridExternalName != '" + ssi["uri"] + "'"); // Locals that are HGing. Hashtable reply = new Hashtable(); - ssi["members"] = m_Database.GetCount("UserAccounts").ToString(); - ssi["sims"] = m_Database.GetCount("regions").ToString(); + ssi["members"] = m_database.Count("UserAccounts").ToString(); + ssi["sims"] = m_database.Count("regions").ToString(); ssi["inworld"] = (locIn - HGin).ToString(); ssi["outworld"] = locOut.ToString(); ssi["hgers"] = HGin.ToString(); - ssi["month"] = m_Database.GetCount("GridUser", "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200))").ToString(); + ssi["month"] = m_database.Count("GridUser", "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200))").ToString(); string reqpath = (string) request["uri"]; string[] query = (string[]) request["querystringkeys"]; -- cgit v1.1 From 1b7c8cf7b54da6e1a59f9fc1039e78189be3815e Mon Sep 17 00:00:00 2001 From: onefang Date: Wed, 7 Aug 2019 07:45:44 +1000 Subject: Testing MySQLRaw's SELECT. --- OpenSim/Server/Handlers/Web/WebServerInConnector.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs index bc34bae..568b7d6 100644 --- a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs @@ -212,6 +212,17 @@ namespace OpenSim.Server.Handlers.Web reply["str_response_string"] = loggedOnPage(body, fields); } } + else if ("list" == fields["doit"].ToString()) + { + List< Hashtable > rows = m_database.Select("GridUser", "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200))"); + foreach (Hashtable row in rows) + { + string line = ""; + foreach (DictionaryEntry c in row) + line = line + " | " + (string) c.Value; + m_log.Info("[MariaDB RAW]: " + line); + } + } else { reply["str_response_string"] = loggedOnPage(body, fields); -- cgit v1.1 From afddecb2830f6afa73f869e120002d12803b3266 Mon Sep 17 00:00:00 2001 From: onefang Date: Wed, 7 Aug 2019 22:12:46 +1000 Subject: More account manager. Select with more parameters. Tables, with member accounts. Print the query values. --- .../Server/Handlers/Web/WebServerInConnector.cs | 65 +++++++++++++++++++--- 1 file changed, 56 insertions(+), 9 deletions(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs index 568b7d6..1dedfa3 100644 --- a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs @@ -143,7 +143,7 @@ namespace OpenSim.Server.Handlers.Web foreach (DictionaryEntry h in headers) m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} header {2} = {3}", method, reqpath, (string) h.Key, (string) h.Value); foreach (String q in query) - m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} query {2}", method, reqpath, q); + m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} query {2} value {3}", method, reqpath, q, (string) request[q]); reply["int_response_code"] = 200; if ("GET" == method) @@ -214,14 +214,12 @@ namespace OpenSim.Server.Handlers.Web } else if ("list" == fields["doit"].ToString()) { - List< Hashtable > rows = m_database.Select("GridUser", "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200))"); - foreach (Hashtable row in rows) - { - string line = ""; - foreach (DictionaryEntry c in row) - line = line + " | " + (string) c.Value; - m_log.Info("[MariaDB RAW]: " + line); - } + List< Hashtable > rows = m_database.Select("UserAccounts", + "CONCAT(FirstName,' ',LastName) as Name,UserTitle as Title,UserLevel as Level,UserFlags as Flags,PrincipalID as UUID", + "", "Name"); + reply["str_response_string"] = "member accounts" + + table(rows, new string[5] {"Name", "Title", "Level", "Flags", "UUID"}, "member accounts", + "account.html?doit=edit&token=" + fields["token"].ToString(), "UUID") + "

" + button("my account") + "

"; } else { @@ -281,8 +279,10 @@ namespace OpenSim.Server.Handlers.Web + form("account.html", fields["token"].ToString(), hidden("firstName", fields["firstName"].ToString()) + hidden("lastName", fields["lastName"].ToString()) +// + hidden("UUID", fields["UUID"].ToString()) + text("email", "email", "email", fields["email"].ToString(), 0, false) + text("password", "password", "password", "", 14, false) +// + text("title", "text", "title", fields["title"].ToString(), 0, false) + select("type", "type", option("", false) + option("approved", true) @@ -303,6 +303,53 @@ namespace OpenSim.Server.Handlers.Web { return "\n \n " + title + "\n \n \n"; } + // account.html?token=&UUID=.... + private string table(List< Hashtable > rows, string[] fields, string caption, string URL, string id) + { + string tbl = ""; + bool head = true; + string address = ""; + string addrend = ""; + foreach (Hashtable row in rows) + { + if (0 == fields.Length) + { + int c = 0; + foreach (DictionaryEntry r in row) + c++; + fields = new string[c]; + c = 0; + foreach (DictionaryEntry r in row) + fields[c++] = (string) r.Key; + } + string line = ""; + address = ""; + if ("" != URL) + { + address = ""; + if (head) + { + foreach (string s in fields) + line = line + ""; + tbl = tbl + line + "\n"; + head = false; + } + line = ""; + foreach (string s in fields) + { + if (s == id) + line = line + ""; + else + line = line + ""; + } + tbl = tbl + line + "\n"; + } + return tbl + "
" + caption + "
" + s + "
" + address + row[s] + addrend + "" + row[s] + "
"; + } private string form(string action, string token, string form) { return "
\n" + hidden("token", token) + form + "
\n"; -- cgit v1.1 From bab33ad24a4b960dc97eb0e179e99e52b12a1706 Mon Sep 17 00:00:00 2001 From: onefang Date: Thu, 8 Aug 2019 04:11:54 +1000 Subject: Various clean ups. --- .../Server/Handlers/Web/WebServerInConnector.cs | 113 ++++++++------------- 1 file changed, 44 insertions(+), 69 deletions(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs index 1dedfa3..bcfb7ac 100644 --- a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs @@ -1,30 +1,3 @@ -/* - * 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; @@ -34,11 +7,11 @@ using System.Reflection; using System.Security; using System.Text; using log4net; +using Nini.Config; using OpenMetaverse; using OpenMetaverse.StructuredData; -using Nini.Config; -using OpenSim.Framework; using OpenSim.Data.MySQL; +using OpenSim.Framework; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Server.Handlers.Base; @@ -55,14 +28,12 @@ namespace OpenSim.Server.Handlers.Web public WebServerInConnector(IConfigSource config, IHttpServer server, string configName) : base(config, server, configName) { - m_Config = config; - string dllName = String.Empty; string connString = String.Empty; - // + m_Config = config; + // Try reading the [DatabaseService] section, if it exists - // IConfig dbConfig = m_Config.Configs["DatabaseService"]; if (dbConfig != null) { @@ -71,7 +42,6 @@ namespace OpenSim.Server.Handlers.Web if (connString == String.Empty) connString = dbConfig.GetString("ConnectionString", String.Empty); } - if (dllName.Equals(String.Empty)) throw new Exception("No StorageProvider configured"); @@ -80,8 +50,6 @@ namespace OpenSim.Server.Handlers.Web // m_Database = LoadPlugin(dllName, new Object[] { connString }); m_database = new MySQLRaw(connString); - if (m_database == null) - throw new Exception("Could not find a storage interface in the given module " + dllName); mime.Add(".gz", "application/gzip"); mime.Add(".js", "application/javascript"); @@ -111,24 +79,24 @@ namespace OpenSim.Server.Handlers.Web IConfig cfg = m_Config.Configs["GridInfoService"]; string HomeURI = Util.GetConfigVarFromSections(m_Config, "HomeURI", new string[] { "Startup", "Hypergrid" }, String.Empty); - ssi.Add("grid", cfg.GetString("gridname", "my grid")); - ssi.Add("uri", cfg.GetString("login", HomeURI)); - ssi.Add("version", VersionInfo.Version); + ssi.Add("grid", cfg.GetString("gridname", "my grid")); + ssi.Add("uri", cfg.GetString("login", HomeURI)); + ssi.Add("version", VersionInfo.Version); server.AddHTTPHandler("/web/", WebRequestHandler); } private Hashtable WebRequestHandler(Hashtable request) { - long locIn = m_database.Count("Presence", "RegionID != '00000000-0000-0000-0000-000000000000'"); // Locals online but not HGing, and HGers in world. - long HGin = m_database.Count("Presence", "UserID NOT IN (SELECT PrincipalID FROM UserAccounts)"); // HGers in world. - long locOut = m_database.Count("hg_traveling_data", "GridExternalName != '" + ssi["uri"] + "'"); // Locals that are HGing. + long locIn = m_database.Count("Presence", "RegionID != '00000000-0000-0000-0000-000000000000'"); // Locals online but not HGing, and HGers in world. + long HGin = m_database.Count("Presence", "UserID NOT IN (SELECT PrincipalID FROM UserAccounts)"); // HGers in world. + long locOut = m_database.Count("hg_traveling_data", "GridExternalName != '" + ssi["uri"] + "'"); // Locals that are HGing. Hashtable reply = new Hashtable(); - ssi["members"] = m_database.Count("UserAccounts").ToString(); - ssi["sims"] = m_database.Count("regions").ToString(); - ssi["inworld"] = (locIn - HGin).ToString(); - ssi["outworld"] = locOut.ToString(); - ssi["hgers"] = HGin.ToString(); - ssi["month"] = m_database.Count("GridUser", "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200))").ToString(); + ssi["members"] = m_database.Count("UserAccounts").ToString(); + ssi["sims"] = m_database.Count("regions").ToString(); + ssi["inworld"] = (locIn - HGin).ToString(); + ssi["outworld"] = locOut.ToString(); + ssi["hgers"] = HGin.ToString(); + ssi["month"] = m_database.Count("GridUser", "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200))").ToString(); string reqpath = (string) request["uri"]; string[] query = (string[]) request["querystringkeys"]; @@ -148,26 +116,26 @@ namespace OpenSim.Server.Handlers.Web reply["int_response_code"] = 200; if ("GET" == method) { - if (File.Exists(path)) - { - string m = (string) mime[Path.GetExtension(path).ToLower()]; - reply["content_type"] = m; - if ((null == m) || ("text/" != m.Substring(0, 5))) - reply["bin_response_data"] = File.ReadAllBytes(path); - else - { - StreamReader csr = File.OpenText(path); - string content = csr.ReadToEnd(); - // Slow and wasteful, but I'm expecting only tiny web files, not accessed very often. - foreach (DictionaryEntry v in ssi) - { - content = content.Replace("", (string) v.Value); - } - reply["str_response_string"] = content; - csr.Close(); - } - } - else + if (File.Exists(path)) + { + string m = (string) mime[Path.GetExtension(path).ToLower()]; + reply["content_type"] = m; + if ((null == m) || ("text/" != m.Substring(0, 5))) + reply["bin_response_data"] = File.ReadAllBytes(path); + else + { + StreamReader csr = File.OpenText(path); + string content = csr.ReadToEnd(); + // Slow and wasteful, but I'm expecting only tiny web files, not accessed very often. + foreach (DictionaryEntry v in ssi) + { + content = content.Replace("", (string) v.Value); + } + reply["str_response_string"] = content; + csr.Close(); + } + } + else { if ("account.html" == file) reply["str_response_string"] = loginPage(null, ""); @@ -303,7 +271,7 @@ namespace OpenSim.Server.Handlers.Web { return "\n \n " + title + "\n \n \n"; } - // account.html?token=&UUID=.... + private string table(List< Hashtable > rows, string[] fields, string caption, string URL, string id) { string tbl = ""; @@ -350,14 +318,17 @@ namespace OpenSim.Server.Handlers.Web } return tbl + "
" + caption + "
"; } + private string form(string action, string token, string form) { return "
\n" + hidden("token", token) + form + "
\n"; } + private string hidden(string name, string val) { return " \n"; } + private string text(string type, string title, string name, string val, int max, bool required) { string extra = ""; @@ -369,10 +340,12 @@ namespace OpenSim.Server.Handlers.Web val = "value=\"" + val + "\""; return "

" + title + " :

\n"; } + private string select(string title, string name, string options) { return "

" + title + " : \n \n

\n"; } + private string option(string title, bool selected) { string sel = ""; @@ -380,10 +353,12 @@ namespace OpenSim.Server.Handlers.Web sel = " selected"; return " \n"; } + private string button(string title) { return " \n"; } + private string footer() { return " \n\n"; -- cgit v1.1 From 7dffa1fa67ed668872d96036a508e2be64cb8b5c Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 11 Aug 2019 22:21:39 +1000 Subject: WebServerInConnector -> WebServerConnector Just a name change. --- OpenSim/Server/Handlers/Web/WebServerConnector.cs | 368 +++++++++++++++++++++ .../Server/Handlers/Web/WebServerInConnector.cs | 368 --------------------- 2 files changed, 368 insertions(+), 368 deletions(-) create mode 100644 OpenSim/Server/Handlers/Web/WebServerConnector.cs delete mode 100644 OpenSim/Server/Handlers/Web/WebServerInConnector.cs (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerConnector.cs b/OpenSim/Server/Handlers/Web/WebServerConnector.cs new file mode 100644 index 0000000..2607386 --- /dev/null +++ b/OpenSim/Server/Handlers/Web/WebServerConnector.cs @@ -0,0 +1,368 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Reflection; +using System.Security; +using System.Text; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Data.MySQL; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; + +namespace OpenSim.Server.Handlers.Web +{ + public class WebServerConnector : ServiceConnector + { + // This is all slow and clunky, it's not a real web server, just something to use if you don't want a real one. + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private IConfigSource m_Config; + protected MySQLRaw m_database = null; + private Hashtable mime = new Hashtable(); + private Hashtable ssi = new Hashtable(); + + public WebServerConnector(IConfigSource config, IHttpServer server, string configName) : base(config, server, configName) + { + string dllName = String.Empty; + string connString = String.Empty; + + m_Config = config; + + // Try reading the [DatabaseService] section, if it exists + IConfig dbConfig = m_Config.Configs["DatabaseService"]; + if (dbConfig != null) + { + if (dllName == String.Empty) + dllName = dbConfig.GetString("StorageProvider", String.Empty); + if (connString == String.Empty) + connString = dbConfig.GetString("ConnectionString", String.Empty); + } + if (dllName.Equals(String.Empty)) + throw new Exception("No StorageProvider configured"); + +//// TODO - Should do the plugin thing to pick between database backends. +//// Or not, we are all using MariaDB anyway. +// m_Database = LoadPlugin(dllName, new Object[] { connString }); + + m_database = new MySQLRaw(connString); + + mime.Add(".gz", "application/gzip"); + mime.Add(".js", "application/javascript"); + mime.Add(".json", "application/json"); + mime.Add(".pdf", "application/pdf"); + mime.Add(".rtf", "application/rtf"); + mime.Add(".zip", "application/zip"); + mime.Add(".xz", "application/x-xz"); + mime.Add(".gif", "image/gif"); + mime.Add(".png", "image/png"); + mime.Add(".jp2", "image/jp2"); + mime.Add(".jpg2", "image/jp2"); + mime.Add(".jpe", "image/jpeg"); + mime.Add(".jpg", "image/jpeg"); + mime.Add(".jpeg", "image/jpeg"); + mime.Add(".svg", "image/svg+xml"); + mime.Add(".svgz", "image/svg+xml"); + mime.Add(".tif", "image/tiff"); + mime.Add(".tiff", "image/tiff"); + mime.Add(".css", "text/css"); + mime.Add(".html", "text/html"); + mime.Add(".htm", "text/html"); + mime.Add(".shtml", "text/html"); +// mime.Add(".md", "text/markdown"); +// mime.Add(".markdown","text/markdown"); + mime.Add(".txt", "text/plain"); + + IConfig cfg = m_Config.Configs["GridInfoService"]; + string HomeURI = Util.GetConfigVarFromSections(m_Config, "HomeURI", new string[] { "Startup", "Hypergrid" }, String.Empty); + ssi.Add("grid", cfg.GetString("gridname", "my grid")); + ssi.Add("uri", cfg.GetString("login", HomeURI)); + ssi.Add("version", VersionInfo.Version); + server.AddHTTPHandler("/web/", WebRequestHandler); + } + + private Hashtable WebRequestHandler(Hashtable request) + { + long locIn = m_database.Count("Presence", "RegionID != '00000000-0000-0000-0000-000000000000'"); // Locals online but not HGing, and HGers in world. + long HGin = m_database.Count("Presence", "UserID NOT IN (SELECT PrincipalID FROM UserAccounts)"); // HGers in world. + long locOut = m_database.Count("hg_traveling_data", "GridExternalName != '" + ssi["uri"] + "'"); // Locals that are HGing. + Hashtable reply = new Hashtable(); + ssi["members"] = m_database.Count("UserAccounts").ToString(); + ssi["sims"] = m_database.Count("regions").ToString(); + ssi["inworld"] = (locIn - HGin).ToString(); + ssi["outworld"] = locOut.ToString(); + ssi["hgers"] = HGin.ToString(); + ssi["month"] = m_database.Count("GridUser", "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200))").ToString(); + + string reqpath = (string) request["uri"]; + string[] query = (string[]) request["querystringkeys"]; + Hashtable headers = (Hashtable) request["headers"]; + string method = (string) request["http-method"]; + string type = (string) request["content-type"]; + string body = (string) request["body"]; + string file = reqpath.Remove(0, 5); + string path = Path.Combine(Util.webDir(), file); + + m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} type {2} body {3}.", method, reqpath, type, body); + foreach (DictionaryEntry h in headers) + m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} header {2} = {3}", method, reqpath, (string) h.Key, (string) h.Value); + foreach (String q in query) + m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} query {2} value {3}", method, reqpath, q, (string) request[q]); + + reply["int_response_code"] = 200; + if ("GET" == method) + { + if (File.Exists(path)) + { + string m = (string) mime[Path.GetExtension(path).ToLower()]; + reply["content_type"] = m; + if ((null == m) || ("text/" != m.Substring(0, 5))) + reply["bin_response_data"] = File.ReadAllBytes(path); + else + { + StreamReader csr = File.OpenText(path); + string content = csr.ReadToEnd(); + // Slow and wasteful, but I'm expecting only tiny web files, not accessed very often. + foreach (DictionaryEntry v in ssi) + { + content = content.Replace("", (string) v.Value); + } + reply["str_response_string"] = content; + csr.Close(); + } + } + else + { + if ("account.html" == file) + reply["str_response_string"] = loginPage(null, ""); + else + { + m_log.ErrorFormat("[WEB SERVICE]: Unable to read {0}.", path); + reply["int_response_code"] = 404; + reply["content_type"] = "text/html"; + reply["str_response_string"] = "404 Unknown page" + + "404 error, can't find the " + reqpath + " page.

 

"; + } + } + } + else if ("POST" == method) + { + Hashtable fields = new Hashtable(); + string[] bdy = body.Split('&'); + body = ""; + foreach (String bd in bdy) + { + string[] b = bd.Split('='); + if (b.Length == 0) + continue; + String n = System.Web.HttpUtility.UrlDecode(b[0]); + String v = ""; + if (b.Length > 1) + v = System.Web.HttpUtility.UrlDecode(b[1]); + fields[n] = v; + body = body + "

" + n + " = " + v + "

\n"; + } + + if ("account.html" == file) + { + if ("logout" == fields["doit"].ToString()) + reply["str_response_string"] = loginPage(null, "Logged out."); + else if ("create" == fields["doit"].ToString()) + { + if ("" == fields["email"].ToString()) + reply["str_response_string"] = loginPage(fields, "Please supply an email address when creating an account."); + else + { + reply["str_response_string"] = loggedOnPage(body, fields); + } + } + else if ("list" == fields["doit"].ToString()) + { + List< Hashtable > rows = m_database.Select("UserAccounts", + "CONCAT(FirstName,' ',LastName) as Name,UserTitle as Title,UserLevel as Level,UserFlags as Flags,PrincipalID as UUID", + "", "Name"); + reply["str_response_string"] = "member accounts" + + table(rows, new string[5] {"Name", "Title", "Level", "Flags", "UUID"}, "member accounts", + "account.html?doit=edit&token=" + fields["token"].ToString(), "UUID") + "

" + button("my account") + "

"; + } + else + { + reply["str_response_string"] = loggedOnPage(body, fields); + } + } + else + { + m_log.ErrorFormat("[WEB SERVICE]: No such POST target {0}.", path); + reply["int_response_code"] = 404; + reply["content_type"] = "text/html"; + reply["str_response_string"] = "404 Unknown page" + + "404 error, can't find the " + reqpath + " page.

 

"; + } + } + else + { + m_log.ErrorFormat("[WEB SERVICE]: UNKNOWN method {0} path {1}.", method, reqpath); + reply["int_response_code"] = 404; + reply["content_type"] = "text/html"; + reply["str_response_string"] = "Unknown method" + + "HUH! For " + reqpath + " page.

 

"; + } + + m_log.Info("[WEB SERVICE]: "); + return reply; + } + + private string loginPage(Hashtable fields, string message) + { + string f = ""; + string l = ""; + string e = ""; + if (null != fields) + { + f = fields["firstName"].ToString(); + l = fields["lastName"].ToString(); + e = fields["email"].ToString(); + } + return header(ssi["grid"] + " account") + + form("account.html", "", + text("text", "first name", "firstName", f, 16, true) + + text("text", "last name", "lastName", l, 16, true) + + text("email", "email", "email", e, 0, false) + + text("password", "password", "password", "", 14,true) + + button("create") + + button("login") + ) + + "

" + message + "

" + + footer(); + } + + private string loggedOnPage(string body, Hashtable fields) + { + return header(ssi["grid"] + " account") + + "

" + ssi["grid"] + " account for " + fields["firstName"].ToString() + " " + fields["lastName"].ToString() + "

" + + form("account.html", fields["token"].ToString(), + hidden("firstName", fields["firstName"].ToString()) + + hidden("lastName", fields["lastName"].ToString()) +// + hidden("UUID", fields["UUID"].ToString()) + + text("email", "email", "email", fields["email"].ToString(), 0, false) + + text("password", "password", "password", "", 14, false) +// + text("title", "text", "title", fields["title"].ToString(), 0, false) + + select("type", "type", + option("", false) + + option("approved", true) + + option("disabled", false) + + option("god", false) + ) + + button("delete") + + button("list") + + button("logout") +// + button("read") + + button("update") + ) + + body + + footer(); + } + + private string header(string title) + { + return "\n \n " + title + "\n \n \n"; + } + + private string table(List< Hashtable > rows, string[] fields, string caption, string URL, string id) + { + string tbl = ""; + bool head = true; + string address = ""; + string addrend = ""; + foreach (Hashtable row in rows) + { + if (0 == fields.Length) + { + int c = 0; + foreach (DictionaryEntry r in row) + c++; + fields = new string[c]; + c = 0; + foreach (DictionaryEntry r in row) + fields[c++] = (string) r.Key; + } + string line = ""; + address = ""; + if ("" != URL) + { + address = ""; + if (head) + { + foreach (string s in fields) + line = line + ""; + tbl = tbl + line + "\n"; + head = false; + } + line = ""; + foreach (string s in fields) + { + if (s == id) + line = line + ""; + else + line = line + ""; + } + tbl = tbl + line + "\n"; + } + return tbl + "
" + caption + "
" + s + "
" + address + row[s] + addrend + "" + row[s] + "
"; + } + + private string form(string action, string token, string form) + { + return "
\n" + hidden("token", token) + form + "
\n"; + } + + private string hidden(string name, string val) + { + return " \n"; + } + + private string text(string type, string title, string name, string val, int max, bool required) + { + string extra = ""; + if (0 < max) + extra = extra + " maxlength=\"" + max.ToString() + "\""; + if (required) + extra = extra + " required"; + if ("" != val) + val = "value=\"" + val + "\""; + return "

" + title + " :

\n"; + } + + private string select(string title, string name, string options) + { + return "

" + title + " : \n \n

\n"; + } + + private string option(string title, bool selected) + { + string sel = ""; + if (selected) + sel = " selected"; + return " \n"; + } + + private string button(string title) + { + return " \n"; + } + + private string footer() + { + return " \n\n"; + } + + } +} diff --git a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs b/OpenSim/Server/Handlers/Web/WebServerInConnector.cs deleted file mode 100644 index bcfb7ac..0000000 --- a/OpenSim/Server/Handlers/Web/WebServerInConnector.cs +++ /dev/null @@ -1,368 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Reflection; -using System.Security; -using System.Text; -using log4net; -using Nini.Config; -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using OpenSim.Data.MySQL; -using OpenSim.Framework; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Server.Handlers.Base; - -namespace OpenSim.Server.Handlers.Web -{ - public class WebServerInConnector : ServiceConnector - { - // This is all slow and clunky, it's not a real web server, just something to use if you don't want a real one. - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private IConfigSource m_Config; - protected MySQLRaw m_database = null; - private Hashtable mime = new Hashtable(); - private Hashtable ssi = new Hashtable(); - - public WebServerInConnector(IConfigSource config, IHttpServer server, string configName) : base(config, server, configName) - { - string dllName = String.Empty; - string connString = String.Empty; - - m_Config = config; - - // Try reading the [DatabaseService] section, if it exists - IConfig dbConfig = m_Config.Configs["DatabaseService"]; - if (dbConfig != null) - { - if (dllName == String.Empty) - dllName = dbConfig.GetString("StorageProvider", String.Empty); - if (connString == String.Empty) - connString = dbConfig.GetString("ConnectionString", String.Empty); - } - if (dllName.Equals(String.Empty)) - throw new Exception("No StorageProvider configured"); - -//// TODO - Should do the plugin thing to pick between database backends. -//// Or not, we are all using MariaDB anyway. -// m_Database = LoadPlugin(dllName, new Object[] { connString }); - - m_database = new MySQLRaw(connString); - - mime.Add(".gz", "application/gzip"); - mime.Add(".js", "application/javascript"); - mime.Add(".json", "application/json"); - mime.Add(".pdf", "application/pdf"); - mime.Add(".rtf", "application/rtf"); - mime.Add(".zip", "application/zip"); - mime.Add(".xz", "application/x-xz"); - mime.Add(".gif", "image/gif"); - mime.Add(".png", "image/png"); - mime.Add(".jp2", "image/jp2"); - mime.Add(".jpg2", "image/jp2"); - mime.Add(".jpe", "image/jpeg"); - mime.Add(".jpg", "image/jpeg"); - mime.Add(".jpeg", "image/jpeg"); - mime.Add(".svg", "image/svg+xml"); - mime.Add(".svgz", "image/svg+xml"); - mime.Add(".tif", "image/tiff"); - mime.Add(".tiff", "image/tiff"); - mime.Add(".css", "text/css"); - mime.Add(".html", "text/html"); - mime.Add(".htm", "text/html"); - mime.Add(".shtml", "text/html"); -// mime.Add(".md", "text/markdown"); -// mime.Add(".markdown","text/markdown"); - mime.Add(".txt", "text/plain"); - - IConfig cfg = m_Config.Configs["GridInfoService"]; - string HomeURI = Util.GetConfigVarFromSections(m_Config, "HomeURI", new string[] { "Startup", "Hypergrid" }, String.Empty); - ssi.Add("grid", cfg.GetString("gridname", "my grid")); - ssi.Add("uri", cfg.GetString("login", HomeURI)); - ssi.Add("version", VersionInfo.Version); - server.AddHTTPHandler("/web/", WebRequestHandler); - } - - private Hashtable WebRequestHandler(Hashtable request) - { - long locIn = m_database.Count("Presence", "RegionID != '00000000-0000-0000-0000-000000000000'"); // Locals online but not HGing, and HGers in world. - long HGin = m_database.Count("Presence", "UserID NOT IN (SELECT PrincipalID FROM UserAccounts)"); // HGers in world. - long locOut = m_database.Count("hg_traveling_data", "GridExternalName != '" + ssi["uri"] + "'"); // Locals that are HGing. - Hashtable reply = new Hashtable(); - ssi["members"] = m_database.Count("UserAccounts").ToString(); - ssi["sims"] = m_database.Count("regions").ToString(); - ssi["inworld"] = (locIn - HGin).ToString(); - ssi["outworld"] = locOut.ToString(); - ssi["hgers"] = HGin.ToString(); - ssi["month"] = m_database.Count("GridUser", "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200))").ToString(); - - string reqpath = (string) request["uri"]; - string[] query = (string[]) request["querystringkeys"]; - Hashtable headers = (Hashtable) request["headers"]; - string method = (string) request["http-method"]; - string type = (string) request["content-type"]; - string body = (string) request["body"]; - string file = reqpath.Remove(0, 5); - string path = Path.Combine(Util.webDir(), file); - - m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} type {2} body {3}.", method, reqpath, type, body); - foreach (DictionaryEntry h in headers) - m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} header {2} = {3}", method, reqpath, (string) h.Key, (string) h.Value); - foreach (String q in query) - m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} query {2} value {3}", method, reqpath, q, (string) request[q]); - - reply["int_response_code"] = 200; - if ("GET" == method) - { - if (File.Exists(path)) - { - string m = (string) mime[Path.GetExtension(path).ToLower()]; - reply["content_type"] = m; - if ((null == m) || ("text/" != m.Substring(0, 5))) - reply["bin_response_data"] = File.ReadAllBytes(path); - else - { - StreamReader csr = File.OpenText(path); - string content = csr.ReadToEnd(); - // Slow and wasteful, but I'm expecting only tiny web files, not accessed very often. - foreach (DictionaryEntry v in ssi) - { - content = content.Replace("", (string) v.Value); - } - reply["str_response_string"] = content; - csr.Close(); - } - } - else - { - if ("account.html" == file) - reply["str_response_string"] = loginPage(null, ""); - else - { - m_log.ErrorFormat("[WEB SERVICE]: Unable to read {0}.", path); - reply["int_response_code"] = 404; - reply["content_type"] = "text/html"; - reply["str_response_string"] = "404 Unknown page" + - "404 error, can't find the " + reqpath + " page.

 

"; - } - } - } - else if ("POST" == method) - { - Hashtable fields = new Hashtable(); - string[] bdy = body.Split('&'); - body = ""; - foreach (String bd in bdy) - { - string[] b = bd.Split('='); - if (b.Length == 0) - continue; - String n = System.Web.HttpUtility.UrlDecode(b[0]); - String v = ""; - if (b.Length > 1) - v = System.Web.HttpUtility.UrlDecode(b[1]); - fields[n] = v; - body = body + "

" + n + " = " + v + "

\n"; - } - - if ("account.html" == file) - { - if ("logout" == fields["doit"].ToString()) - reply["str_response_string"] = loginPage(null, "Logged out."); - else if ("create" == fields["doit"].ToString()) - { - if ("" == fields["email"].ToString()) - reply["str_response_string"] = loginPage(fields, "Please supply an email address when creating an account."); - else - { - reply["str_response_string"] = loggedOnPage(body, fields); - } - } - else if ("list" == fields["doit"].ToString()) - { - List< Hashtable > rows = m_database.Select("UserAccounts", - "CONCAT(FirstName,' ',LastName) as Name,UserTitle as Title,UserLevel as Level,UserFlags as Flags,PrincipalID as UUID", - "", "Name"); - reply["str_response_string"] = "member accounts" + - table(rows, new string[5] {"Name", "Title", "Level", "Flags", "UUID"}, "member accounts", - "account.html?doit=edit&token=" + fields["token"].ToString(), "UUID") + "

" + button("my account") + "

"; - } - else - { - reply["str_response_string"] = loggedOnPage(body, fields); - } - } - else - { - m_log.ErrorFormat("[WEB SERVICE]: No such POST target {0}.", path); - reply["int_response_code"] = 404; - reply["content_type"] = "text/html"; - reply["str_response_string"] = "404 Unknown page" + - "404 error, can't find the " + reqpath + " page.

 

"; - } - } - else - { - m_log.ErrorFormat("[WEB SERVICE]: UNKNOWN method {0} path {1}.", method, reqpath); - reply["int_response_code"] = 404; - reply["content_type"] = "text/html"; - reply["str_response_string"] = "Unknown method" + - "HUH! For " + reqpath + " page.

 

"; - } - - m_log.Info("[WEB SERVICE]: "); - return reply; - } - - private string loginPage(Hashtable fields, string message) - { - string f = ""; - string l = ""; - string e = ""; - if (null != fields) - { - f = fields["firstName"].ToString(); - l = fields["lastName"].ToString(); - e = fields["email"].ToString(); - } - return header(ssi["grid"] + " account") - + form("account.html", "", - text("text", "first name", "firstName", f, 16, true) - + text("text", "last name", "lastName", l, 16, true) - + text("email", "email", "email", e, 0, false) - + text("password", "password", "password", "", 14,true) - + button("create") - + button("login") - ) - + "

" + message + "

" - + footer(); - } - - private string loggedOnPage(string body, Hashtable fields) - { - return header(ssi["grid"] + " account") - + "

" + ssi["grid"] + " account for " + fields["firstName"].ToString() + " " + fields["lastName"].ToString() + "

" - + form("account.html", fields["token"].ToString(), - hidden("firstName", fields["firstName"].ToString()) - + hidden("lastName", fields["lastName"].ToString()) -// + hidden("UUID", fields["UUID"].ToString()) - + text("email", "email", "email", fields["email"].ToString(), 0, false) - + text("password", "password", "password", "", 14, false) -// + text("title", "text", "title", fields["title"].ToString(), 0, false) - + select("type", "type", - option("", false) - + option("approved", true) - + option("disabled", false) - + option("god", false) - ) - + button("delete") - + button("list") - + button("logout") -// + button("read") - + button("update") - ) - + body - + footer(); - } - - private string header(string title) - { - return "\n \n " + title + "\n \n \n"; - } - - private string table(List< Hashtable > rows, string[] fields, string caption, string URL, string id) - { - string tbl = ""; - bool head = true; - string address = ""; - string addrend = ""; - foreach (Hashtable row in rows) - { - if (0 == fields.Length) - { - int c = 0; - foreach (DictionaryEntry r in row) - c++; - fields = new string[c]; - c = 0; - foreach (DictionaryEntry r in row) - fields[c++] = (string) r.Key; - } - string line = ""; - address = ""; - if ("" != URL) - { - address = ""; - if (head) - { - foreach (string s in fields) - line = line + ""; - tbl = tbl + line + "\n"; - head = false; - } - line = ""; - foreach (string s in fields) - { - if (s == id) - line = line + ""; - else - line = line + ""; - } - tbl = tbl + line + "\n"; - } - return tbl + "
" + caption + "
" + s + "
" + address + row[s] + addrend + "" + row[s] + "
"; - } - - private string form(string action, string token, string form) - { - return "
\n" + hidden("token", token) + form + "
\n"; - } - - private string hidden(string name, string val) - { - return " \n"; - } - - private string text(string type, string title, string name, string val, int max, bool required) - { - string extra = ""; - if (0 < max) - extra = extra + " maxlength=\"" + max.ToString() + "\""; - if (required) - extra = extra + " required"; - if ("" != val) - val = "value=\"" + val + "\""; - return "

" + title + " :

\n"; - } - - private string select(string title, string name, string options) - { - return "

" + title + " : \n \n

\n"; - } - - private string option(string title, bool selected) - { - string sel = ""; - if (selected) - sel = " selected"; - return " \n"; - } - - private string button(string title) - { - return " \n"; - } - - private string footer() - { - return " \n\n"; - } - - } -} -- cgit v1.1 From 70efa042176d2dd1c49f9f00a6e5b9452bbc9de6 Mon Sep 17 00:00:00 2001 From: onefang Date: Tue, 13 Aug 2019 07:35:50 +1000 Subject: Beef up the web server a bit. Sanatize the path. Add support for Last-Modified, If-Modified-Since, and Cache-Control: no-cache. Teach the base server about more binary content types. --- OpenSim/Server/Handlers/Web/WebServerConnector.cs | 37 +++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerConnector.cs b/OpenSim/Server/Handlers/Web/WebServerConnector.cs index 2607386..06fd892 100644 --- a/OpenSim/Server/Handlers/Web/WebServerConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerConnector.cs @@ -91,6 +91,7 @@ namespace OpenSim.Server.Handlers.Web long HGin = m_database.Count("Presence", "UserID NOT IN (SELECT PrincipalID FROM UserAccounts)"); // HGers in world. long locOut = m_database.Count("hg_traveling_data", "GridExternalName != '" + ssi["uri"] + "'"); // Locals that are HGing. Hashtable reply = new Hashtable(); + Hashtable replyHeaders = new Hashtable(); ssi["members"] = m_database.Count("UserAccounts").ToString(); ssi["sims"] = m_database.Count("regions").ToString(); ssi["inworld"] = (locIn - HGin).ToString(); @@ -107,6 +108,16 @@ namespace OpenSim.Server.Handlers.Web string file = reqpath.Remove(0, 5); string path = Path.Combine(Util.webDir(), file); + if (! Path.GetFullPath(path).StartsWith(Path.GetFullPath(Util.webDir()))) + { + m_log.ErrorFormat("[WEB SERVICE]: INVALID PATH {0} != {1}", Path.GetFullPath(path), Path.GetFullPath(Util.webDir())); + reply["int_response_code"] = 404; + reply["content_type"] = "text/html"; + reply["str_response_string"] = "404 Unknown page" + + "404 error, can't find the " + reqpath + " page.

 

"; + return reply; + } + m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} type {2} body {3}.", method, reqpath, type, body); foreach (DictionaryEntry h in headers) m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} header {2} = {3}", method, reqpath, (string) h.Key, (string) h.Value); @@ -118,12 +129,36 @@ namespace OpenSim.Server.Handlers.Web { if (File.Exists(path)) { + DateTime dt = File.GetLastWriteTimeUtc(path); string m = (string) mime[Path.GetExtension(path).ToLower()]; reply["content_type"] = m; if ((null == m) || ("text/" != m.Substring(0, 5))) + { + string ifdtr = (string) headers["if-modified-since"]; + if (null != ifdtr) + { + try + { + DateTime ifdt = DateTime.Parse(ifdtr, System.Globalization.CultureInfo.InvariantCulture); + if (0 >= DateTime.Compare(ifdt, dt)) + { + reply["int_response_code"] = 304; + m_log.InfoFormat("[WEB SERVICE]: If-Modified-Since is earliar or equal to Last-Modified, from {0}", path); + reply["headers"] = replyHeaders; + return reply; + } + } + catch (Exception) + { + m_log.ErrorFormat("[WEB SERVICE]: Invalid If-Modified-Since header, ignoring it, from {0}", path); + } + } + replyHeaders["Last-Modified"] = dt.ToString("R"); reply["bin_response_data"] = File.ReadAllBytes(path); + } else { + replyHeaders["Cache-Control"] = "no-cache"; StreamReader csr = File.OpenText(path); string content = csr.ReadToEnd(); // Slow and wasteful, but I'm expecting only tiny web files, not accessed very often. @@ -169,6 +204,7 @@ namespace OpenSim.Server.Handlers.Web if ("account.html" == file) { + replyHeaders["Cache-Control"] = "no-cache"; if ("logout" == fields["doit"].ToString()) reply["str_response_string"] = loginPage(null, "Logged out."); else if ("create" == fields["doit"].ToString()) @@ -213,6 +249,7 @@ namespace OpenSim.Server.Handlers.Web } m_log.Info("[WEB SERVICE]: "); + reply["headers"] = replyHeaders; return reply; } -- cgit v1.1 From 9c043cbf4c9adb85acef5c9ffa269d4180f44832 Mon Sep 17 00:00:00 2001 From: onefang Date: Sat, 17 Aug 2019 07:05:49 +1000 Subject: Simple web server gets HTTPS. --- OpenSim/Server/Handlers/Web/WebServerConnector.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerConnector.cs b/OpenSim/Server/Handlers/Web/WebServerConnector.cs index 06fd892..3a8e906 100644 --- a/OpenSim/Server/Handlers/Web/WebServerConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerConnector.cs @@ -12,6 +12,7 @@ using OpenMetaverse; using OpenMetaverse.StructuredData; using OpenSim.Data.MySQL; using OpenSim.Framework; +using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Server.Handlers.Base; @@ -82,8 +83,20 @@ namespace OpenSim.Server.Handlers.Web ssi.Add("grid", cfg.GetString("gridname", "my grid")); ssi.Add("uri", cfg.GetString("login", HomeURI)); ssi.Add("version", VersionInfo.Version); + server.AddHTTPHandler("/web/", WebRequestHandler); - } + IConfig networkConfig = m_Config.Configs["Network"]; + if (null != networkConfig) + { + uint https_port = (uint) networkConfig.GetInt("https_port", 0); + if (0 != https_port) + { + server = MainServer.GetHttpServer(https_port, null); + if (null != server) + server.AddHTTPHandler("/web/", WebRequestHandler); + } + } + } private Hashtable WebRequestHandler(Hashtable request) { -- cgit v1.1 From ee33dd4b56f7782bbf7798fa3ff8821ff81acd36 Mon Sep 17 00:00:00 2001 From: onefang Date: Sat, 17 Aug 2019 07:09:16 +1000 Subject: VArious additions to account manager. First and last names merged into one name. Is name two words check, a suprisingly effective spam blocker. Poor mans Bobby Tables protection. Various other input checking. Added account creation confirmation page. Some text and length tweaks. --- OpenSim/Server/Handlers/Web/WebServerConnector.cs | 102 ++++++++++++++++++---- 1 file changed, 83 insertions(+), 19 deletions(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerConnector.cs b/OpenSim/Server/Handlers/Web/WebServerConnector.cs index 3a8e906..7879e4e 100644 --- a/OpenSim/Server/Handlers/Web/WebServerConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerConnector.cs @@ -6,6 +6,7 @@ using System.Net; using System.Reflection; using System.Security; using System.Text; +using System.Text.RegularExpressions; using log4net; using Nini.Config; using OpenMetaverse; @@ -131,13 +132,14 @@ namespace OpenSim.Server.Handlers.Web return reply; } - m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} type {2} body {3}.", method, reqpath, type, body); + m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} contont type {2} body {3}.", method, reqpath, type, body); foreach (DictionaryEntry h in headers) m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} header {2} = {3}", method, reqpath, (string) h.Key, (string) h.Value); foreach (String q in query) m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} query {2} value {3}", method, reqpath, q, (string) request[q]); reply["int_response_code"] = 200; +// TODO - need to support HEAD method, seems to be what triggers the endles GETs. if ("GET" == method) { if (File.Exists(path)) @@ -211,25 +213,71 @@ namespace OpenSim.Server.Handlers.Web String v = ""; if (b.Length > 1) v = System.Web.HttpUtility.UrlDecode(b[1]); + if ((0 != String.Compare("password", n)) && (0 != String.Compare("psswrd", n))) + { + // Poor mans Bobby Tables protection. + v = v.Replace("'", "_"); + v = v.Replace("\"", "_"); + v = v.Replace(";", "_"); + v = v.Replace("(", "_"); + v = v.Replace(")", "_"); + } fields[n] = v; body = body + "

" + n + " = " + v + "

\n"; } if ("account.html" == file) { + string doit = fields["doit"].ToString(); replyHeaders["Cache-Control"] = "no-cache"; - if ("logout" == fields["doit"].ToString()) + if ("logout" == doit) reply["str_response_string"] = loginPage(null, "Logged out."); - else if ("create" == fields["doit"].ToString()) + else if (("create" == doit) || ("confirm" == doit)) { + Regex rgxName = new Regex("^[a-zA-Z0-9]+$"); + Regex rgxEmail = new Regex("^.+@.+\\..+$"); + string[] names = fields["name"].ToString().Split(' '); if ("" == fields["email"].ToString()) reply["str_response_string"] = loginPage(fields, "Please supply an email address when creating an account."); + else if (!rgxEmail.IsMatch(fields["email"].ToString())) + reply["str_response_string"] = loginPage(fields, "Please supply a valid email address when creating an account."); + else if (!Uri.IsWellFormedUriString("mailto:" + fields["email"].ToString(), System.UriKind.Absolute)) + reply["str_response_string"] = loginPage(fields, "Please supply a valid email address when creating an account."); +// TODO - the other test to do here is actually lookup the domain name, looking for any sort of record. + else if (2 != names.Length) + reply["str_response_string"] = loginPage(fields, "Please supply a two word name when creating an account."); + // SL docs say 31 characters each for first and last name. UserAccounts table is varchar(64) each. userinfo has varchar(50) for the combined name. + // The userinfo table seems to be obsolete. + // Singularity at least limits the total name to 64. + // I can't find any limitations on characters allowed, but I only ever see letters and digits used. Case is stored, but not significant. + // OpenSims "create user" console command doesn't sanitize it at all, even crashing on some names. + else if (31 < names[0].Length) + reply["str_response_string"] = loginPage(fields, "First and last names are limited to 31 letters each."); + else if (31 < names[1].Length) + reply["str_response_string"] = loginPage(fields, "First and last names are limited to 31 letters each."); + else if (!rgxName.IsMatch(names[0])) + reply["str_response_string"] = loginPage(fields, "First and last names are limited to letters and digits."); + else if (!rgxName.IsMatch(names[1])) + reply["str_response_string"] = loginPage(fields, "First and last names are limited to letters and digits."); +// TODO - check and disallow god names, those are done in the console. else { - reply["str_response_string"] = loggedOnPage(body, fields); + if (("create" == doit)) + reply["str_response_string"] = accountCreationPage(body, fields); + else + { + if (0 != String.Compare(fields["psswrd"].ToString(), fields["password"].ToString())) + reply["str_response_string"] = loginPage(fields, "Passwords are not the same."); + else + reply["str_response_string"] = loggedOnPage(body, fields); + } } } - else if ("list" == fields["doit"].ToString()) + else if ("cancel" == doit) + { + reply["str_response_string"] = loginPage(null, "Cancelled."); + } + else if ("list" == doit) { List< Hashtable > rows = m_database.Select("UserAccounts", "CONCAT(FirstName,' ',LastName) as Name,UserTitle as Title,UserLevel as Level,UserFlags as Flags,PrincipalID as UUID", @@ -268,21 +316,19 @@ namespace OpenSim.Server.Handlers.Web private string loginPage(Hashtable fields, string message) { - string f = ""; - string l = ""; + string n = ""; string e = ""; if (null != fields) { - f = fields["firstName"].ToString(); - l = fields["lastName"].ToString(); + n = fields["name"].ToString(); e = fields["email"].ToString(); } return header(ssi["grid"] + " account") + form("account.html", "", - text("text", "first name", "firstName", f, 16, true) - + text("text", "last name", "lastName", l, 16, true) - + text("email", "email", "email", e, 0, false) - + text("password", "password", "password", "", 14,true) + text("text", "name", "name", n, 63, true) + + text("email", "email", "email", e, 254, false) + + text("password", "password", "password", "", 0, true) + + "Warning, the limit on password length is set by your viewer, some can't handle longer than 16 characters." + button("create") + button("login") ) @@ -290,17 +336,35 @@ namespace OpenSim.Server.Handlers.Web + footer(); } + private string accountCreationPage(string body, Hashtable fields) + { + return header(ssi["grid"] + " account") + + "

Creating " + ssi["grid"] + " account for " + fields["name"].ToString() + "

" + + form("account.html", fields["token"].ToString(), + hidden("name", fields["name"].ToString()) + + hidden("psswrd", fields["password"].ToString()) + + text("email", "An email will be sent to", "email", fields["email"].ToString(), 254, true) + + " to validate it, please double check this." + + text("password", "Re-enter your password", "password", "", 0, true) + + "Warning, the limit on password length is set by your viewer, some can't handle longer than 16 characters." + + button("confirm") + + button("cancel") + ) + + body + + footer(); + } + private string loggedOnPage(string body, Hashtable fields) { return header(ssi["grid"] + " account") - + "

" + ssi["grid"] + " account for " + fields["firstName"].ToString() + " " + fields["lastName"].ToString() + "

" + + "

" + ssi["grid"] + " account for " + fields["name"].ToString() + "

" + form("account.html", fields["token"].ToString(), - hidden("firstName", fields["firstName"].ToString()) - + hidden("lastName", fields["lastName"].ToString()) + hidden("name", fields["name"].ToString()) // + hidden("UUID", fields["UUID"].ToString()) - + text("email", "email", "email", fields["email"].ToString(), 0, false) - + text("password", "password", "password", "", 14, false) -// + text("title", "text", "title", fields["title"].ToString(), 0, false) + + text("email", "email", "email", fields["email"].ToString(), 254, true) + + text("password", "password", "password", "", 0, false) + + "Warning, the limit on password length is set by your viewer, some can't handle longer than 16 characters." +// + text("title", "text", "title", fields["title"].ToString(), 64, false) + select("type", "type", option("", false) + option("approved", true) -- cgit v1.1 From 7ed68c3e38b7e1b46aa110d4eb1b1eac686f291e Mon Sep 17 00:00:00 2001 From: onefang Date: Sat, 17 Aug 2019 08:38:45 +1000 Subject: Implement HEAD in our simple web server. --- OpenSim/Server/Handlers/Web/WebServerConnector.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerConnector.cs b/OpenSim/Server/Handlers/Web/WebServerConnector.cs index 7879e4e..c18e09e 100644 --- a/OpenSim/Server/Handlers/Web/WebServerConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerConnector.cs @@ -139,8 +139,7 @@ namespace OpenSim.Server.Handlers.Web m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} query {2} value {3}", method, reqpath, q, (string) request[q]); reply["int_response_code"] = 200; -// TODO - need to support HEAD method, seems to be what triggers the endles GETs. - if ("GET" == method) + if (("GET" == method) || ("HEAD" == method)) { if (File.Exists(path)) { @@ -160,6 +159,11 @@ namespace OpenSim.Server.Handlers.Web reply["int_response_code"] = 304; m_log.InfoFormat("[WEB SERVICE]: If-Modified-Since is earliar or equal to Last-Modified, from {0}", path); reply["headers"] = replyHeaders; + if ("HEAD" == method) + { + reply["bin_response_data"] = null; + reply["str_response_string"] = null; + } return reply; } } @@ -311,6 +315,11 @@ namespace OpenSim.Server.Handlers.Web m_log.Info("[WEB SERVICE]: "); reply["headers"] = replyHeaders; + if ("HEAD" == method) + { + reply["bin_response_data"] = null; + reply["str_response_string"] = null; + } return reply; } -- cgit v1.1 From 8f280962f019d46e0367b29246283a1e34ceb955 Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 18 Aug 2019 14:12:21 +1000 Subject: Various additions to the web account manager. Track if we are accessed via HTTP or HTTPS, and the server name. Track cookies. HEAD method. Various security clean ups. Force HTTPS for account.html. Poor mans Bobby Tables protection. Security token. Validate inputs. Looking up the DNS records for email domain name. Don't allow creation of accounts with god names, leave that for the console. Check if created user name exists already. Double check the passwords and emails. Error messages on dynamic pages. Various clean ups. TODO++ --- OpenSim/Server/Handlers/Web/WebServerConnector.cs | 514 +++++++++++++++++----- 1 file changed, 406 insertions(+), 108 deletions(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerConnector.cs b/OpenSim/Server/Handlers/Web/WebServerConnector.cs index c18e09e..67cb8da 100644 --- a/OpenSim/Server/Handlers/Web/WebServerConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerConnector.cs @@ -24,16 +24,34 @@ namespace OpenSim.Server.Handlers.Web // This is all slow and clunky, it's not a real web server, just something to use if you don't want a real one. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private IConfigSource m_Config; + protected MySQLRaw m_database = null; + private Hashtable mime = new Hashtable(); private Hashtable ssi = new Hashtable(); + private IPAddress m_IP; + private IHttpServer m_server; + private IHttpServer m_SSLserver = null; + private string m_domain = ""; + private uint m_http_port; + private uint m_https_port = 0; + + private Dictionary m_auth = new Dictionary(); + + private static Dictionary m_firstNames = new Dictionary(); + private static Dictionary m_lastNames = new Dictionary(); + private static Dictionary m_fullNames = new Dictionary(); + public WebServerConnector(IConfigSource config, IHttpServer server, string configName) : base(config, server, configName) { string dllName = String.Empty; string connString = String.Empty; m_Config = config; + m_server = server; + m_IP = MainServer.Instance.ListenIPAddress; + m_http_port = server.Port; // Try reading the [DatabaseService] section, if it exists IConfig dbConfig = m_Config.Configs["DatabaseService"]; @@ -79,52 +97,104 @@ namespace OpenSim.Server.Handlers.Web // mime.Add(".markdown","text/markdown"); mime.Add(".txt", "text/plain"); + // Grab some info. IConfig cfg = m_Config.Configs["GridInfoService"]; string HomeURI = Util.GetConfigVarFromSections(m_Config, "HomeURI", new string[] { "Startup", "Hypergrid" }, String.Empty); ssi.Add("grid", cfg.GetString("gridname", "my grid")); ssi.Add("uri", cfg.GetString("login", HomeURI)); ssi.Add("version", VersionInfo.Version); + cfg = m_Config.Configs["Const"]; + m_domain = cfg.GetString("HostName", "localhost"); + // Copied from OpenSim/Region/OptionalModules/ViewerSupport/GodNamesModule.cs + cfg = m_Config.Configs["GodNames"]; + if (null != cfg) + { + m_log.Info("[WEB SERVICE]: Loading god names."); + string conf_str = cfg.GetString("FullNames", String.Empty); + if (String.Empty != conf_str) + { + foreach (string strl in conf_str.Split(',')) + { + string strlan = strl.Trim(" \t".ToCharArray()); + m_log.InfoFormat("[WEB SERVICE]: Adding {0} as a god name", strlan); + m_fullNames.Add(strlan, strlan); + } + } + + conf_str = cfg.GetString("FirstNames", String.Empty); + if (String.Empty != conf_str) + { + foreach (string strl in conf_str.Split(',')) + { + string strlan = strl.Trim(" \t".ToCharArray()); + m_log.InfoFormat("[WEB SERVICE]: Adding {0} as a god first name", strlan); + m_firstNames.Add(strlan, strlan); + } + } + + conf_str = cfg.GetString("Surnames", String.Empty); + if (String.Empty != conf_str) + { + foreach (string strl in conf_str.Split(',')) + { + string strlan = strl.Trim(" \t".ToCharArray()); + m_log.InfoFormat("[WEB SERVICE]: Adding {0} as a god last name", strlan); + m_lastNames.Add(strlan, strlan); + } + } + } + else + m_log.Info("[WEB SERVICE]: No god names loaded."); + + // Add the HTTP and HTTPS handlers. server.AddHTTPHandler("/web/", WebRequestHandler); IConfig networkConfig = m_Config.Configs["Network"]; if (null != networkConfig) { - uint https_port = (uint) networkConfig.GetInt("https_port", 0); - if (0 != https_port) + m_https_port = (uint) networkConfig.GetInt("https_port", 0); + if (0 != m_https_port) { - server = MainServer.GetHttpServer(https_port, null); - if (null != server) - server.AddHTTPHandler("/web/", WebRequestHandler); + m_SSLserver = MainServer.GetHttpServer(m_https_port, null); + if (null != m_SSLserver) + m_SSLserver.AddHTTPHandler("/web/", WebRequestHandlerSSL); } - } - } + } + } + // AAARGGGH, in the request we don't get the HTTP/S, domain name, nor port number we were called from. So we have to fake it, sorta. + private Hashtable WebRequestHandlerSSL(Hashtable request) + { + return Handler(request, true); + } private Hashtable WebRequestHandler(Hashtable request) { - long locIn = m_database.Count("Presence", "RegionID != '00000000-0000-0000-0000-000000000000'"); // Locals online but not HGing, and HGers in world. - long HGin = m_database.Count("Presence", "UserID NOT IN (SELECT PrincipalID FROM UserAccounts)"); // HGers in world. - long locOut = m_database.Count("hg_traveling_data", "GridExternalName != '" + ssi["uri"] + "'"); // Locals that are HGing. + return Handler(request, false); + } + private Hashtable Handler(Hashtable request, bool usedSSL) + { Hashtable reply = new Hashtable(); Hashtable replyHeaders = new Hashtable(); - ssi["members"] = m_database.Count("UserAccounts").ToString(); - ssi["sims"] = m_database.Count("regions").ToString(); - ssi["inworld"] = (locIn - HGin).ToString(); - ssi["outworld"] = locOut.ToString(); - ssi["hgers"] = HGin.ToString(); - ssi["month"] = m_database.Count("GridUser", "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200))").ToString(); + Hashtable cookies = new Hashtable(); + Hashtable fields = new Hashtable(); + List errors = new List(); string reqpath = (string) request["uri"]; - string[] query = (string[]) request["querystringkeys"]; - Hashtable headers = (Hashtable) request["headers"]; string method = (string) request["http-method"]; string type = (string) request["content-type"]; string body = (string) request["body"]; + string[] query = (string[]) request["querystringkeys"]; + Hashtable headers = (Hashtable) request["headers"]; + Hashtable vars = (Hashtable) request["requestvars"]; string file = reqpath.Remove(0, 5); string path = Path.Combine(Util.webDir(), file); + m_log.InfoFormat("[WEB SERVICE]: {0} {1} {2} : {3} {4}, server IP {5} content type {6}, body {7}.", + headers["remote_addr"].ToString(), method, m_domain, (usedSSL ? m_https_port : m_http_port), reqpath, m_IP, type, body); + if (! Path.GetFullPath(path).StartsWith(Path.GetFullPath(Util.webDir()))) { - m_log.ErrorFormat("[WEB SERVICE]: INVALID PATH {0} != {1}", Path.GetFullPath(path), Path.GetFullPath(Util.webDir())); + m_log.ErrorFormat("[WEB SERVICE]: INVALID PATH {0} != {1}", Path.GetFullPath(path), Path.GetFullPath(Util.webDir())); reply["int_response_code"] = 404; reply["content_type"] = "text/html"; reply["str_response_string"] = "404 Unknown page" + @@ -132,13 +202,59 @@ namespace OpenSim.Server.Handlers.Web return reply; } - m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} contont type {2} body {3}.", method, reqpath, type, body); + long locIn = m_database.Count("Presence", "RegionID != '00000000-0000-0000-0000-000000000000'"); // Locals online but not HGing, and HGers in world. + long HGin = m_database.Count("Presence", "UserID NOT IN (SELECT PrincipalID FROM UserAccounts)"); // HGers in world. + ssi["hgers"] = HGin.ToString(); + ssi["inworld"] = (locIn - HGin).ToString(); + ssi["outworld"] = m_database.Count("hg_traveling_data", "GridExternalName != '" + ssi["uri"] + "'").ToString(); // Locals that are HGing. + ssi["members"] = m_database.Count("UserAccounts").ToString(); + ssi["month"] = m_database.Count("GridUser", "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200))").ToString(); + ssi["sims"] = m_database.Count("regions").ToString(); + foreach (DictionaryEntry h in headers) - m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} header {2} = {3}", method, reqpath, (string) h.Key, (string) h.Value); + { + if ("cookie" == h.Key.ToString()) + { + string[] cks = h.Value.ToString().Split(';'); + foreach (String c in cks) + { + string[] ck = c.Split('='); + cookies[ck[0].Trim(' ')] = ck[1].Trim(' '); + } + } + } + + if ("POST" == method) + { + string[] bdy = body.Split('&'); + body = ""; + foreach (String bd in bdy) + { + string[] b = bd.Split('='); + if (b.Length == 0) + continue; + string n = System.Web.HttpUtility.UrlDecode(b[0]); + string v = ""; + if (b.Length > 1) + v = System.Web.HttpUtility.UrlDecode(b[1]); + fields[n] = bobbyTables(n, v); + body = body + "

" + n + " = " + v + "

\n"; + } + } + foreach (String q in query) - m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} query {2} value {3}", method, reqpath, q, (string) request[q]); + { + m_log.InfoFormat("[WEB SERVICE]: {0} {1} query {2} = {3}", method, reqpath, q, (string) request[q]); + fields[q] = bobbyTables(q, (string) request[q]); + } + foreach (DictionaryEntry h in headers) + m_log.DebugFormat("[WEB SERVICE]: {0} {1} header {2} = {3}", method, reqpath, (string) h.Key, (string) h.Value); + // I dunno what these vars are or where they come from, never actually seen them. + foreach (DictionaryEntry h in vars) + m_log.InfoFormat("[WEB SERVICE]: {0} {1} var {2} = {3}", method, reqpath, (string) h.Key, (string) h.Value); reply["int_response_code"] = 200; + if (("GET" == method) || ("HEAD" == method)) { if (File.Exists(path)) @@ -157,19 +273,19 @@ namespace OpenSim.Server.Handlers.Web if (0 >= DateTime.Compare(ifdt, dt)) { reply["int_response_code"] = 304; - m_log.InfoFormat("[WEB SERVICE]: If-Modified-Since is earliar or equal to Last-Modified, from {0}", path); + m_log.InfoFormat("[WEB SERVICE]: If-Modified-Since is earliar or equal to Last-Modified, from {0}", reqpath); reply["headers"] = replyHeaders; if ("HEAD" == method) { - reply["bin_response_data"] = null; - reply["str_response_string"] = null; + reply.Remove("bin_response_data"); + reply.Remove("str_response_string"); } return reply; } } catch (Exception) { - m_log.ErrorFormat("[WEB SERVICE]: Invalid If-Modified-Since header, ignoring it, from {0}", path); + m_log.WarnFormat("[WEB SERVICE]: Invalid If-Modified-Since header, ignoring it, from {0} - {1}", reqpath, ifdtr); } } replyHeaders["Last-Modified"] = dt.ToString("R"); @@ -192,10 +308,21 @@ namespace OpenSim.Server.Handlers.Web else { if ("account.html" == file) - reply["str_response_string"] = loginPage(null, ""); + { + if (usedSSL) + reply["str_response_string"] = loginPage(null, ""); + else // Force HTTPS by redirecting. + { + reply["int_response_code"] = 200; + reply["content_type"] = "text/html"; + reply["str_response_string"] = "404 Unknown page" + + "" + + ""; + } + } else { - m_log.ErrorFormat("[WEB SERVICE]: Unable to read {0}.", path); + m_log.ErrorFormat("[WEB SERVICE]: Unable to read {0}.", reqpath); reply["int_response_code"] = 404; reply["content_type"] = "text/html"; reply["str_response_string"] = "404 Unknown page" + @@ -205,124 +332,295 @@ namespace OpenSim.Server.Handlers.Web } else if ("POST" == method) { - Hashtable fields = new Hashtable(); - string[] bdy = body.Split('&'); - body = ""; - foreach (String bd in bdy) - { - string[] b = bd.Split('='); - if (b.Length == 0) - continue; - String n = System.Web.HttpUtility.UrlDecode(b[0]); - String v = ""; - if (b.Length > 1) - v = System.Web.HttpUtility.UrlDecode(b[1]); - if ((0 != String.Compare("password", n)) && (0 != String.Compare("psswrd", n))) - { - // Poor mans Bobby Tables protection. - v = v.Replace("'", "_"); - v = v.Replace("\"", "_"); - v = v.Replace(";", "_"); - v = v.Replace("(", "_"); - v = v.Replace(")", "_"); - } - fields[n] = v; - body = body + "

" + n + " = " + v + "

\n"; - } if ("account.html" == file) { string doit = fields["doit"].ToString(); + string toke_n_munchie = ""; replyHeaders["Cache-Control"] = "no-cache"; - if ("logout" == doit) - reply["str_response_string"] = loginPage(null, "Logged out."); - else if (("create" == doit) || ("confirm" == doit)) + +/* TODO - + Switch to using prepared SQL statements. + + Actually authenticate them. + Deal with dictionary attacks by slowing down access on password failures etc. + + Regenerate token on authentication. + Store users UUID. + + Invalidate token on logout and password reset. + Logout when invalidating tokens. + + Deal with validation and password reset emails, likely with the same code. +*/ + + if ((null == cookies["toke_n_munchie"]) || (null == fields["toke_n_munchie"]) + || ("" == cookies["toke_n_munchie"].ToString()) || ("" == fields["toke_n_munchie"].ToString())) + toke_n_munchie = newSession(doit, headers, ref fields, ref replyHeaders); + else if (cookies["toke_n_munchie"].ToString() != fields["toke_n_munchie"].ToString()) + errors.Add("Invalid session."); + else { - Regex rgxName = new Regex("^[a-zA-Z0-9]+$"); - Regex rgxEmail = new Regex("^.+@.+\\..+$"); - string[] names = fields["name"].ToString().Split(' '); - if ("" == fields["email"].ToString()) - reply["str_response_string"] = loginPage(fields, "Please supply an email address when creating an account."); - else if (!rgxEmail.IsMatch(fields["email"].ToString())) - reply["str_response_string"] = loginPage(fields, "Please supply a valid email address when creating an account."); - else if (!Uri.IsWellFormedUriString("mailto:" + fields["email"].ToString(), System.UriKind.Absolute)) - reply["str_response_string"] = loginPage(fields, "Please supply a valid email address when creating an account."); -// TODO - the other test to do here is actually lookup the domain name, looking for any sort of record. - else if (2 != names.Length) - reply["str_response_string"] = loginPage(fields, "Please supply a two word name when creating an account."); - // SL docs say 31 characters each for first and last name. UserAccounts table is varchar(64) each. userinfo has varchar(50) for the combined name. - // The userinfo table seems to be obsolete. - // Singularity at least limits the total name to 64. - // I can't find any limitations on characters allowed, but I only ever see letters and digits used. Case is stored, but not significant. - // OpenSims "create user" console command doesn't sanitize it at all, even crashing on some names. - else if (31 < names[0].Length) - reply["str_response_string"] = loginPage(fields, "First and last names are limited to 31 letters each."); - else if (31 < names[1].Length) - reply["str_response_string"] = loginPage(fields, "First and last names are limited to 31 letters each."); - else if (!rgxName.IsMatch(names[0])) - reply["str_response_string"] = loginPage(fields, "First and last names are limited to letters and digits."); - else if (!rgxName.IsMatch(names[1])) - reply["str_response_string"] = loginPage(fields, "First and last names are limited to letters and digits."); -// TODO - check and disallow god names, those are done in the console. + toke_n_munchie = cookies["toke_n_munchie"].ToString(); + Hashtable auth = m_auth[toke_n_munchie]; + if (null == auth) + { + errors.Add("Null session."); + m_log.InfoFormat("[WEB SERVICE]: Null session {0} - {1}.", toke_n_munchie, doit); + } else { - if (("create" == doit)) - reply["str_response_string"] = accountCreationPage(body, fields); +// TODO - maybe check if session has expired, but how long should they last? + if (auth["IP"].ToString() != headers["remote_addr"].ToString()) + errors.Add("Wrong IP for session."); else { - if (0 != String.Compare(fields["psswrd"].ToString(), fields["password"].ToString())) - reply["str_response_string"] = loginPage(fields, "Passwords are not the same."); - else - reply["str_response_string"] = loggedOnPage(body, fields); + auth["time"] = DateTime.Now; + m_auth[toke_n_munchie] = auth; + m_log.InfoFormat("[WEB SERVICE]: New timestamp for session {0} - {1}.", toke_n_munchie, doit); } } } + + if (0 != errors.Count) + deleteSession(toke_n_munchie, doit, headers, ref fields, ref replyHeaders); + + if (("https://" + m_domain + ":" + m_https_port.ToString() + "/web/account.html") != headers["referer"].ToString()) + errors.Add("Invalid referer."); + + validateName(false, fields, ref errors); + + if ("logout" == doit) + { + deleteSession(toke_n_munchie, doit, headers, ref fields, ref replyHeaders); + errors.Add("Logged out."); + } + else if (("create" == doit) || ("confirm" == doit)) + { + validateName(true, fields, ref errors); + validateEmail(fields, ref errors); + if ("confirm" == doit) + validatePassword(fields, ref errors); + if (0 == errors.Count) + { + // Check the account name doesn't exist yet. + // Which might be tricky, apparently names are not case sensitive on login, but stored with case in the database. + // I confirmed that, can log in no matter what case you use. + // UserAccounts FirstName and LastName fields are both varchar(64) utf8_general_ci. + // The MySQL docs say that the "_ci" bit means comparisons will be case insensitive. So that should work fine. + // No need for prepared SQL here, the names have already been checked. + string[] names = fields["name"].ToString().Split(' '); + long c = m_database.Count("UserAccounts", "FirstName = '" + names[0] + "' AND LastName = '" + names[1] + "'"); + if (0 != c) + errors.Add("Pick a different name."); + else if (("create" == doit)) + reply["str_response_string"] = accountCreationPage(fields, body); + else + reply["str_response_string"] = loggedOnPage(fields, body); + } + else + deleteSession(toke_n_munchie.ToString(), doit, headers, ref fields, ref replyHeaders); + } else if ("cancel" == doit) { - reply["str_response_string"] = loginPage(null, "Cancelled."); + deleteSession(toke_n_munchie.ToString(), doit, headers, ref fields, ref replyHeaders); + errors.Add("Cancelled."); } else if ("list" == doit) { +// TODO - should check if the user is a god before allowing this. List< Hashtable > rows = m_database.Select("UserAccounts", - "CONCAT(FirstName,' ',LastName) as Name,UserTitle as Title,UserLevel as Level,UserFlags as Flags,PrincipalID as UUID", + "CONCAT(FirstName,' ',LastName) as Name,UserTitle as Title,UserLevel as Level,UserFlags as Flags,PrincipalID as UUID", "", "Name"); reply["str_response_string"] = "member accounts" + table(rows, new string[5] {"Name", "Title", "Level", "Flags", "UUID"}, "member accounts", - "account.html?doit=edit&token=" + fields["token"].ToString(), "UUID") + "

" + button("my account") + "

"; + "account.html?doit=edit&token=" + fields["toke_n_munchie"].ToString(), "UUID") + "

" + button("my account") + "

"; } - else + else if ("login" == doit) { - reply["str_response_string"] = loggedOnPage(body, fields); + if (0 != errors.Count) + deleteSession(toke_n_munchie.ToString(), doit, headers, ref fields, ref replyHeaders); + else + reply["str_response_string"] = loggedOnPage(fields, body); } + else + reply["str_response_string"] = loggedOnPage(fields, body); } - else + else // Not one of our dynamic pages. { - m_log.ErrorFormat("[WEB SERVICE]: No such POST target {0}.", path); + m_log.ErrorFormat("[WEB SERVICE]: No such POST target {0}.", path); reply["int_response_code"] = 404; reply["content_type"] = "text/html"; reply["str_response_string"] = "404 Unknown page" + "404 error, can't find the " + reqpath + " page.

 

"; } } - else + else // Not one of our handled methods. { - m_log.ErrorFormat("[WEB SERVICE]: UNKNOWN method {0} path {1}.", method, reqpath); + m_log.ErrorFormat("[WEB SERVICE]: UNKNOWN method {0} path {1}.", method, reqpath); reply["int_response_code"] = 404; reply["content_type"] = "text/html"; reply["str_response_string"] = "Unknown method" + "HUH! For " + reqpath + " page.

 

"; } - m_log.Info("[WEB SERVICE]: "); reply["headers"] = replyHeaders; + if (0 != errors.Count) + { + string b = ""; + foreach (string e in errors) + b = b + "

" + e + "

"; + reply["str_response_string"] = loginPage(fields, b); + } + if ("HEAD" == method) { - reply["bin_response_data"] = null; - reply["str_response_string"] = null; + reply.Remove("bin_response_data"); + reply.Remove("str_response_string"); } return reply; } + // Poor mans Bobby Tables protection. + private string bobbyTables(string n, string v) + { + if ((0 != String.Compare("password", n)) && (0 != String.Compare("psswrd", n))) + { + v = v.Replace("'", "_"); + v = v.Replace("\"", "_"); + v = v.Replace(";", "_"); + v = v.Replace("(", "_"); + v = v.Replace(")", "_"); + } + return v; + } + + private string newSession(string doit, Hashtable headers, ref Hashtable fields, ref Hashtable replyHeaders) + { + // This is a little over the top, but apparently best practices. + string toke_n_munchie = Guid.NewGuid().ToString(); + string salt = Util.Md5Hash(UUID.Random().ToString()); + string hash = Util.Md5Hash(Util.Md5Hash(toke_n_munchie) + ":" + salt); + Hashtable auth = new Hashtable(); + auth["toke_n_munchie"] = toke_n_munchie; + auth["salt"] = salt; + auth["hash"] = hash; + auth["IP"] = headers["remote_addr"].ToString(); + auth["time"] = DateTime.Now; + auth["UUID"] = UUID.Zero; + m_auth[hash] = auth; + // For some odd reason, __Host- only works if "Path=/", and if no "Domain=", per the spec. + //replyHeaders["Set-Cookie"] = "__Host-toke_n_munchie=" + toke_n_munchie + "; HttpOnly; Path=/web/; SameSite=Strict; Secure;"; + replyHeaders["Set-Cookie"] = "toke_n_munchie=" + hash + "; HttpOnly; Path=/web/; SameSite=Strict; Secure;"; + fields["toke_n_munchie"] = hash; + toke_n_munchie = hash; + m_log.InfoFormat("[WEB SERVICE]: {0} New session {1} - {2}.", headers["remote_addr"].ToString(), toke_n_munchie, doit); + return toke_n_munchie; + } + + private void deleteSession(string session, string doit, Hashtable headers, ref Hashtable fields, ref Hashtable replyHeaders) + { + m_log.InfoFormat("[WEB SERVICE]: {0} Deleted session {1} - {2}.", headers["remote_addr"].ToString(), session, doit); + m_auth.Remove(session); + fields.Remove("toke_n_munchie"); + replyHeaders["Set-Cookie"] = "toke_n_munchie=\"\"; HttpOnly; Path=/web/; SameSite=Strict; Secure; expires=Thu, 01 Jan 1970 00:00:00 GMT;"; + } + + private void validateEmail(Hashtable fields, ref List errors) + { + Regex rgxEmail = new Regex("^.+@.+\\..+$"); + if ((null == fields["email"]) || ("" == fields["email"].ToString())) + errors.Add("Please supply an email address."); + else if (!rgxEmail.IsMatch(fields["email"].ToString())) + errors.Add("Please supply a proper email address."); + else if (!Uri.IsWellFormedUriString("mailto:" + fields["email"].ToString(), System.UriKind.Absolute)) + errors.Add("Please supply a valid email address."); + + // Actually lookup the domain name, looking for any sort of record. + string e = fields["email"].ToString().Split('@')[1]; + IPHostEntry ip = null; + try + { + ip = Dns.GetHostEntry(e); + } + catch(Exception) + { + } + if (null == ip) + errors.Add("Can't find that email server, try a different email address."); + } + + private void validateName(bool godCheck, Hashtable fields, ref List errors) + { + Regex rgxName = new Regex("^[a-zA-Z0-9]+$"); + string[] names; + if ((null == fields["name"]) || ("" == fields["name"].ToString())) + errors.Add("Please supply an account name."); + else + { + names = fields["name"].ToString().Split(' '); + if (2 != names.Length) + errors.Add("Names have to be two words."); + // SL docs say 31 characters each for first and last name. UserAccounts table is varchar(64) each. userinfo has varchar(50) for the combined name. + // The userinfo table seems to be obsolete. + // Singularity at least limits the total name to 64. + // I can't find any limitations on characters allowed, but I only ever see letters and digits used. Case is stored, but not significant. + // OpenSims "create user" console command doesn't sanitize it at all, even crashing on some names. + else + { + if ((31 < names[0].Length) || (31 < names[1].Length)) + errors.Add("First and last names are limited to 31 letters each."); + if ((!rgxName.IsMatch(names[0])) || (!rgxName.IsMatch(names[1]))) + errors.Add("First and last names are limited to letters and digits."); + if (godCheck) + { + // Check and disallow god names, those are done in the console. + bool f = false; + try + { + if (null != m_fullNames[names[0] + " " + names[1]]) + { + f = true; + errors.Add("Pick another name."); + } + } + catch (Exception) + { + } + if (!f) + { + try + { + if (null != m_firstNames[names[0]]) + errors.Add("Pick another first name."); + } + catch (Exception) + { + } + try + { + if (null != m_firstNames[names[1]]) + errors.Add("Pick another last name."); + } + catch (Exception) + { + } + } + } + } + } + } + + private void validatePassword(Hashtable fields, ref List errors) + { + if ((null == fields["password"]) || ("" == fields["password"].ToString())) + errors.Add("Please supply a password."); + else if ((null == fields["psswrd"]) || ("" == fields["psswrd"].ToString())) + errors.Add("Please supply a password."); + else if (0 != String.Compare(fields["psswrd"].ToString(), fields["password"].ToString())) + errors.Add("Passwords are not the same."); + } + private string loginPage(Hashtable fields, string message) { string n = ""; @@ -345,29 +643,29 @@ namespace OpenSim.Server.Handlers.Web + footer(); } - private string accountCreationPage(string body, Hashtable fields) + private string accountCreationPage(Hashtable fields, string message) { return header(ssi["grid"] + " account") + "

Creating " + ssi["grid"] + " account for " + fields["name"].ToString() + "

" - + form("account.html", fields["token"].ToString(), + + form("account.html", fields["toke_n_munchie"].ToString(), hidden("name", fields["name"].ToString()) + hidden("psswrd", fields["password"].ToString()) - + text("email", "An email will be sent to", "email", fields["email"].ToString(), 254, true) + + text("email", "An email will be sent to", "email", fields["email"].ToString(), 254, false) + " to validate it, please double check this." - + text("password", "Re-enter your password", "password", "", 0, true) + + text("password", "Re-enter your password", "password", "", 0, false) + "Warning, the limit on password length is set by your viewer, some can't handle longer than 16 characters." + button("confirm") + button("cancel") ) - + body + + message + footer(); } - private string loggedOnPage(string body, Hashtable fields) + private string loggedOnPage(Hashtable fields, string message) { return header(ssi["grid"] + " account") + "

" + ssi["grid"] + " account for " + fields["name"].ToString() + "

" - + form("account.html", fields["token"].ToString(), + + form("account.html", fields["toke_n_munchie"].ToString(), hidden("name", fields["name"].ToString()) // + hidden("UUID", fields["UUID"].ToString()) + text("email", "email", "email", fields["email"].ToString(), 254, true) @@ -386,7 +684,7 @@ namespace OpenSim.Server.Handlers.Web // + button("read") + button("update") ) - + body + + message + footer(); } @@ -444,7 +742,7 @@ namespace OpenSim.Server.Handlers.Web private string form(string action, string token, string form) { - return "
\n" + hidden("token", token) + form + "
\n"; + return "
\n" + hidden("toke_n_munchie", token) + form + "
\n"; } private string hidden(string name, string val) -- cgit v1.1 From 24d6b61d9c99e3119b0a765ffe6ef5c10e05d563 Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 18 Aug 2019 15:45:03 +1000 Subject: TODO++ --- OpenSim/Server/Handlers/Web/WebServerConnector.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerConnector.cs b/OpenSim/Server/Handlers/Web/WebServerConnector.cs index 67cb8da..cbfee3a 100644 --- a/OpenSim/Server/Handlers/Web/WebServerConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerConnector.cs @@ -352,6 +352,9 @@ namespace OpenSim.Server.Handlers.Web Logout when invalidating tokens. Deal with validation and password reset emails, likely with the same code. + + Deal with editing yourself. + Deal with editing others, but only as god. */ if ((null == cookies["toke_n_munchie"]) || (null == fields["toke_n_munchie"]) -- cgit v1.1 From 82d9bf5258a9627eac4c012f3d6f3e40036d0dee Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 18 Aug 2019 15:45:43 +1000 Subject: Optimise account name validation. --- OpenSim/Server/Handlers/Web/WebServerConnector.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerConnector.cs b/OpenSim/Server/Handlers/Web/WebServerConnector.cs index cbfee3a..c4a0531 100644 --- a/OpenSim/Server/Handlers/Web/WebServerConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerConnector.cs @@ -391,7 +391,8 @@ namespace OpenSim.Server.Handlers.Web if (("https://" + m_domain + ":" + m_https_port.ToString() + "/web/account.html") != headers["referer"].ToString()) errors.Add("Invalid referer."); - validateName(false, fields, ref errors); + // Include a check for god names if we are creating a new account. + string[] names = validateName(("create" == doit) || ("confirm" == doit), fields, ref errors); if ("logout" == doit) { @@ -400,7 +401,6 @@ namespace OpenSim.Server.Handlers.Web } else if (("create" == doit) || ("confirm" == doit)) { - validateName(true, fields, ref errors); validateEmail(fields, ref errors); if ("confirm" == doit) validatePassword(fields, ref errors); @@ -412,9 +412,7 @@ namespace OpenSim.Server.Handlers.Web // UserAccounts FirstName and LastName fields are both varchar(64) utf8_general_ci. // The MySQL docs say that the "_ci" bit means comparisons will be case insensitive. So that should work fine. // No need for prepared SQL here, the names have already been checked. - string[] names = fields["name"].ToString().Split(' '); - long c = m_database.Count("UserAccounts", "FirstName = '" + names[0] + "' AND LastName = '" + names[1] + "'"); - if (0 != c) + if (0 != m_database.Count("UserAccounts", "FirstName = '" + names[0] + "' AND LastName = '" + names[1] + "'")) errors.Add("Pick a different name."); else if (("create" == doit)) reply["str_response_string"] = accountCreationPage(fields, body); @@ -553,10 +551,10 @@ namespace OpenSim.Server.Handlers.Web errors.Add("Can't find that email server, try a different email address."); } - private void validateName(bool godCheck, Hashtable fields, ref List errors) + private string[] validateName(bool godCheck, Hashtable fields, ref List errors) { Regex rgxName = new Regex("^[a-zA-Z0-9]+$"); - string[] names; + string[] names = {"", ""}; if ((null == fields["name"]) || ("" == fields["name"].ToString())) errors.Add("Please supply an account name."); else @@ -612,6 +610,7 @@ namespace OpenSim.Server.Handlers.Web } } } + return names; } private void validatePassword(Hashtable fields, ref List errors) -- cgit v1.1 From 14616c8438fef749c5e7cb6bdcefe9b7c9554597 Mon Sep 17 00:00:00 2001 From: onefang Date: Wed, 21 Aug 2019 21:50:16 +1000 Subject: Disable the account manager for now, and anything else HTTPS related. Bump it to the next version. --- OpenSim/Server/Handlers/Web/WebServerConnector.cs | 92 ++++++++++++++++++----- 1 file changed, 74 insertions(+), 18 deletions(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerConnector.cs b/OpenSim/Server/Handlers/Web/WebServerConnector.cs index c4a0531..0f328d9 100644 --- a/OpenSim/Server/Handlers/Web/WebServerConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerConnector.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Generic; using System.IO; using System.Net; +using System.Net.Mail; using System.Reflection; using System.Security; using System.Text; @@ -32,10 +33,10 @@ namespace OpenSim.Server.Handlers.Web private IPAddress m_IP; private IHttpServer m_server; - private IHttpServer m_SSLserver = null; +// private IHttpServer m_SSLserver = null; private string m_domain = ""; private uint m_http_port; - private uint m_https_port = 0; +// private uint m_https_port = 0; private Dictionary m_auth = new Dictionary(); @@ -43,6 +44,15 @@ namespace OpenSim.Server.Handlers.Web private static Dictionary m_lastNames = new Dictionary(); private static Dictionary m_fullNames = new Dictionary(); +/* TODO - shelved for now, rewrite it in Lua for lighttpd after the release. + private string m_SMTP_server; + private string m_SMTP_port; + private string m_SMTP_user; + private string m_SMTP_password; + private string m_email_from; + private SmtpClient m_smtp; +*/ + public WebServerConnector(IConfigSource config, IHttpServer server, string configName) : base(config, server, configName) { string dllName = String.Empty; @@ -106,6 +116,7 @@ namespace OpenSim.Server.Handlers.Web cfg = m_Config.Configs["Const"]; m_domain = cfg.GetString("HostName", "localhost"); +/* TODO - shelved for now, rewrite it in Lua for lighttpd after the release. // Copied from OpenSim/Region/OptionalModules/ViewerSupport/GodNamesModule.cs cfg = m_Config.Configs["GodNames"]; if (null != cfg) @@ -147,8 +158,32 @@ namespace OpenSim.Server.Handlers.Web else m_log.Info("[WEB SERVICE]: No god names loaded."); + // Add the email client. + cfg = m_Config.Configs["SMTP"]; + if (null != cfg) + { + m_log.Info("[WEB SERVICE]: Loading email configuration."); + m_SMTP_server = cfg.GetString("SMTP_SERVER_HOSTNAME", "127.0.0.1"); + m_SMTP_port = cfg.GetString("SMTP_SERVER_PORT", "25"); + m_SMTP_user = cfg.GetString("SMTP_SERVER_LOGIN", ""); + m_SMTP_password = cfg.GetString("SMTP_SERVER_PASSWORD", ""); + m_email_from = cfg.GetString("host_domain_header_from", "grid@localhost"); + + m_smtp = new SmtpClient + { + Host = m_SMTP_server, + Port = Convert.ToInt16(m_SMTP_port), + EnableSsl = false, + DeliveryMethod = SmtpDeliveryMethod.Network, + Credentials = new NetworkCredential(m_SMTP_user, m_SMTP_password), + Timeout = 20000 + }; + } +*/ + // Add the HTTP and HTTPS handlers. server.AddHTTPHandler("/web/", WebRequestHandler); +/* TODO - shelved for now, rewrite it in Lua for lighttpd after the release. IConfig networkConfig = m_Config.Configs["Network"]; if (null != networkConfig) { @@ -160,13 +195,16 @@ namespace OpenSim.Server.Handlers.Web m_SSLserver.AddHTTPHandler("/web/", WebRequestHandlerSSL); } } +*/ } // AAARGGGH, in the request we don't get the HTTP/S, domain name, nor port number we were called from. So we have to fake it, sorta. +/* TODO - shelved for now, rewrite it in Lua for lighttpd after the release. private Hashtable WebRequestHandlerSSL(Hashtable request) { return Handler(request, true); } +*/ private Hashtable WebRequestHandler(Hashtable request) { return Handler(request, false); @@ -189,8 +227,10 @@ namespace OpenSim.Server.Handlers.Web string file = reqpath.Remove(0, 5); string path = Path.Combine(Util.webDir(), file); +// m_log.InfoFormat("[WEB SERVICE]: {0} {1} {2} : {3} {4}, server IP {5} content type {6}, body {7}.", +// headers["remote_addr"].ToString(), method, m_domain, (usedSSL ? m_https_port : m_http_port), reqpath, m_IP, type, body); m_log.InfoFormat("[WEB SERVICE]: {0} {1} {2} : {3} {4}, server IP {5} content type {6}, body {7}.", - headers["remote_addr"].ToString(), method, m_domain, (usedSSL ? m_https_port : m_http_port), reqpath, m_IP, type, body); + headers["remote_addr"].ToString(), method, m_domain, m_http_port, reqpath, m_IP, type, body); if (! Path.GetFullPath(path).StartsWith(Path.GetFullPath(Util.webDir()))) { @@ -244,14 +284,15 @@ namespace OpenSim.Server.Handlers.Web foreach (String q in query) { - m_log.InfoFormat("[WEB SERVICE]: {0} {1} query {2} = {3}", method, reqpath, q, (string) request[q]); +// m_log.InfoFormat("[WEB SERVICE]: {0} {1} query {2} = {3}", method, reqpath, q, (string) request[q]); fields[q] = bobbyTables(q, (string) request[q]); } - foreach (DictionaryEntry h in headers) - m_log.DebugFormat("[WEB SERVICE]: {0} {1} header {2} = {3}", method, reqpath, (string) h.Key, (string) h.Value); +// foreach (DictionaryEntry h in headers) +// m_log.DebugFormat("[WEB SERVICE]: {0} {1} header {2} = {3}", method, reqpath, (string) h.Key, (string) h.Value); // I dunno what these vars are or where they come from, never actually seen them. - foreach (DictionaryEntry h in vars) - m_log.InfoFormat("[WEB SERVICE]: {0} {1} var {2} = {3}", method, reqpath, (string) h.Key, (string) h.Value); + // Ah, viewers send them, and they seem to be identical to the query that viewers also send. +// foreach (DictionaryEntry h in vars) +// m_log.InfoFormat("[WEB SERVICE]: {0} {1} var {2} = {3}", method, reqpath, (string) h.Key, (string) h.Value); reply["int_response_code"] = 200; @@ -305,6 +346,7 @@ namespace OpenSim.Server.Handlers.Web csr.Close(); } } +/* TODO - shelved for now, rewrite it in Lua for lighttpd after the release. else { if ("account.html" == file) @@ -329,15 +371,16 @@ namespace OpenSim.Server.Handlers.Web "404 error, can't find the " + reqpath + " page.

 

"; } } +*/ } else if ("POST" == method) { - if ("account.html" == file) - { - string doit = fields["doit"].ToString(); - string toke_n_munchie = ""; - replyHeaders["Cache-Control"] = "no-cache"; +// if ("account.html" == file) +// { +// string doit = fields["doit"].ToString(); +// string toke_n_munchie = ""; +// replyHeaders["Cache-Control"] = "no-cache"; /* TODO - Switch to using prepared SQL statements. @@ -356,7 +399,7 @@ namespace OpenSim.Server.Handlers.Web Deal with editing yourself. Deal with editing others, but only as god. */ - +/* TODO - shelved for now, rewrite it in Lua for lighttpd after the release. if ((null == cookies["toke_n_munchie"]) || (null == fields["toke_n_munchie"]) || ("" == cookies["toke_n_munchie"].ToString()) || ("" == fields["toke_n_munchie"].ToString())) toke_n_munchie = newSession(doit, headers, ref fields, ref replyHeaders); @@ -417,7 +460,19 @@ namespace OpenSim.Server.Handlers.Web else if (("create" == doit)) reply["str_response_string"] = accountCreationPage(fields, body); else + { + var fromAddress = new MailAddress(m_email_from, (string) ssi["grid"]); + var toAddress = new MailAddress((string) fields["email"], (string) fields["name"]); + using (var message = new MailMessage(fromAddress, toAddress) + { + Subject = "validation email", + Body = "Should be a linky around here somewhere." + }) + { + m_smtp.Send(message); + } reply["str_response_string"] = loggedOnPage(fields, body); + } } else deleteSession(toke_n_munchie.ToString(), doit, headers, ref fields, ref replyHeaders); @@ -446,15 +501,16 @@ namespace OpenSim.Server.Handlers.Web } else reply["str_response_string"] = loggedOnPage(fields, body); - } - else // Not one of our dynamic pages. - { +*/ +// } +// else // Not one of our dynamic pages. +// { m_log.ErrorFormat("[WEB SERVICE]: No such POST target {0}.", path); reply["int_response_code"] = 404; reply["content_type"] = "text/html"; reply["str_response_string"] = "404 Unknown page" + "404 error, can't find the " + reqpath + " page.

 

"; - } +// } } else // Not one of our handled methods. { -- cgit v1.1 From 2c4a60c5d686168e54d71b0582b8d78eafec00a1 Mon Sep 17 00:00:00 2001 From: onefang Date: Thu, 22 Aug 2019 15:47:24 +1000 Subject: More stats, and an actual stats web page. --- OpenSim/Server/Handlers/Web/WebServerConnector.cs | 37 +++++++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerConnector.cs b/OpenSim/Server/Handlers/Web/WebServerConnector.cs index 0f328d9..f06d4d8 100644 --- a/OpenSim/Server/Handlers/Web/WebServerConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerConnector.cs @@ -242,14 +242,45 @@ namespace OpenSim.Server.Handlers.Web return reply; } - long locIn = m_database.Count("Presence", "RegionID != '00000000-0000-0000-0000-000000000000'"); // Locals online but not HGing, and HGers in world. - long HGin = m_database.Count("Presence", "UserID NOT IN (SELECT PrincipalID FROM UserAccounts)"); // HGers in world. + long locIn = m_database.Count("Presence", "RegionID != '00000000-0000-0000-0000-000000000000'"); // Locals online but not HGing, and HGers in world. + long HGin = m_database.Count("Presence", "UserID NOT IN (SELECT PrincipalID FROM UserAccounts)"); // HGers in world. ssi["hgers"] = HGin.ToString(); ssi["inworld"] = (locIn - HGin).ToString(); ssi["outworld"] = m_database.Count("hg_traveling_data", "GridExternalName != '" + ssi["uri"] + "'").ToString(); // Locals that are HGing. ssi["members"] = m_database.Count("UserAccounts").ToString(); - ssi["month"] = m_database.Count("GridUser", "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200))").ToString(); ssi["sims"] = m_database.Count("regions").ToString(); + ssi["onlineSims"] = m_database.Count("regions", "sizeX != 0").ToString(); + ssi["varRegions"] = m_database.Count("regions", "sizeX > 256 or sizeY > 256").ToString(); + ssi["singleSims"] = m_database.Count("regions", "sizeX = 256 and sizeY = 256").ToString(); + ssi["offlineSims"] = m_database.Count("regions", "sizeX = 0").ToString(); + + // Calculate grid area. + long simSize = 0; + List< Hashtable > rows = m_database.Select("regions", "sizeX,sizeY", "sizeX != 0", ""); + foreach (Hashtable row in rows) + { + simSize = simSize + Convert.ToInt32(row["sizeX"]) * Convert.ToInt32(row["sizeY"]); + } + ssi["simsSize"] = simSize.ToString(); + + // Count local and HG visitors for the last 30 and 60 days. + HGin = m_database.Count("GridUser", "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200))"); + rows = m_database.Join("GridUser", "GridUser.UserID", "INNER JOIN UserAccounts ON GridUser.UserID = UserAccounts.PrincipalID", + "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200))", ""); + locIn = rows.Count; + ssi["locDay30"] = locIn.ToString(); + ssi["day30"] = HGin.ToString(); + HGin = HGin - locIn; + ssi["HGday30"] = HGin.ToString(); + + HGin = m_database.Count("GridUser", "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 4838400))"); + rows = m_database.Join("GridUser", "GridUser.UserID", "INNER JOIN UserAccounts ON GridUser.UserID = UserAccounts.PrincipalID", + "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 4838400))", ""); + locIn = rows.Count; + ssi["locDay60"] = locIn.ToString(); + ssi["day60"] = HGin.ToString(); + HGin = HGin - locIn; + ssi["HGday60"] = HGin.ToString(); foreach (DictionaryEntry h in headers) { -- cgit v1.1 From 817dabf5cb07044c2fee331455a0bb961b13dd46 Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 25 Aug 2019 14:15:28 +1000 Subject: Now with favicons. --- OpenSim/Server/Handlers/Web/WebServerConnector.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerConnector.cs b/OpenSim/Server/Handlers/Web/WebServerConnector.cs index f06d4d8..11bf435 100644 --- a/OpenSim/Server/Handlers/Web/WebServerConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerConnector.cs @@ -237,7 +237,7 @@ namespace OpenSim.Server.Handlers.Web m_log.ErrorFormat("[WEB SERVICE]: INVALID PATH {0} != {1}", Path.GetFullPath(path), Path.GetFullPath(Util.webDir())); reply["int_response_code"] = 404; reply["content_type"] = "text/html"; - reply["str_response_string"] = "404 Unknown page" + + reply["str_response_string"] = "404 Unknown page" + "404 error, can't find the " + reqpath + " page.

 

"; return reply; } @@ -398,7 +398,7 @@ namespace OpenSim.Server.Handlers.Web m_log.ErrorFormat("[WEB SERVICE]: Unable to read {0}.", reqpath); reply["int_response_code"] = 404; reply["content_type"] = "text/html"; - reply["str_response_string"] = "404 Unknown page" + + reply["str_response_string"] = "404 Unknown page" + "404 error, can't find the " + reqpath + " page.

 

"; } } @@ -519,7 +519,7 @@ namespace OpenSim.Server.Handlers.Web List< Hashtable > rows = m_database.Select("UserAccounts", "CONCAT(FirstName,' ',LastName) as Name,UserTitle as Title,UserLevel as Level,UserFlags as Flags,PrincipalID as UUID", "", "Name"); - reply["str_response_string"] = "member accounts" + + reply["str_response_string"] = "member accounts" + table(rows, new string[5] {"Name", "Title", "Level", "Flags", "UUID"}, "member accounts", "account.html?doit=edit&token=" + fields["toke_n_munchie"].ToString(), "UUID") + "

" + button("my account") + "

"; } @@ -539,7 +539,7 @@ namespace OpenSim.Server.Handlers.Web m_log.ErrorFormat("[WEB SERVICE]: No such POST target {0}.", path); reply["int_response_code"] = 404; reply["content_type"] = "text/html"; - reply["str_response_string"] = "404 Unknown page" + + reply["str_response_string"] = "404 Unknown page" + "404 error, can't find the " + reqpath + " page.

 

"; // } } @@ -548,7 +548,7 @@ namespace OpenSim.Server.Handlers.Web m_log.ErrorFormat("[WEB SERVICE]: UNKNOWN method {0} path {1}.", method, reqpath); reply["int_response_code"] = 404; reply["content_type"] = "text/html"; - reply["str_response_string"] = "Unknown method" + + reply["str_response_string"] = "Unknown method" + "HUH! For " + reqpath + " page.

 

"; } -- cgit v1.1 From 9d6c4374e6e2836fdb5d8703e4e92549c9d96b22 Mon Sep 17 00:00:00 2001 From: onefang Date: Sat, 31 Aug 2019 14:28:57 +1000 Subject: typo-- --- OpenSim/Server/Handlers/Web/WebServerConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Server') diff --git a/OpenSim/Server/Handlers/Web/WebServerConnector.cs b/OpenSim/Server/Handlers/Web/WebServerConnector.cs index 11bf435..5389c6e 100644 --- a/OpenSim/Server/Handlers/Web/WebServerConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerConnector.cs @@ -345,7 +345,7 @@ namespace OpenSim.Server.Handlers.Web if (0 >= DateTime.Compare(ifdt, dt)) { reply["int_response_code"] = 304; - m_log.InfoFormat("[WEB SERVICE]: If-Modified-Since is earliar or equal to Last-Modified, from {0}", reqpath); + m_log.InfoFormat("[WEB SERVICE]: If-Modified-Since is earlier or equal to Last-Modified, from {0}", reqpath); reply["headers"] = replyHeaders; if ("HEAD" == method) { -- cgit v1.1