From 9b998a068a2622f43ac813800654e357f94d0c21 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 28 Oct 2015 15:40:38 -0400 Subject: update image encoding --- .../HttpServer/HttpListenerHost.cs | 4 +++- MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs | 5 ++++- .../HttpServer/SocketSharp/WebSocketSharpListener.cs | 10 +--------- 3 files changed, 8 insertions(+), 11 deletions(-) (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index e8bb40ba1..6abfa0674 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -92,7 +92,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer {typeof (FileNotFoundException), 404}, {typeof (DirectoryNotFoundException), 404}, {typeof (SecurityException), 401}, - {typeof (UnauthorizedAccessException), 500} + {typeof (PaymentRequiredException), 402}, + {typeof (UnauthorizedAccessException), 500}, + {typeof (ApplicationException), 500} }; HostConfig.Instance.DebugMode = true; diff --git a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs b/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs index 02ce38ef1..fae702023 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs @@ -16,7 +16,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer /// The duration. public static void LogResponse(ILogger logger, int statusCode, string url, string endPoint, TimeSpan duration) { - logger.Info("HTTP Response {0} to {1}. Time: {2}ms. {3}", statusCode, endPoint, Convert.ToInt32(duration.TotalMilliseconds).ToString(CultureInfo.InvariantCulture), url); + var durationMs = duration.TotalMilliseconds; + var logSuffix = durationMs >= 1000 ? "ms (slow)" : "ms"; + + logger.Info("HTTP Response {0} to {1}. Time: {2}{3}. {4}", statusCode, endPoint, Convert.ToInt32(durationMs).ToString(CultureInfo.InvariantCulture), logSuffix, url); } } } diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs index f8178c115..9f80c8ac9 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs @@ -183,15 +183,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp /// The request. private static void LogRequest(ILogger logger, HttpListenerRequest request) { - var log = new StringBuilder(); - - var headers = string.Join(",", request.Headers.AllKeys.Where(i => !string.Equals(i, "cookie", StringComparison.OrdinalIgnoreCase) && !string.Equals(i, "Referer", StringComparison.OrdinalIgnoreCase)).Select(k => k + "=" + request.Headers[k])); - - log.AppendLine("Ip: " + request.RemoteEndPoint + ". Headers: " + headers); - - var type = request.IsWebSocketRequest ? "Web Socket" : "HTTP " + request.HttpMethod; - - logger.LogMultiline(type + " " + request.Url, LogSeverity.Info, log); + logger.Info("{0} {1}. UserAgent: {2}", (request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod), request.Url, request.UserAgent ?? string.Empty); } private void HandleError(Exception ex, HttpListenerContext context) -- cgit v1.2.3 From 9abdf5a0450dbd8925b9360d59c4b27d6c0d5c8b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 30 Oct 2015 12:58:36 -0400 Subject: update components --- MediaBrowser.Controller/MediaBrowser.Controller.csproj | 1 - MediaBrowser.Controller/Net/PaymentRequiredException.cs | 15 --------------- .../HttpServer/HttpListenerHost.cs | 1 + 3 files changed, 1 insertion(+), 16 deletions(-) delete mode 100644 MediaBrowser.Controller/Net/PaymentRequiredException.cs (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 600674114..bcf4de2a2 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -248,7 +248,6 @@ - diff --git a/MediaBrowser.Controller/Net/PaymentRequiredException.cs b/MediaBrowser.Controller/Net/PaymentRequiredException.cs deleted file mode 100644 index e09fe092e..000000000 --- a/MediaBrowser.Controller/Net/PaymentRequiredException.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Net -{ - /// - /// Corresponds to a 402 response code - /// - public class PaymentRequiredException : Exception - { - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 6abfa0674..e8ed91615 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -19,6 +19,7 @@ using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Security; namespace MediaBrowser.Server.Implementations.HttpServer { -- cgit v1.2.3 From ab6fefbbbdb1afedecc68fe2330bde081cbdbc47 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 14 Nov 2015 14:09:49 -0500 Subject: fixes #1248 - Browsing to /web/ causes error --- .../HttpServer/HttpListenerHost.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 1ac47016d..6ade9a8f6 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -330,6 +330,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer httpRes.RedirectToUrl("emby/" + DefaultRedirectPath); return Task.FromResult(true); } + if (string.Equals(localPath, "/web", StringComparison.OrdinalIgnoreCase)) + { + httpRes.RedirectToUrl(DefaultRedirectPath); + return Task.FromResult(true); + } + if (string.Equals(localPath, "/web/", StringComparison.OrdinalIgnoreCase)) + { + httpRes.RedirectToUrl("../" + DefaultRedirectPath); + return Task.FromResult(true); + } if (string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase)) { httpRes.RedirectToUrl(DefaultRedirectPath); -- cgit v1.2.3 From e9686a56a607a9b8fca00a990063319ac0fe9138 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 1 Dec 2015 00:22:52 -0500 Subject: update requirecss --- .../HttpServer/HttpResultFactory.cs | 37 +++++++++++++++------- 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs index 080441dda..4252d7aa8 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -114,6 +114,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer /// result public object GetOptimizedResult(IRequest requestContext, T result, IDictionary responseHeaders = null) where T : class + { + return GetOptimizedResultInternal(requestContext, result, true, responseHeaders); + } + + private object GetOptimizedResultInternal(IRequest requestContext, T result, bool addCachePrevention, IDictionary responseHeaders = null) + where T : class { if (result == null) { @@ -122,20 +128,27 @@ namespace MediaBrowser.Server.Implementations.HttpServer var optimizedResult = requestContext.ToOptimizedResult(result); - if (responseHeaders != null) + if (responseHeaders == null) { - // Apply headers - var hasOptions = optimizedResult as IHasOptions; + responseHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); + } - if (hasOptions != null) - { - AddResponseHeaders(hasOptions, responseHeaders); - } + if (addCachePrevention) + { + responseHeaders["Expires"] = "-1"; + } + + // Apply headers + var hasOptions = optimizedResult as IHasOptions; + + if (hasOptions != null) + { + AddResponseHeaders(hasOptions, responseHeaders); } return optimizedResult; } - + /// /// Gets the optimized result using cache. /// @@ -166,7 +179,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer if (responseHeaders == null) { - responseHeaders = new Dictionary(); + responseHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); } // See if the result is already cached in the browser @@ -177,7 +190,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer return result; } - return GetOptimizedResult(requestContext, factoryFn(), responseHeaders); + return GetOptimizedResultInternal(requestContext, factoryFn(), false, responseHeaders); } /// @@ -209,7 +222,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer if (responseHeaders == null) { - responseHeaders = new Dictionary(); + responseHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); } // See if the result is already cached in the browser @@ -363,7 +376,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer public object GetStaticResult(IRequest requestContext, StaticResultOptions options) { var cacheKey = options.CacheKey; - options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary(); + options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary(StringComparer.OrdinalIgnoreCase); var contentType = options.ContentType; if (cacheKey == Guid.Empty) -- cgit v1.2.3 From d27cd521b54d0d9c0d2256218e927bb88fd2aac0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 14 Dec 2015 09:45:42 -0500 Subject: rework dialog --- .../Networking/BaseNetworkManager.cs | 2 +- MediaBrowser.Common/Net/INetworkManager.cs | 7 +++++++ .../HttpServer/HttpListenerHost.cs | 13 ++++++------- .../HttpServer/ServerFactory.cs | 5 ++++- MediaBrowser.Server.Startup.Common/ApplicationHost.cs | 2 +- MediaBrowser.WebDashboard/Api/DashboardService.cs | 19 +++++++++++++++++++ .../MediaBrowser.WebDashboard.csproj | 5 +---- 7 files changed, 39 insertions(+), 14 deletions(-) (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs index 703fec68d..1708206dc 100644 --- a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs +++ b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs @@ -84,7 +84,7 @@ namespace MediaBrowser.Common.Implementations.Networking return true; } - private bool IsInPrivateAddressSpace(string endpoint) + public bool IsInPrivateAddressSpace(string endpoint) { if (string.Equals(endpoint, "::1", StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs index 8fc947e8f..a3bf1aac8 100644 --- a/MediaBrowser.Common/Net/INetworkManager.cs +++ b/MediaBrowser.Common/Net/INetworkManager.cs @@ -25,6 +25,13 @@ namespace MediaBrowser.Common.Net /// [string] MAC Address string GetMacAddress(); + /// + /// Determines whether [is in private address space] [the specified endpoint]. + /// + /// The endpoint. + /// true if [is in private address space] [the specified endpoint]; otherwise, false. + bool IsInPrivateAddressSpace(string endpoint); + /// /// Gets the network shares. /// diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 6ade9a8f6..847982976 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -19,6 +19,7 @@ using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Common.Security; namespace MediaBrowser.Server.Implementations.HttpServer @@ -46,6 +47,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer public string CertificatePath { get; private set; } private readonly IServerConfigurationManager _config; + private readonly INetworkManager _networkManager; /// /// Gets the local end points. @@ -69,10 +71,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer ILogManager logManager, IServerConfigurationManager config, string serviceName, - string defaultRedirectPath, params Assembly[] assembliesWithServices) + string defaultRedirectPath, INetworkManager networkManager, params Assembly[] assembliesWithServices) : base(serviceName, assembliesWithServices) { DefaultRedirectPath = defaultRedirectPath; + _networkManager = networkManager; _config = config; _logger = logManager.GetLogger("HttpServer"); @@ -175,11 +178,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer private void OnRequestReceived(string localEndPoint) { - var ignore = localEndPoint.IndexOf("::", StringComparison.OrdinalIgnoreCase) != -1 || - - localEndPoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) || - localEndPoint.StartsWith("localhost", StringComparison.OrdinalIgnoreCase) || - localEndPoint.StartsWith("169.", StringComparison.OrdinalIgnoreCase); + var ignore = _networkManager.IsInPrivateAddressSpace(localEndPoint); if (ignore) { @@ -188,7 +187,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer if (_localEndpointLock.TryEnterWriteLock(100)) { - var list = _localEndpoints.ToList(); + var list = _localEndpoints; list.Remove(localEndPoint); list.Insert(0, localEndPoint); diff --git a/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs index 4d81ec157..cc351f6b3 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Logging; @@ -17,18 +18,20 @@ namespace MediaBrowser.Server.Implementations.HttpServer /// The application host. /// The log manager. /// The configuration. + /// The _networkmanager. /// Name of the server. /// The default redirectpath. /// IHttpServer. public static IHttpServer CreateServer(IApplicationHost applicationHost, ILogManager logManager, IServerConfigurationManager config, + INetworkManager _networkmanager, string serverName, string defaultRedirectpath) { LogManager.LogFactory = new ServerLogFactory(logManager); - return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath); + return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, _networkmanager); } } } diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index f0fe68dd8..f4da52f2e 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -436,7 +436,7 @@ namespace MediaBrowser.Server.Startup.Common RegisterSingleInstance(() => new SearchEngine(LogManager, LibraryManager, UserManager)); - HttpServer = ServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, "Emby", "web/index.html"); + HttpServer = ServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, NetworkManager, "Emby", "web/index.html"); HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading"); RegisterSingleInstance(HttpServer, false); progress.Report(10); diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 0ee62cb96..2fc77dff4 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -310,6 +310,7 @@ namespace MediaBrowser.WebDashboard.Api DeleteFilesByExtension(bowerPath, ".md"); DeleteFilesByExtension(bowerPath, ".json"); DeleteFilesByExtension(bowerPath, ".gz"); + DeleteFilesByExtension(bowerPath, ".bat"); DeleteFilesByName(bowerPath, "copying", true); DeleteFilesByName(bowerPath, "license", true); DeleteFilesByName(bowerPath, "license-mit", true); @@ -330,6 +331,8 @@ namespace MediaBrowser.WebDashboard.Api DeleteFoldersByName(bowerPath, "grunt"); DeleteFoldersByName(bowerPath, "rollups"); + DeleteCryptoFiles(Path.Combine(bowerPath, "cryptojslib", "components")); + DeleteFoldersByName(Path.Combine(bowerPath, "jquery"), "src"); DeleteFoldersByName(Path.Combine(bowerPath, "jstree"), "src"); DeleteFoldersByName(Path.Combine(bowerPath, "Sortable"), "meteor"); @@ -357,6 +360,22 @@ namespace MediaBrowser.WebDashboard.Api return ""; } + private void DeleteCryptoFiles(string path) + { + var files = _fileSystem.GetFiles(path) + .ToList(); + + var keepFiles = new[] { "core-min.js", "md5-min.js", "sha1-min.js" }; + + foreach (var file in files) + { + if (!keepFiles.Contains(file.Name, StringComparer.OrdinalIgnoreCase)) + { + _fileSystem.DeleteFile(file.FullName); + } + } + } + private void DeleteFilesByExtension(string path, string extension) { var files = _fileSystem.GetFiles(path, true) diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 4ce05415b..975c60a0b 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -116,15 +116,12 @@ PreserveNewest - + PreserveNewest PreserveNewest - - PreserveNewest - PreserveNewest -- cgit v1.2.3 From 9c3119808b73bdc988312144cc034f55e8a8c616 Mon Sep 17 00:00:00 2001 From: Luke Date: Fri, 25 Dec 2015 16:21:18 -0500 Subject: fixes #1075 - XSS in "Active Devices" Panel of Admin Dashboard --- .../HttpServer/Security/AuthorizationContext.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index 509a00ff9..75d54a80a 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -175,11 +175,22 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security if (param.Length == 2) { - result.Add(param[0], param[1].Trim(new[] { '"' })); + var value = NormalizeValue (param[1].Trim(new[] { '"' })); + result.Add(param[0], value); } } return result; } + + private string NormalizeValue(string value) + { + if (string.IsNullOrWhiteSpace (value)) + { + return value; + } + + return System.Net.WebUtility.HtmlEncode(value); + } } } -- cgit v1.2.3 From 3007a988af2dcc3ccc23379a2ebdabce0a8f5e58 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 26 Dec 2015 03:07:52 -0500 Subject: update SocketHttpListener --- .../HttpServer/SocketSharp/HttpUtility.cs | 941 +++++++++++++++++++++ .../SocketSharp/WebSocketSharpRequest.cs | 3 +- .../MediaBrowser.Server.Implementations.csproj | 5 +- .../packages.config | 2 +- 4 files changed, 947 insertions(+), 4 deletions(-) create mode 100644 MediaBrowser.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs new file mode 100644 index 000000000..3ef48d13a --- /dev/null +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs @@ -0,0 +1,941 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Text; + +namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp +{ + public static class MyHttpUtility + { + sealed class HttpQSCollection : NameValueCollection + { + public override string ToString() + { + int count = Count; + if (count == 0) + return ""; + StringBuilder sb = new StringBuilder(); + string[] keys = AllKeys; + for (int i = 0; i < count; i++) + { + sb.AppendFormat("{0}={1}&", keys[i], this[keys[i]]); + } + if (sb.Length > 0) + sb.Length--; + return sb.ToString(); + } + } + + // Must be sorted + static readonly long[] entities = new long[] { + (long)'A' << 56 | (long)'E' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24, + (long)'A' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, + (long)'A' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, + (long)'A' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, + (long)'A' << 56 | (long)'l' << 48 | (long)'p' << 40 | (long)'h' << 32 | (long)'a' << 24, + (long)'A' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'g' << 24, + (long)'A' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16, + (long)'A' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, + (long)'B' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32, + (long)'C' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'d' << 32 | (long)'i' << 24 | (long)'l' << 16, + (long)'C' << 56 | (long)'h' << 48 | (long)'i' << 40, + (long)'D' << 56 | (long)'a' << 48 | (long)'g' << 40 | (long)'g' << 32 | (long)'e' << 24 | (long)'r' << 16, + (long)'D' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'t' << 32 | (long)'a' << 24, + (long)'E' << 56 | (long)'T' << 48 | (long)'H' << 40, + (long)'E' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, + (long)'E' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, + (long)'E' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, + (long)'E' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8, + (long)'E' << 56 | (long)'t' << 48 | (long)'a' << 40, + (long)'E' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, + (long)'G' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'m' << 32 | (long)'a' << 24, + (long)'I' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, + (long)'I' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, + (long)'I' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, + (long)'I' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'a' << 32, + (long)'I' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, + (long)'K' << 56 | (long)'a' << 48 | (long)'p' << 40 | (long)'p' << 32 | (long)'a' << 24, + (long)'L' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'b' << 32 | (long)'d' << 24 | (long)'a' << 16, + (long)'M' << 56 | (long)'u' << 48, + (long)'N' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16, + (long)'N' << 56 | (long)'u' << 48, + (long)'O' << 56 | (long)'E' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24, + (long)'O' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, + (long)'O' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, + (long)'O' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, + (long)'O' << 56 | (long)'m' << 48 | (long)'e' << 40 | (long)'g' << 32 | (long)'a' << 24, + (long)'O' << 56 | (long)'m' << 48 | (long)'i' << 40 | (long)'c' << 32 | (long)'r' << 24 | (long)'o' << 16 | (long)'n' << 8, + (long)'O' << 56 | (long)'s' << 48 | (long)'l' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'h' << 16, + (long)'O' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16, + (long)'O' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, + (long)'P' << 56 | (long)'h' << 48 | (long)'i' << 40, + (long)'P' << 56 | (long)'i' << 48, + (long)'P' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24, + (long)'P' << 56 | (long)'s' << 48 | (long)'i' << 40, + (long)'R' << 56 | (long)'h' << 48 | (long)'o' << 40, + (long)'S' << 56 | (long)'c' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'o' << 24 | (long)'n' << 16, + (long)'S' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24, + (long)'T' << 56 | (long)'H' << 48 | (long)'O' << 40 | (long)'R' << 32 | (long)'N' << 24, + (long)'T' << 56 | (long)'a' << 48 | (long)'u' << 40, + (long)'T' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24, + (long)'U' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, + (long)'U' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, + (long)'U' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, + (long)'U' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8, + (long)'U' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, + (long)'X' << 56 | (long)'i' << 48, + (long)'Y' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, + (long)'Y' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, + (long)'Z' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32, + (long)'a' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, + (long)'a' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, + (long)'a' << 56 | (long)'c' << 48 | (long)'u' << 40 | (long)'t' << 32 | (long)'e' << 24, + (long)'a' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24, + (long)'a' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, + (long)'a' << 56 | (long)'l' << 48 | (long)'e' << 40 | (long)'f' << 32 | (long)'s' << 24 | (long)'y' << 16 | (long)'m' << 8, + (long)'a' << 56 | (long)'l' << 48 | (long)'p' << 40 | (long)'h' << 32 | (long)'a' << 24, + (long)'a' << 56 | (long)'m' << 48 | (long)'p' << 40, + (long)'a' << 56 | (long)'n' << 48 | (long)'d' << 40, + (long)'a' << 56 | (long)'n' << 48 | (long)'g' << 40, + (long)'a' << 56 | (long)'p' << 48 | (long)'o' << 40 | (long)'s' << 32, + (long)'a' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'g' << 24, + (long)'a' << 56 | (long)'s' << 48 | (long)'y' << 40 | (long)'m' << 32 | (long)'p' << 24, + (long)'a' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16, + (long)'a' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, + (long)'b' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24, + (long)'b' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32, + (long)'b' << 56 | (long)'r' << 48 | (long)'v' << 40 | (long)'b' << 32 | (long)'a' << 24 | (long)'r' << 16, + (long)'b' << 56 | (long)'u' << 48 | (long)'l' << 40 | (long)'l' << 32, + (long)'c' << 56 | (long)'a' << 48 | (long)'p' << 40, + (long)'c' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'d' << 32 | (long)'i' << 24 | (long)'l' << 16, + (long)'c' << 56 | (long)'e' << 48 | (long)'d' << 40 | (long)'i' << 32 | (long)'l' << 24, + (long)'c' << 56 | (long)'e' << 48 | (long)'n' << 40 | (long)'t' << 32, + (long)'c' << 56 | (long)'h' << 48 | (long)'i' << 40, + (long)'c' << 56 | (long)'i' << 48 | (long)'r' << 40 | (long)'c' << 32, + (long)'c' << 56 | (long)'l' << 48 | (long)'u' << 40 | (long)'b' << 32 | (long)'s' << 24, + (long)'c' << 56 | (long)'o' << 48 | (long)'n' << 40 | (long)'g' << 32, + (long)'c' << 56 | (long)'o' << 48 | (long)'p' << 40 | (long)'y' << 32, + (long)'c' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'r' << 24, + (long)'c' << 56 | (long)'u' << 48 | (long)'p' << 40, + (long)'c' << 56 | (long)'u' << 48 | (long)'r' << 40 | (long)'r' << 32 | (long)'e' << 24 | (long)'n' << 16, + (long)'d' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32, + (long)'d' << 56 | (long)'a' << 48 | (long)'g' << 40 | (long)'g' << 32 | (long)'e' << 24 | (long)'r' << 16, + (long)'d' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32, + (long)'d' << 56 | (long)'e' << 48 | (long)'g' << 40, + (long)'d' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'t' << 32 | (long)'a' << 24, + (long)'d' << 56 | (long)'i' << 48 | (long)'a' << 40 | (long)'m' << 32 | (long)'s' << 24, + (long)'d' << 56 | (long)'i' << 48 | (long)'v' << 40 | (long)'i' << 32 | (long)'d' << 24 | (long)'e' << 16, + (long)'e' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, + (long)'e' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, + (long)'e' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, + (long)'e' << 56 | (long)'m' << 48 | (long)'p' << 40 | (long)'t' << 32 | (long)'y' << 24, + (long)'e' << 56 | (long)'m' << 48 | (long)'s' << 40 | (long)'p' << 32, + (long)'e' << 56 | (long)'n' << 48 | (long)'s' << 40 | (long)'p' << 32, + (long)'e' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8, + (long)'e' << 56 | (long)'q' << 48 | (long)'u' << 40 | (long)'i' << 32 | (long)'v' << 24, + (long)'e' << 56 | (long)'t' << 48 | (long)'a' << 40, + (long)'e' << 56 | (long)'t' << 48 | (long)'h' << 40, + (long)'e' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, + (long)'e' << 56 | (long)'u' << 48 | (long)'r' << 40 | (long)'o' << 32, + (long)'e' << 56 | (long)'x' << 48 | (long)'i' << 40 | (long)'s' << 32 | (long)'t' << 24, + (long)'f' << 56 | (long)'n' << 48 | (long)'o' << 40 | (long)'f' << 32, + (long)'f' << 56 | (long)'o' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'l' << 24 | (long)'l' << 16, + (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'1' << 24 | (long)'2' << 16, + (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'1' << 24 | (long)'4' << 16, + (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'3' << 24 | (long)'4' << 16, + (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'l' << 24, + (long)'g' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'m' << 32 | (long)'a' << 24, + (long)'g' << 56 | (long)'e' << 48, + (long)'g' << 56 | (long)'t' << 48, + (long)'h' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32, + (long)'h' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32, + (long)'h' << 56 | (long)'e' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'t' << 24 | (long)'s' << 16, + (long)'h' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'l' << 32 | (long)'i' << 24 | (long)'p' << 16, + (long)'i' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, + (long)'i' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, + (long)'i' << 56 | (long)'e' << 48 | (long)'x' << 40 | (long)'c' << 32 | (long)'l' << 24, + (long)'i' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, + (long)'i' << 56 | (long)'m' << 48 | (long)'a' << 40 | (long)'g' << 32 | (long)'e' << 24, + (long)'i' << 56 | (long)'n' << 48 | (long)'f' << 40 | (long)'i' << 32 | (long)'n' << 24, + (long)'i' << 56 | (long)'n' << 48 | (long)'t' << 40, + (long)'i' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'a' << 32, + (long)'i' << 56 | (long)'q' << 48 | (long)'u' << 40 | (long)'e' << 32 | (long)'s' << 24 | (long)'t' << 16, + (long)'i' << 56 | (long)'s' << 48 | (long)'i' << 40 | (long)'n' << 32, + (long)'i' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, + (long)'k' << 56 | (long)'a' << 48 | (long)'p' << 40 | (long)'p' << 32 | (long)'a' << 24, + (long)'l' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32, + (long)'l' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'b' << 32 | (long)'d' << 24 | (long)'a' << 16, + (long)'l' << 56 | (long)'a' << 48 | (long)'n' << 40 | (long)'g' << 32, + (long)'l' << 56 | (long)'a' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24, + (long)'l' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32, + (long)'l' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'i' << 32 | (long)'l' << 24, + (long)'l' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24, + (long)'l' << 56 | (long)'e' << 48, + (long)'l' << 56 | (long)'f' << 48 | (long)'l' << 40 | (long)'o' << 32 | (long)'o' << 24 | (long)'r' << 16, + (long)'l' << 56 | (long)'o' << 48 | (long)'w' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'t' << 16, + (long)'l' << 56 | (long)'o' << 48 | (long)'z' << 40, + (long)'l' << 56 | (long)'r' << 48 | (long)'m' << 40, + (long)'l' << 56 | (long)'s' << 48 | (long)'a' << 40 | (long)'q' << 32 | (long)'u' << 24 | (long)'o' << 16, + (long)'l' << 56 | (long)'s' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24, + (long)'l' << 56 | (long)'t' << 48, + (long)'m' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'r' << 32, + (long)'m' << 56 | (long)'d' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'h' << 24, + (long)'m' << 56 | (long)'i' << 48 | (long)'c' << 40 | (long)'r' << 32 | (long)'o' << 24, + (long)'m' << 56 | (long)'i' << 48 | (long)'d' << 40 | (long)'d' << 32 | (long)'o' << 24 | (long)'t' << 16, + (long)'m' << 56 | (long)'i' << 48 | (long)'n' << 40 | (long)'u' << 32 | (long)'s' << 24, + (long)'m' << 56 | (long)'u' << 48, + (long)'n' << 56 | (long)'a' << 48 | (long)'b' << 40 | (long)'l' << 32 | (long)'a' << 24, + (long)'n' << 56 | (long)'b' << 48 | (long)'s' << 40 | (long)'p' << 32, + (long)'n' << 56 | (long)'d' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'h' << 24, + (long)'n' << 56 | (long)'e' << 48, + (long)'n' << 56 | (long)'i' << 48, + (long)'n' << 56 | (long)'o' << 48 | (long)'t' << 40, + (long)'n' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'i' << 32 | (long)'n' << 24, + (long)'n' << 56 | (long)'s' << 48 | (long)'u' << 40 | (long)'b' << 32, + (long)'n' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16, + (long)'n' << 56 | (long)'u' << 48, + (long)'o' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, + (long)'o' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, + (long)'o' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24, + (long)'o' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, + (long)'o' << 56 | (long)'l' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'e' << 24, + (long)'o' << 56 | (long)'m' << 48 | (long)'e' << 40 | (long)'g' << 32 | (long)'a' << 24, + (long)'o' << 56 | (long)'m' << 48 | (long)'i' << 40 | (long)'c' << 32 | (long)'r' << 24 | (long)'o' << 16 | (long)'n' << 8, + (long)'o' << 56 | (long)'p' << 48 | (long)'l' << 40 | (long)'u' << 32 | (long)'s' << 24, + (long)'o' << 56 | (long)'r' << 48, + (long)'o' << 56 | (long)'r' << 48 | (long)'d' << 40 | (long)'f' << 32, + (long)'o' << 56 | (long)'r' << 48 | (long)'d' << 40 | (long)'m' << 32, + (long)'o' << 56 | (long)'s' << 48 | (long)'l' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'h' << 16, + (long)'o' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16, + (long)'o' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24 | (long)'s' << 16, + (long)'o' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, + (long)'p' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'a' << 32, + (long)'p' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'t' << 32, + (long)'p' << 56 | (long)'e' << 48 | (long)'r' << 40 | (long)'m' << 32 | (long)'i' << 24 | (long)'l' << 16, + (long)'p' << 56 | (long)'e' << 48 | (long)'r' << 40 | (long)'p' << 32, + (long)'p' << 56 | (long)'h' << 48 | (long)'i' << 40, + (long)'p' << 56 | (long)'i' << 48, + (long)'p' << 56 | (long)'i' << 48 | (long)'v' << 40, + (long)'p' << 56 | (long)'l' << 48 | (long)'u' << 40 | (long)'s' << 32 | (long)'m' << 24 | (long)'n' << 16, + (long)'p' << 56 | (long)'o' << 48 | (long)'u' << 40 | (long)'n' << 32 | (long)'d' << 24, + (long)'p' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24, + (long)'p' << 56 | (long)'r' << 48 | (long)'o' << 40 | (long)'d' << 32, + (long)'p' << 56 | (long)'r' << 48 | (long)'o' << 40 | (long)'p' << 32, + (long)'p' << 56 | (long)'s' << 48 | (long)'i' << 40, + (long)'q' << 56 | (long)'u' << 48 | (long)'o' << 40 | (long)'t' << 32, + (long)'r' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32, + (long)'r' << 56 | (long)'a' << 48 | (long)'d' << 40 | (long)'i' << 32 | (long)'c' << 24, + (long)'r' << 56 | (long)'a' << 48 | (long)'n' << 40 | (long)'g' << 32, + (long)'r' << 56 | (long)'a' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24, + (long)'r' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32, + (long)'r' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'i' << 32 | (long)'l' << 24, + (long)'r' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24, + (long)'r' << 56 | (long)'e' << 48 | (long)'a' << 40 | (long)'l' << 32, + (long)'r' << 56 | (long)'e' << 48 | (long)'g' << 40, + (long)'r' << 56 | (long)'f' << 48 | (long)'l' << 40 | (long)'o' << 32 | (long)'o' << 24 | (long)'r' << 16, + (long)'r' << 56 | (long)'h' << 48 | (long)'o' << 40, + (long)'r' << 56 | (long)'l' << 48 | (long)'m' << 40, + (long)'r' << 56 | (long)'s' << 48 | (long)'a' << 40 | (long)'q' << 32 | (long)'u' << 24 | (long)'o' << 16, + (long)'r' << 56 | (long)'s' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24, + (long)'s' << 56 | (long)'b' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24, + (long)'s' << 56 | (long)'c' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'o' << 24 | (long)'n' << 16, + (long)'s' << 56 | (long)'d' << 48 | (long)'o' << 40 | (long)'t' << 32, + (long)'s' << 56 | (long)'e' << 48 | (long)'c' << 40 | (long)'t' << 32, + (long)'s' << 56 | (long)'h' << 48 | (long)'y' << 40, + (long)'s' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24, + (long)'s' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24 | (long)'f' << 16, + (long)'s' << 56 | (long)'i' << 48 | (long)'m' << 40, + (long)'s' << 56 | (long)'p' << 48 | (long)'a' << 40 | (long)'d' << 32 | (long)'e' << 24 | (long)'s' << 16, + (long)'s' << 56 | (long)'u' << 48 | (long)'b' << 40, + (long)'s' << 56 | (long)'u' << 48 | (long)'b' << 40 | (long)'e' << 32, + (long)'s' << 56 | (long)'u' << 48 | (long)'m' << 40, + (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40, + (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'1' << 32, + (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'2' << 32, + (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'3' << 32, + (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'e' << 32, + (long)'s' << 56 | (long)'z' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24, + (long)'t' << 56 | (long)'a' << 48 | (long)'u' << 40, + (long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'r' << 32 | (long)'e' << 24 | (long)'4' << 16, + (long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24, + (long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24 | (long)'s' << 16 | (long)'y' << 8 | (long)'m' << 0, + (long)'t' << 56 | (long)'h' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'s' << 24 | (long)'p' << 16, + (long)'t' << 56 | (long)'h' << 48 | (long)'o' << 40 | (long)'r' << 32 | (long)'n' << 24, + (long)'t' << 56 | (long)'i' << 48 | (long)'l' << 40 | (long)'d' << 32 | (long)'e' << 24, + (long)'t' << 56 | (long)'i' << 48 | (long)'m' << 40 | (long)'e' << 32 | (long)'s' << 24, + (long)'t' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'d' << 32 | (long)'e' << 24, + (long)'u' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32, + (long)'u' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, + (long)'u' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32, + (long)'u' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, + (long)'u' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, + (long)'u' << 56 | (long)'m' << 48 | (long)'l' << 40, + (long)'u' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'h' << 24, + (long)'u' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8, + (long)'u' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, + (long)'w' << 56 | (long)'e' << 48 | (long)'i' << 40 | (long)'e' << 32 | (long)'r' << 24 | (long)'p' << 16, + (long)'x' << 56 | (long)'i' << 48, + (long)'y' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, + (long)'y' << 56 | (long)'e' << 48 | (long)'n' << 40, + (long)'y' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, + (long)'z' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32, + (long)'z' << 56 | (long)'w' << 48 | (long)'j' << 40, + (long)'z' << 56 | (long)'w' << 48 | (long)'n' << 40 | (long)'j' << 32 + }; + + static readonly char[] entities_values = new char[] { + '\u00C6', + '\u00C1', + '\u00C2', + '\u00C0', + '\u0391', + '\u00C5', + '\u00C3', + '\u00C4', + '\u0392', + '\u00C7', + '\u03A7', + '\u2021', + '\u0394', + '\u00D0', + '\u00C9', + '\u00CA', + '\u00C8', + '\u0395', + '\u0397', + '\u00CB', + '\u0393', + '\u00CD', + '\u00CE', + '\u00CC', + '\u0399', + '\u00CF', + '\u039A', + '\u039B', + '\u039C', + '\u00D1', + '\u039D', + '\u0152', + '\u00D3', + '\u00D4', + '\u00D2', + '\u03A9', + '\u039F', + '\u00D8', + '\u00D5', + '\u00D6', + '\u03A6', + '\u03A0', + '\u2033', + '\u03A8', + '\u03A1', + '\u0160', + '\u03A3', + '\u00DE', + '\u03A4', + '\u0398', + '\u00DA', + '\u00DB', + '\u00D9', + '\u03A5', + '\u00DC', + '\u039E', + '\u00DD', + '\u0178', + '\u0396', + '\u00E1', + '\u00E2', + '\u00B4', + '\u00E6', + '\u00E0', + '\u2135', + '\u03B1', + '\u0026', + '\u2227', + '\u2220', + '\u0027', + '\u00E5', + '\u2248', + '\u00E3', + '\u00E4', + '\u201E', + '\u03B2', + '\u00A6', + '\u2022', + '\u2229', + '\u00E7', + '\u00B8', + '\u00A2', + '\u03C7', + '\u02C6', + '\u2663', + '\u2245', + '\u00A9', + '\u21B5', + '\u222A', + '\u00A4', + '\u21D3', + '\u2020', + '\u2193', + '\u00B0', + '\u03B4', + '\u2666', + '\u00F7', + '\u00E9', + '\u00EA', + '\u00E8', + '\u2205', + '\u2003', + '\u2002', + '\u03B5', + '\u2261', + '\u03B7', + '\u00F0', + '\u00EB', + '\u20AC', + '\u2203', + '\u0192', + '\u2200', + '\u00BD', + '\u00BC', + '\u00BE', + '\u2044', + '\u03B3', + '\u2265', + '\u003E', + '\u21D4', + '\u2194', + '\u2665', + '\u2026', + '\u00ED', + '\u00EE', + '\u00A1', + '\u00EC', + '\u2111', + '\u221E', + '\u222B', + '\u03B9', + '\u00BF', + '\u2208', + '\u00EF', + '\u03BA', + '\u21D0', + '\u03BB', + '\u2329', + '\u00AB', + '\u2190', + '\u2308', + '\u201C', + '\u2264', + '\u230A', + '\u2217', + '\u25CA', + '\u200E', + '\u2039', + '\u2018', + '\u003C', + '\u00AF', + '\u2014', + '\u00B5', + '\u00B7', + '\u2212', + '\u03BC', + '\u2207', + '\u00A0', + '\u2013', + '\u2260', + '\u220B', + '\u00AC', + '\u2209', + '\u2284', + '\u00F1', + '\u03BD', + '\u00F3', + '\u00F4', + '\u0153', + '\u00F2', + '\u203E', + '\u03C9', + '\u03BF', + '\u2295', + '\u2228', + '\u00AA', + '\u00BA', + '\u00F8', + '\u00F5', + '\u2297', + '\u00F6', + '\u00B6', + '\u2202', + '\u2030', + '\u22A5', + '\u03C6', + '\u03C0', + '\u03D6', + '\u00B1', + '\u00A3', + '\u2032', + '\u220F', + '\u221D', + '\u03C8', + '\u0022', + '\u21D2', + '\u221A', + '\u232A', + '\u00BB', + '\u2192', + '\u2309', + '\u201D', + '\u211C', + '\u00AE', + '\u230B', + '\u03C1', + '\u200F', + '\u203A', + '\u2019', + '\u201A', + '\u0161', + '\u22C5', + '\u00A7', + '\u00AD', + '\u03C3', + '\u03C2', + '\u223C', + '\u2660', + '\u2282', + '\u2286', + '\u2211', + '\u2283', + '\u00B9', + '\u00B2', + '\u00B3', + '\u2287', + '\u00DF', + '\u03C4', + '\u2234', + '\u03B8', + '\u03D1', + '\u2009', + '\u00FE', + '\u02DC', + '\u00D7', + '\u2122', + '\u21D1', + '\u00FA', + '\u2191', + '\u00FB', + '\u00F9', + '\u00A8', + '\u03D2', + '\u03C5', + '\u00FC', + '\u2118', + '\u03BE', + '\u00FD', + '\u00A5', + '\u00FF', + '\u03B6', + '\u200D', + '\u200C' + }; + + #region Methods + + static void WriteCharBytes(IList buf, char ch, Encoding e) + { + if (ch > 255) + { + foreach (byte b in e.GetBytes(new char[] { ch })) + buf.Add(b); + } + else + buf.Add((byte)ch); + } + + public static string UrlDecode(string s, Encoding e) + { + if (null == s) + return null; + + if (s.IndexOf('%') == -1 && s.IndexOf('+') == -1) + return s; + + if (e == null) + e = Encoding.UTF8; + + long len = s.Length; + var bytes = new List(); + int xchar; + char ch; + + for (int i = 0; i < len; i++) + { + ch = s[i]; + if (ch == '%' && i + 2 < len && s[i + 1] != '%') + { + if (s[i + 1] == 'u' && i + 5 < len) + { + // unicode hex sequence + xchar = GetChar(s, i + 2, 4); + if (xchar != -1) + { + WriteCharBytes(bytes, (char)xchar, e); + i += 5; + } + else + WriteCharBytes(bytes, '%', e); + } + else if ((xchar = GetChar(s, i + 1, 2)) != -1) + { + WriteCharBytes(bytes, (char)xchar, e); + i += 2; + } + else + { + WriteCharBytes(bytes, '%', e); + } + continue; + } + + if (ch == '+') + WriteCharBytes(bytes, ' ', e); + else + WriteCharBytes(bytes, ch, e); + } + + byte[] buf = bytes.ToArray(); + bytes = null; + return e.GetString(buf); + + } + + static int GetInt(byte b) + { + char c = (char)b; + if (c >= '0' && c <= '9') + return c - '0'; + + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + + return -1; + } + + static int GetChar(string str, int offset, int length) + { + int val = 0; + int end = length + offset; + for (int i = offset; i < end; i++) + { + char c = str[i]; + if (c > 127) + return -1; + + int current = GetInt((byte)c); + if (current == -1) + return -1; + val = (val << 4) + current; + } + + return val; + } + + static bool TryConvertKeyToEntity(string key, out char value) + { + var token = CalculateKeyValue(key); + if (token == 0) + { + value = '\0'; + return false; + } + + var idx = Array.BinarySearch(entities, token); + if (idx < 0) + { + value = '\0'; + return false; + } + + value = entities_values[idx]; + return true; + } + + static long CalculateKeyValue(string s) + { + if (s.Length > 8) + return 0; + + long key = 0; + for (int i = 0; i < s.Length; ++i) + { + long ch = s[i]; + if (ch > 'z' || ch < '0') + return 0; + + key |= ch << ((7 - i) * 8); + } + + return key; + } + + /// + /// Decodes an HTML-encoded string and returns the decoded string. + /// + /// The HTML string to decode. + /// The decoded text. + public static string HtmlDecode(string s) + { + if (s == null) + throw new ArgumentNullException("s"); + + if (s.IndexOf('&') == -1) + return s; + + StringBuilder entity = new StringBuilder(); + StringBuilder output = new StringBuilder(); + int len = s.Length; + // 0 -> nothing, + // 1 -> right after '&' + // 2 -> between '&' and ';' but no '#' + // 3 -> '#' found after '&' and getting numbers + int state = 0; + int number = 0; + int digit_start = 0; + bool hex_number = false; + + for (int i = 0; i < len; i++) + { + char c = s[i]; + if (state == 0) + { + if (c == '&') + { + entity.Append(c); + state = 1; + } + else + { + output.Append(c); + } + continue; + } + + if (c == '&') + { + state = 1; + if (digit_start > 0) + { + entity.Append(s, digit_start, i - digit_start); + digit_start = 0; + } + + output.Append(entity.ToString()); + entity.Length = 0; + entity.Append('&'); + continue; + } + + switch (state) + { + case 1: + if (c == ';') + { + state = 0; + output.Append(entity.ToString()); + output.Append(c); + entity.Length = 0; + break; + } + + number = 0; + hex_number = false; + if (c != '#') + { + state = 2; + } + else + { + state = 3; + } + entity.Append(c); + + break; + case 2: + entity.Append(c); + if (c == ';') + { + string key = entity.ToString(); + state = 0; + entity.Length = 0; + + if (key.Length > 1) + { + var skey = key.Substring(1, key.Length - 2); + if (TryConvertKeyToEntity(skey, out c)) + { + output.Append(c); + break; + } + } + + output.Append(key); + } + + break; + case 3: + if (c == ';') + { + if (number < 0x10000) + { + output.Append((char)number); + } + else + { + output.Append((char)(0xd800 + ((number - 0x10000) >> 10))); + output.Append((char)(0xdc00 + ((number - 0x10000) & 0x3ff))); + } + state = 0; + entity.Length = 0; + digit_start = 0; + break; + } + + if (c == 'x' || c == 'X' && !hex_number) + { + digit_start = i; + hex_number = true; + break; + } + + if (Char.IsDigit(c)) + { + if (digit_start == 0) + digit_start = i; + + number = number * (hex_number ? 16 : 10) + ((int)c - '0'); + break; + } + + if (hex_number) + { + if (c >= 'a' && c <= 'f') + { + number = number * 16 + 10 + ((int)c - 'a'); + break; + } + if (c >= 'A' && c <= 'F') + { + number = number * 16 + 10 + ((int)c - 'A'); + break; + } + } + + state = 2; + if (digit_start > 0) + { + entity.Append(s, digit_start, i - digit_start); + digit_start = 0; + } + + entity.Append(c); + break; + } + } + + if (entity.Length > 0) + { + output.Append(entity); + } + else if (digit_start > 0) + { + output.Append(s, digit_start, s.Length - digit_start); + } + return output.ToString(); + } + + public static NameValueCollection ParseQueryString(string query) + { + return ParseQueryString(query, Encoding.UTF8); + } + + public static NameValueCollection ParseQueryString(string query, Encoding encoding) + { + if (query == null) + throw new ArgumentNullException("query"); + if (encoding == null) + throw new ArgumentNullException("encoding"); + if (query.Length == 0 || (query.Length == 1 && query[0] == '?')) + return new NameValueCollection(); + if (query[0] == '?') + query = query.Substring(1); + + NameValueCollection result = new HttpQSCollection(); + ParseQueryString(query, encoding, result); + return result; + } + + internal static void ParseQueryString(string query, Encoding encoding, NameValueCollection result) + { + if (query.Length == 0) + return; + + string decoded = HtmlDecode(query); + int decodedLength = decoded.Length; + int namePos = 0; + bool first = true; + while (namePos <= decodedLength) + { + int valuePos = -1, valueEnd = -1; + for (int q = namePos; q < decodedLength; q++) + { + if (valuePos == -1 && decoded[q] == '=') + { + valuePos = q + 1; + } + else if (decoded[q] == '&') + { + valueEnd = q; + break; + } + } + + if (first) + { + first = false; + if (decoded[namePos] == '?') + namePos++; + } + + string name, value; + if (valuePos == -1) + { + name = null; + valuePos = namePos; + } + else + { + name = UrlDecode(decoded.Substring(namePos, valuePos - namePos - 1), encoding); + } + if (valueEnd < 0) + { + namePos = -1; + valueEnd = decoded.Length; + } + else + { + namePos = valueEnd + 1; + } + value = UrlDecode(decoded.Substring(valuePos, valueEnd - valuePos), encoding); + + result.Add(name, value); + if (namePos == -1) + break; + } + } + #endregion // Methods + } +} diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs index 54c27cf0a..b3fbd2d1d 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Text; +using System.Web; using Funq; using MediaBrowser.Model.Logging; using ServiceStack; @@ -236,7 +237,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp private NameValueCollectionWrapper queryString; public INameValueCollection QueryString { - get { return queryString ?? (queryString = new NameValueCollectionWrapper(HttpUtility.ParseQueryString(request.Url.Query))); } + get { return queryString ?? (queryString = new NameValueCollectionWrapper(MyHttpUtility.ParseQueryString(request.Url.Query))); } } private NameValueCollectionWrapper formData; diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 844266534..c93875811 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -62,9 +62,9 @@ ..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll - + False - ..\packages\SocketHttpListener.1.0.0.17\lib\net45\SocketHttpListener.dll + ..\packages\SocketHttpListener.1.0.0.19\lib\net45\SocketHttpListener.dll @@ -163,6 +163,7 @@ + diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 1a3b5028f..a1e97ddc8 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -6,5 +6,5 @@ - + \ No newline at end of file -- cgit v1.2.3 From b46ef16ba838dafbd79f6e9ffbea37afa2104b0b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 28 Dec 2015 22:39:38 -0500 Subject: update local address detection --- MediaBrowser.Api/System/SystemService.cs | 11 ++++ .../Networking/BaseNetworkManager.cs | 4 +- MediaBrowser.Controller/IServerApplicationHost.cs | 4 +- MediaBrowser.Controller/Net/IHttpServer.cs | 6 -- MediaBrowser.Dlna/Main/DlnaEntryPoint.cs | 44 +++++++------ MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs | 7 ++- .../HttpServer/HttpListenerHost.cs | 38 ------------ .../ApplicationHost.cs | 72 +++++++++++++++------- 8 files changed, 95 insertions(+), 91 deletions(-) (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs index a95fcb542..4faff8780 100644 --- a/MediaBrowser.Api/System/SystemService.cs +++ b/MediaBrowser.Api/System/SystemService.cs @@ -32,6 +32,12 @@ namespace MediaBrowser.Api.System } + [Route("/System/Ping", "POST")] + public class PingSystem : IReturnVoid + { + + } + /// /// Class RestartApplication /// @@ -117,6 +123,11 @@ namespace MediaBrowser.Api.System return ToOptimizedResult(result); } + public void Post(PingSystem request) + { + + } + public object Get(GetServerLogs request) { List files; diff --git a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs index 789cde5fc..9b278b889 100644 --- a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs +++ b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs @@ -69,7 +69,7 @@ namespace MediaBrowser.Common.Implementations.Networking list.AddRange(GetLocalIpAddressesFallback()); } - return list.Where(i => !IPAddress.IsLoopback(i)).Where(FilterIpAddress).DistinctBy(i => i.ToString()); + return list.Where(FilterIpAddress).DistinctBy(i => i.ToString()); } private bool FilterIpAddress(IPAddress address) @@ -232,7 +232,7 @@ namespace MediaBrowser.Common.Implementations.Networking return properties.UnicastAddresses .Select(i => i.Address) - .Where(i => i.AddressFamily == AddressFamily.InterNetwork && !IPAddress.IsLoopback(i)) + .Where(i => i.AddressFamily == AddressFamily.InterNetwork) .ToList(); } catch (Exception ex) diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 1b842a5f6..fb843d191 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -1,6 +1,8 @@ using MediaBrowser.Common; using MediaBrowser.Model.System; using System; +using System.Collections.Generic; +using System.Net; namespace MediaBrowser.Controller { @@ -63,7 +65,7 @@ namespace MediaBrowser.Controller /// Gets the local ip address. /// /// The local ip address. - string LocalIpAddress { get; } + List LocalIpAddresses { get; } /// /// Gets the local API URL. diff --git a/MediaBrowser.Controller/Net/IHttpServer.cs b/MediaBrowser.Controller/Net/IHttpServer.cs index 91da5fab2..97c5dd31b 100644 --- a/MediaBrowser.Controller/Net/IHttpServer.cs +++ b/MediaBrowser.Controller/Net/IHttpServer.cs @@ -28,12 +28,6 @@ namespace MediaBrowser.Controller.Net /// the ssl certificate localtion on the file system. void StartServer(IEnumerable urlPrefixes, string certificatePath); - /// - /// Gets the local end points. - /// - /// The local end points. - IEnumerable LocalEndPoints { get; } - /// /// Stops this instance. /// diff --git a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs index 37cca43eb..d79ef9eaf 100644 --- a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs +++ b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs @@ -43,19 +43,19 @@ namespace MediaBrowser.Dlna.Main private readonly List _registeredServerIds = new List(); private bool _dlnaServerStarted; - public DlnaEntryPoint(IServerConfigurationManager config, - ILogManager logManager, - IServerApplicationHost appHost, - INetworkManager network, - ISessionManager sessionManager, - IHttpClient httpClient, - ILibraryManager libraryManager, - IUserManager userManager, - IDlnaManager dlnaManager, - IImageProcessor imageProcessor, - IUserDataManager userDataManager, - ILocalizationManager localization, - IMediaSourceManager mediaSourceManager, + public DlnaEntryPoint(IServerConfigurationManager config, + ILogManager logManager, + IServerApplicationHost appHost, + INetworkManager network, + ISessionManager sessionManager, + IHttpClient httpClient, + ILibraryManager libraryManager, + IUserManager userManager, + IDlnaManager dlnaManager, + IImageProcessor imageProcessor, + IUserDataManager userDataManager, + ILocalizationManager localization, + IMediaSourceManager mediaSourceManager, ISsdpHandler ssdpHandler, IDeviceDiscovery deviceDiscovery) { _config = config; @@ -148,14 +148,20 @@ namespace MediaBrowser.Dlna.Main private void RegisterServerEndpoints() { - foreach (var address in _network.GetLocalIpAddresses()) + foreach (var address in _appHost.LocalIpAddresses) { - var addressString = address.ToString (); - var guid = addressString.GetMD5(); + //if (IPAddress.IsLoopback(address)) + //{ + // // Should we allow this? + // continue; + //} + + var addressString = address.ToString(); + var guid = addressString.GetMD5(); var descriptorURI = "/dlna/" + guid.ToString("N") + "/description.xml"; - var uri = new Uri(_appHost.GetLocalApiUrl(addressString) + descriptorURI); + var uri = new Uri(_appHost.GetLocalApiUrl(addressString) + descriptorURI); var services = new List { @@ -166,8 +172,8 @@ namespace MediaBrowser.Dlna.Main "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1", "uuid:" + guid.ToString("N") }; - - _ssdpHandler.RegisterNotification(guid, uri, address, services); + + _ssdpHandler.RegisterNotification(guid, uri, address, services); _registeredServerIds.Add(guid.ToString("N")); } diff --git a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs index 457134913..279979550 100644 --- a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs +++ b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs @@ -110,8 +110,11 @@ namespace MediaBrowser.Dlna.Ssdp { if (e.LocalEndPoint == null) { - var ip = _appHost.LocalIpAddress; - e.LocalEndPoint = new IPEndPoint(IPAddress.Parse(ip), 0); + var ip = _appHost.LocalIpAddresses.FirstOrDefault(i => !IPAddress.IsLoopback(i)); + if (ip != null) + { + e.LocalEndPoint = new IPEndPoint(ip, 0); + } } if (e.LocalEndPoint != null) diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 847982976..0283c1f7a 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -40,33 +40,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer public event EventHandler WebSocketConnected; public event EventHandler WebSocketConnecting; - private readonly List _localEndpoints = new List(); - - private readonly ReaderWriterLockSlim _localEndpointLock = new ReaderWriterLockSlim(); - public string CertificatePath { get; private set; } private readonly IServerConfigurationManager _config; private readonly INetworkManager _networkManager; - /// - /// Gets the local end points. - /// - /// The local end points. - public IEnumerable LocalEndPoints - { - get - { - _localEndpointLock.EnterReadLock(); - - var list = _localEndpoints.ToList(); - - _localEndpointLock.ExitReadLock(); - - return list; - } - } - public HttpListenerHost(IApplicationHost applicationHost, ILogManager logManager, IServerConfigurationManager config, @@ -178,22 +156,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer private void OnRequestReceived(string localEndPoint) { - var ignore = _networkManager.IsInPrivateAddressSpace(localEndPoint); - - if (ignore) - { - return; - } - - if (_localEndpointLock.TryEnterWriteLock(100)) - { - var list = _localEndpoints; - - list.Remove(localEndPoint); - list.Insert(0, localEndPoint); - - _localEndpointLock.ExitWriteLock(); - } } /// diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 2bdb138d7..a4760f3af 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -91,10 +91,12 @@ using MediaBrowser.Server.Startup.Common.Migrations; using MediaBrowser.WebDashboard.Api; using MediaBrowser.XbmcMetadata.Providers; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Net; using System.Reflection; using System.Threading; using System.Threading.Tasks; @@ -207,6 +209,7 @@ namespace MediaBrowser.Server.Startup.Common private readonly string _remotePackageName; internal INativeApp NativeApp { get; set; } + private Timer _ipAddressCacheTimer; /// /// Initializes a new instance of the class. @@ -230,6 +233,8 @@ namespace MediaBrowser.Server.Startup.Common NativeApp = nativeApp; SetBaseExceptionMessage(); + + _ipAddressCacheTimer = new Timer(OnCacheClearTimerFired, null, TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3)); } private Version _version; @@ -1116,14 +1121,14 @@ namespace MediaBrowser.Server.Startup.Common try { // Return the first matched address, if found, or the first known local address - var address = LocalIpAddress; + var address = LocalIpAddresses.FirstOrDefault(i => !IPAddress.IsLoopback(i)); - if (!string.IsNullOrWhiteSpace(address)) + if (address != null) { - address = GetLocalApiUrl(address); + return GetLocalApiUrl(address.ToString()); } - return address; + return null; } catch (Exception ex) { @@ -1141,39 +1146,60 @@ namespace MediaBrowser.Server.Startup.Common HttpPort.ToString(CultureInfo.InvariantCulture)); } - public string LocalIpAddress + public List LocalIpAddresses { get { - return HttpServerIpAddresses.FirstOrDefault(); + var localAddresses = NetworkManager.GetLocalIpAddresses() + .Where(IsIpAddressValid) + .ToList(); + + return localAddresses; } } - private IEnumerable HttpServerIpAddresses + private readonly ConcurrentDictionary _validAddressResults = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + private bool IsIpAddressValid(IPAddress address) { - get + if (IPAddress.IsLoopback(address)) { - var localAddresses = NetworkManager.GetLocalIpAddresses() - .Select(i => i.ToString()) - .ToList(); + return true; + } - var httpServerAddresses = HttpServer.LocalEndPoints - .Select(i => i.Split(':').FirstOrDefault()) - .Where(i => !string.IsNullOrEmpty(i)) - .ToList(); + var apiUrl = GetLocalApiUrl(address.ToString()); + apiUrl += "/system/ping"; - // Cross-check the local ip addresses with addresses that have been received on with the http server - var matchedAddresses = httpServerAddresses - .Where(i => localAddresses.Contains(i, StringComparer.OrdinalIgnoreCase)) - .ToList(); + bool cachedResult; + if (_validAddressResults.TryGetValue(apiUrl, out cachedResult)) + { + return cachedResult; + } - if (matchedAddresses.Count == 0) + try + { + using (var response = HttpClient.SendAsync(new HttpRequestOptions { - return localAddresses; - } + Url = apiUrl, + BufferContent = false, + LogErrorResponseBody = false, + LogErrors = false - return matchedAddresses; + }, "POST").Result) + { + _validAddressResults.AddOrUpdate(apiUrl, true, (k, v) => true); + return true; + } } + catch + { + _validAddressResults.AddOrUpdate(apiUrl, true, (k, v) => false); + return false; + } + } + + private void OnCacheClearTimerFired(object state) + { + _validAddressResults.Clear(); } public string FriendlyName -- cgit v1.2.3 From 31f137500d3f8fa9c87d3137264018937b09c0d0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 14 Jan 2016 16:41:23 -0500 Subject: xbox 360 dlna fixes --- MediaBrowser.Dlna/Profiles/Xbox360Profile.cs | 3 +-- MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml | 4 ++-- MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs | 12 ++++++++---- .../HttpServer/ResponseFilter.cs | 5 ++++- 4 files changed, 15 insertions(+), 9 deletions(-) (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs b/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs index 431807aed..64b728721 100644 --- a/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs +++ b/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.Dlna.Profiles Name = "Xbox 360"; // Required according to above - ModelName = "Windows Media Connect"; + ModelName = "Windows Media Player Sharing"; ModelNumber = "12.0"; @@ -25,7 +25,6 @@ namespace MediaBrowser.Dlna.Profiles ManufacturerUrl = "http://www.microsoft.com"; XDlnaDoc = "DMS-1.50"; ModelDescription = "Emby : UPnP Media Server"; - ModelNumber = "001"; TimelineOffsetSeconds = 40; RequiresPlainFolders = true; diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml index bfe1fceea..35799f313 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml @@ -11,9 +11,9 @@ ${HostName}: 1 Microsoft Corporation http://www.microsoft.com - Windows Media Connect + Windows Media Player Sharing Emby : UPnP Media Server - 001 + 12.0 http://go.microsoft.com/fwlink/?LinkId=105926 false false diff --git a/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs b/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs index 649612e1e..63ea59d53 100644 --- a/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs +++ b/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs @@ -92,10 +92,7 @@ namespace MediaBrowser.Dlna.Server builder.Append(""); AppendDeviceProperties(builder); - if (_profile.EnableDlnaProtocol) - { - AppendIconList(builder); - } + AppendIconList(builder); AppendServiceList(builder); builder.Append(""); } @@ -111,6 +108,13 @@ namespace MediaBrowser.Dlna.Server builder.Append("M-DMS-1.50"); builder.Append("" + SecurityElement.Escape(_profile.XDlnaDoc ?? string.Empty) + ""); } + else + { + builder.Append("" + SecurityElement.Escape(_profile.XDlnaCap ?? string.Empty) + ""); + + builder.Append("" + SecurityElement.Escape(_profile.XDlnaDoc ?? string.Empty) + ""); + builder.Append("M-DMS-1.50"); + } builder.Append("" + SecurityElement.Escape(GetFriendlyName()) + ""); builder.Append("" + SecurityElement.Escape(_profile.Manufacturer ?? string.Empty) + ""); diff --git a/MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs b/MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs index 0da34efc6..4ef9d5277 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs @@ -58,7 +58,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer if (hasOptions != null) { - hasOptions.Options["Server"] = "Mono-HTTPAPI/1.1"; + if (!hasOptions.Options.ContainsKey("Server")) + { + hasOptions.Options["Server"] = "Mono-HTTPAPI/1.1, UPnP/1.0 DLNADOC/1.50"; + } // Content length has to be explicitly set on on HttpListenerResponse or it won't be happy string contentLength; -- cgit v1.2.3 From 2e78362db2497ca36bf3b1835dbd57f938c0f04d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 19 Jan 2016 22:02:26 -0500 Subject: normalize remote ip --- .../HttpServer/SocketSharp/WebSocketSharpRequest.cs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs index b3fbd2d1d..5df37118d 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs @@ -136,11 +136,27 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { return remoteIp ?? (remoteIp = XForwardedFor ?? - (XRealIp ?? - ((request.RemoteEndPoint != null) ? request.RemoteEndPoint.Address.ToString() : null))); + (NormalizeIp(XRealIp) ?? + ((request.RemoteEndPoint != null) ? NormalizeIp(request.RemoteEndPoint.Address.ToString()) : null))); } } + private string NormalizeIp(string ip) + { + if (!string.IsNullOrWhiteSpace(ip)) + { + // Handle ipv4 mapped to ipv6 + const string srch = "::ffff:"; + var index = ip.IndexOf(srch, StringComparison.OrdinalIgnoreCase); + if (index == 0) + { + ip = ip.Substring(srch.Length); + } + } + + return ip; + } + public bool IsSecureConnection { get { return request.IsSecureConnection || XForwardedProtocol == "https"; } -- cgit v1.2.3 From 984274964365c3c0435d7c885e00dcf261fa061e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 14:45:52 -0500 Subject: trim logging --- .../TV/MissingEpisodeProvider.cs | 2 +- .../HttpServer/HttpListenerHost.cs | 6 +-- .../SocketSharp/WebSocketSharpListener.cs | 56 ++++++++++++---------- 3 files changed, 34 insertions(+), 30 deletions(-) (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index 19eda4905..9c0e0b873 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -53,7 +53,7 @@ namespace MediaBrowser.Providers.TV } catch (DirectoryNotFoundException) { - _logger.Warn("Series files missing for series id {0}", seriesGroup.Key); + //_logger.Warn("Series files missing for series id {0}", seriesGroup.Key); } catch (Exception ex) { diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 0283c1f7a..6a23a8497 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -154,10 +154,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer return this; } - private void OnRequestReceived(string localEndPoint) - { - } - /// /// Starts the Web Service /// @@ -177,7 +173,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer private IHttpListener GetListener() { - return new WebSocketSharpListener(_logger, OnRequestReceived, CertificatePath); + return new WebSocketSharpListener(_logger, CertificatePath); } private void OnWebSocketConnecting(WebSocketConnectingEventArgs args) diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs index 9f80c8ac9..a91b1e3ed 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs @@ -7,6 +7,7 @@ using ServiceStack.Web; using SocketHttpListener.Net; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -18,14 +19,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp private HttpListener _listener; private readonly ILogger _logger; - private readonly Action _endpointListener; private readonly string _certificatePath; - public WebSocketSharpListener(ILogger logger, Action endpointListener, - string certificatePath) + public WebSocketSharpListener(ILogger logger, string certificatePath) { _logger = logger; - _endpointListener = endpointListener; _certificatePath = certificatePath; } @@ -80,7 +78,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { var request = context.Request; - LogHttpRequest(request); + LogRequest(_logger, request); if (request.IsWebSocketRequest) { @@ -96,24 +94,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp return RequestHandler(httpReq, request.Url); } - /// - /// Logs the HTTP request. - /// - /// The request. - private void LogHttpRequest(HttpListenerRequest request) - { - var endpoint = request.LocalEndPoint; - - if (endpoint != null) - { - var address = endpoint.ToString(); - - _endpointListener(address); - } - - LogRequest(_logger, request); - } - private void ProcessWebSocketRequest(HttpListenerContext ctx) { try @@ -183,7 +163,35 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp /// The request. private static void LogRequest(ILogger logger, HttpListenerRequest request) { - logger.Info("{0} {1}. UserAgent: {2}", (request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod), request.Url, request.UserAgent ?? string.Empty); + var url = request.Url.ToString(); + var extension = Path.GetExtension(url); + + if (string.Equals(extension, ".js", StringComparison.OrdinalIgnoreCase)) + { + return; + } + if (string.Equals(extension, ".css", StringComparison.OrdinalIgnoreCase)) + { + return; + } + if (string.Equals(extension, ".woff", StringComparison.OrdinalIgnoreCase)) + { + return; + } + if (string.Equals(extension, ".woff2", StringComparison.OrdinalIgnoreCase)) + { + return; + } + if (string.Equals(extension, ".ttf", StringComparison.OrdinalIgnoreCase)) + { + return; + } + if (string.Equals(extension, ".html", StringComparison.OrdinalIgnoreCase)) + { + return; + } + + logger.Info("{0} {1}. UserAgent: {2}", (request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod), url, request.UserAgent ?? string.Empty); } private void HandleError(Exception ex, HttpListenerContext context) -- cgit v1.2.3 From 3b0b607836ad1ecd89579c72b019668bd4675a73 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 22:10:21 -0500 Subject: trim logging --- .../HttpServer/HttpListenerHost.cs | 34 ++++++++++++++++-- .../HttpServer/LoggerUtils.cs | 19 ++++++++++ .../SocketSharp/WebSocketSharpListener.cs | 42 ++-------------------- 3 files changed, 52 insertions(+), 43 deletions(-) (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 6a23a8497..8d8d7f6f7 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -256,6 +256,25 @@ namespace MediaBrowser.Server.Implementations.HttpServer } } + private readonly Dictionary _skipLogExtensions = new Dictionary(StringComparer.OrdinalIgnoreCase) + { + {".js", 0}, + {".css", 0}, + {".woff", 0}, + {".woff2", 0}, + {".ttf", 0}, + {".html", 0} + }; + + private bool EnableLogging(string url) + { + var parts = url.Split(new[] { '?' }, 2); + + var extension = Path.GetExtension(parts[0]); + + return string.IsNullOrWhiteSpace(extension) || !_skipLogExtensions.ContainsKey(extension); + } + /// /// Overridable method that can be used to implement a custom hnandler /// @@ -271,6 +290,14 @@ namespace MediaBrowser.Server.Implementations.HttpServer var operationName = httpReq.OperationName; var localPath = url.LocalPath; + var urlString = url.ToString(); + var enableLog = EnableLogging(urlString); + + if (enableLog) + { + LoggerUtils.LogRequest(_logger, urlString, httpReq.HttpMethod, httpReq.UserAgent); + } + if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase) || string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase)) { @@ -333,15 +360,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer task.ContinueWith(x => httpRes.Close(), TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.AttachedToParent); //Matches Exceptions handled in HttpListenerBase.InitTask() - var urlString = url.ToString(); - task.ContinueWith(x => { var statusCode = httpRes.StatusCode; var duration = DateTime.Now - date; - LoggerUtils.LogResponse(_logger, statusCode, urlString, remoteIp, duration); + if (enableLog) + { + LoggerUtils.LogResponse(_logger, statusCode, urlString, remoteIp, duration); + } }, TaskContinuationOptions.None); return task; diff --git a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs b/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs index fae702023..0b8caaa6e 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs @@ -1,11 +1,30 @@ using MediaBrowser.Model.Logging; using System; using System.Globalization; +using System.IO; +using SocketHttpListener.Net; namespace MediaBrowser.Server.Implementations.HttpServer { public static class LoggerUtils { + /// + /// Logs the request. + /// + /// The logger. + /// The request. + public static void LogRequest(ILogger logger, HttpListenerRequest request) + { + var url = request.Url.ToString(); + + logger.Info("{0} {1}. UserAgent: {2}", (request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod), url, request.UserAgent ?? string.Empty); + } + + public static void LogRequest(ILogger logger, string url, string method, string userAgent) + { + logger.Info("{0} {1}. UserAgent: {2}", ("HTTP " + method), url, userAgent ?? string.Empty); + } + /// /// Logs the response. /// diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs index a91b1e3ed..a029e0955 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs @@ -78,10 +78,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { var request = context.Request; - LogRequest(_logger, request); - if (request.IsWebSocketRequest) { + LoggerUtils.LogRequest(_logger, request); + ProcessWebSocketRequest(context); return Task.FromResult(true); } @@ -156,44 +156,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp return req; } - /// - /// Logs the request. - /// - /// The logger. - /// The request. - private static void LogRequest(ILogger logger, HttpListenerRequest request) - { - var url = request.Url.ToString(); - var extension = Path.GetExtension(url); - - if (string.Equals(extension, ".js", StringComparison.OrdinalIgnoreCase)) - { - return; - } - if (string.Equals(extension, ".css", StringComparison.OrdinalIgnoreCase)) - { - return; - } - if (string.Equals(extension, ".woff", StringComparison.OrdinalIgnoreCase)) - { - return; - } - if (string.Equals(extension, ".woff2", StringComparison.OrdinalIgnoreCase)) - { - return; - } - if (string.Equals(extension, ".ttf", StringComparison.OrdinalIgnoreCase)) - { - return; - } - if (string.Equals(extension, ".html", StringComparison.OrdinalIgnoreCase)) - { - return; - } - - logger.Info("{0} {1}. UserAgent: {2}", (request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod), url, request.UserAgent ?? string.Empty); - } - private void HandleError(Exception ex, HttpListenerContext context) { var httpReq = GetRequest(context); -- cgit v1.2.3 From 0474a225c4347e2eee86b66b123f44f63b3667d7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Jan 2016 13:35:37 -0500 Subject: fixes #1421 - LogRequest() in WebSocketSharpListener broken for Reports --- MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 8d8d7f6f7..038116703 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -290,7 +290,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer var operationName = httpReq.OperationName; var localPath = url.LocalPath; - var urlString = url.ToString(); + var urlString = url.OriginalString; var enableLog = EnableLogging(urlString); if (enableLog) -- cgit v1.2.3 From 96120099cb2a1d23e46fc32b2985cabd1fa2a84a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 1 Feb 2016 14:54:49 -0500 Subject: add message for db upgrade --- .../HttpServer/HttpListenerHost.cs | 17 ++++++++-- .../Localization/Core/core.json | 3 +- .../Localization/Core/en-US.json | 3 +- .../Persistence/CleanDatabaseScheduledTask.cs | 36 ++++++++++++++++++++-- .../Persistence/SqliteItemRepository.cs | 2 +- .../Migrations/DbMigration.cs | 4 ++- 6 files changed, 55 insertions(+), 10 deletions(-) (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 038116703..78d7a480e 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -268,13 +268,18 @@ namespace MediaBrowser.Server.Implementations.HttpServer private bool EnableLogging(string url) { - var parts = url.Split(new[] { '?' }, 2); - - var extension = Path.GetExtension(parts[0]); + var extension = GetExtension(url); return string.IsNullOrWhiteSpace(extension) || !_skipLogExtensions.ContainsKey(extension); } + private string GetExtension(string url) + { + var parts = url.Split(new[] { '?' }, 2); + + return Path.GetExtension(parts[0]); + } + /// /// Overridable method that can be used to implement a custom hnandler /// @@ -339,6 +344,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer { httpRes.Write(GlobalResponse); httpRes.ContentType = "text/plain"; + + if (!string.Equals(GetExtension(urlString), "html", StringComparison.OrdinalIgnoreCase)) + { + httpRes.StatusCode = 503; + } + return Task.FromResult(true); } diff --git a/MediaBrowser.Server.Implementations/Localization/Core/core.json b/MediaBrowser.Server.Implementations/Localization/Core/core.json index 5f11b9436..976faa8cb 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/core.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/core.json @@ -174,5 +174,6 @@ "HeaderWriter": "Writers", "HeaderParentalRatings": "Parental Ratings", "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." + "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly.", + "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete." } diff --git a/MediaBrowser.Server.Implementations/Localization/Core/en-US.json b/MediaBrowser.Server.Implementations/Localization/Core/en-US.json index e444c0e93..b1e8658de 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/en-US.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/en-US.json @@ -173,5 +173,6 @@ "HeaderWriter": "Writers", "HeaderParentalRatings": "Parental Ratings", "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." + "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly.", + "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs index 69ddb4d13..f4eb4ef8a 100644 --- a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs @@ -9,11 +9,14 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; +using System.Globalization; using System.Threading; using System.Threading.Tasks; using CommonIO; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Localization; +using MediaBrowser.Controller.Net; namespace MediaBrowser.Server.Implementations.Persistence { @@ -24,16 +27,21 @@ namespace MediaBrowser.Server.Implementations.Persistence private readonly ILogger _logger; private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; + private readonly IHttpServer _httpServer; + private readonly ILocalizationManager _localization; - public const int MigrationVersion = 7; + public const int MigrationVersion = 12; + public static bool EnableUnavailableMessage = false; - public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem) + public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IHttpServer httpServer, ILocalizationManager localization) { _libraryManager = libraryManager; _itemRepo = itemRepo; _logger = logger; _config = config; _fileSystem = fileSystem; + _httpServer = httpServer; + _localization = localization; } public string Name @@ -54,7 +62,23 @@ namespace MediaBrowser.Server.Implementations.Persistence public async Task Execute(CancellationToken cancellationToken, IProgress progress) { var innerProgress = new ActionableProgress(); - innerProgress.RegisterAction(p => progress.Report(.4 * p)); + innerProgress.RegisterAction(p => + { + double newPercentCommplete = .4 * p; + if (EnableUnavailableMessage) + { + var html = "Emby"; + var text = _localization.GetLocalizedString("DbUpgradeMessage"); + html += string.Format(text, newPercentCommplete.ToString("N2", CultureInfo.InvariantCulture)); + + html += ""; + html += ""; + + _httpServer.GlobalResponse = html; + } + + progress.Report(newPercentCommplete); + }); await UpdateToLatestSchema(cancellationToken, innerProgress).ConfigureAwait(false); @@ -69,6 +93,12 @@ namespace MediaBrowser.Server.Implementations.Persistence progress.Report(100); await _itemRepo.UpdateInheritedValues(cancellationToken).ConfigureAwait(false); + + if (EnableUnavailableMessage) + { + EnableUnavailableMessage = false; + _httpServer.GlobalResponse = null; + } } private async Task UpdateToLatestSchema(CancellationToken cancellationToken, IProgress progress) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 3d5ddcf49..7898dc1ef 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -82,7 +82,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; - private const int LatestSchemaVersion = 40; + private const int LatestSchemaVersion = 44; /// /// Initializes a new instance of the class. diff --git a/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs b/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs index cdb69025a..1df49845b 100644 --- a/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs +++ b/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs @@ -20,9 +20,11 @@ namespace MediaBrowser.Server.Startup.Common.Migrations { if (_config.Configuration.MigrationVersion < CleanDatabaseScheduledTask.MigrationVersion) { + CleanDatabaseScheduledTask.EnableUnavailableMessage = true; + Task.Run(async () => { - await Task.Delay(2000).ConfigureAwait(false); + await Task.Delay(1000).ConfigureAwait(false); _taskManager.QueueScheduledTask(); }); -- cgit v1.2.3