diff options
58 files changed, 513 insertions, 805 deletions
diff --git a/.ci/azure-pipelines.yml b/.ci/azure-pipelines.yml index efd69680e..46db0d9fe 100644 --- a/.ci/azure-pipelines.yml +++ b/.ci/azure-pipelines.yml @@ -190,7 +190,7 @@ jobs: - task: CmdLine@2 displayName: Execute ABI compatibility check tool inputs: - script: 'dotnet tools/CompatibilityCheckerCoreCLI.dll current-release/$(AssemblyFileName) new-release/$(AssemblyFileName)' + script: 'dotnet tools/CompatibilityCheckerCoreCLI.dll current-release/$(AssemblyFileName) new-release/$(AssemblyFileName) --azure-pipelines' workingDirectory: $(System.ArtifactsDirectory) # Optional #failOnStderr: false # Optional diff --git a/.github/ISSUE_TEMPLATE/enhancement-request.md b/.github/ISSUE_TEMPLATE/enhancement-request.md deleted file mode 100644 index a655b60f5..000000000 --- a/.github/ISSUE_TEMPLATE/enhancement-request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Enhancement request -about: Suggest an modification to an existing feature -title: '' -labels: enhancement -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] --> - -**Describe the solution you'd like** -<!-- A clear and concise description of what you want to happen. --> - -**Describe alternatives you've considered** -<!-- A clear and concise description of any alternative solutions or features you've considered. --> - -**Additional context** -<!-- Add any other context or screenshots about the feature request here. --> diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 3cbc8cbb9..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -name: Feature request -about: Suggest a new feature -title: '' -labels: feature -assignees: '' - ---- - -**Describe the feature you'd like** -<!-- A clear and concise description of what you want to happen. --> - -**Additional context** -<!-- Add any other context or screenshots about the feature request here. --> diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 9168dccc8..c96228f31 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -27,6 +27,7 @@ - [pjeanjean](https://github.com/pjeanjean) - [DrPandemic](https://github.com/drpandemic) - [joern-h](https://github.com/joern-h) + - [Khinenw](https://github.com/HelloWorld017) # Emby Contributors diff --git a/Dockerfile b/Dockerfile index 864cfa445..057d4b041 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ RUN apt-get update \ COPY --from=ffmpeg / / COPY --from=builder /jellyfin /jellyfin -ARG JELLYFIN_WEB_VERSION=10.3.6 +ARG JELLYFIN_WEB_VERSION=10.3.7 RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ && rm -rf /jellyfin/jellyfin-web \ && mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web diff --git a/Dockerfile.arm b/Dockerfile.arm index 816739063..dad4da1f1 100644 --- a/Dockerfile.arm +++ b/Dockerfile.arm @@ -26,7 +26,7 @@ RUN apt-get update \ && chmod 777 /cache /config /media COPY --from=builder /jellyfin /jellyfin -ARG JELLYFIN_WEB_VERSION=10.3.6 +ARG JELLYFIN_WEB_VERSION=10.3.7 RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ && rm -rf /jellyfin/jellyfin-web \ && mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index 1843f7224..5d4e86bff 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -26,7 +26,7 @@ RUN apt-get update \ && chmod 777 /cache /config /media COPY --from=builder /jellyfin /jellyfin -ARG JELLYFIN_WEB_VERSION=10.3.6 +ARG JELLYFIN_WEB_VERSION=10.3.7 RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ && rm -rf /jellyfin/jellyfin-web \ && mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 5fbe70ded..206a873e1 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -1,4 +1,5 @@ using System; +using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; using Emby.Dlna.PlayTo; @@ -247,7 +248,7 @@ namespace Emby.Dlna.Main foreach (var address in addresses) { - if (address.AddressFamily == IpAddressFamily.InterNetworkV6) + if (address.AddressFamily == AddressFamily.InterNetworkV6) { // Not support IPv6 right now continue; diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index 28e70d046..c0a441871 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Net; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Extensions; @@ -14,7 +15,6 @@ using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Events; using MediaBrowser.Model.Globalization; -using MediaBrowser.Model.Net; using MediaBrowser.Model.Session; using Microsoft.Extensions.Logging; @@ -172,7 +172,7 @@ namespace Emby.Dlna.PlayTo _sessionManager.UpdateDeviceName(sessionInfo.Id, deviceName); string serverAddress; - if (info.LocalIpAddress == null || info.LocalIpAddress.Equals(IpAddressInfo.Any) || info.LocalIpAddress.Equals(IpAddressInfo.IPv6Any)) + if (info.LocalIpAddress == null || info.LocalIpAddress.Equals(IPAddress.Any) || info.LocalIpAddress.Equals(IPAddress.IPv6Any)) { serverAddress = await _appHost.GetLocalApiUrl(cancellationToken).ConfigureAwait(false); } diff --git a/Emby.Dlna/PlayTo/SsdpHttpClient.cs b/Emby.Dlna/PlayTo/SsdpHttpClient.cs index 780b0a889..22aaa6885 100644 --- a/Emby.Dlna/PlayTo/SsdpHttpClient.cs +++ b/Emby.Dlna/PlayTo/SsdpHttpClient.cs @@ -155,7 +155,6 @@ namespace Emby.Dlna.PlayTo } options.RequestContentType = "text/xml"; - options.AppendCharsetToMimeType = true; options.RequestContent = postData; return _httpClient.Post(options); diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 120aade39..ef2f59d30 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Sockets; using System.Reflection; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; @@ -1546,14 +1547,32 @@ namespace Emby.Server.Implementations return null; } - public string GetLocalApiUrl(IpAddressInfo ipAddress) + /// <summary> + /// Removes the scope id from IPv6 addresses. + /// </summary> + /// <param name="address">The IPv6 address.</param> + /// <returns>The IPv6 address without the scope id.</returns> + private string RemoveScopeId(string address) + { + var index = address.IndexOf('%'); + if (index == -1) + { + return address; + } + + return address.Substring(0, index); + } + + public string GetLocalApiUrl(IPAddress ipAddress) { - if (ipAddress.AddressFamily == IpAddressFamily.InterNetworkV6) + if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6) { - return GetLocalApiUrl("[" + ipAddress.Address + "]"); + var str = RemoveScopeId(ipAddress.ToString()); + + return GetLocalApiUrl("[" + str + "]"); } - return GetLocalApiUrl(ipAddress.Address); + return GetLocalApiUrl(ipAddress.ToString()); } public string GetLocalApiUrl(string host) @@ -1564,19 +1583,22 @@ namespace Emby.Server.Implementations host, HttpsPort.ToString(CultureInfo.InvariantCulture)); } + return string.Format("http://{0}:{1}", host, HttpPort.ToString(CultureInfo.InvariantCulture)); } - public string GetWanApiUrl(IpAddressInfo ipAddress) + public string GetWanApiUrl(IPAddress ipAddress) { - if (ipAddress.AddressFamily == IpAddressFamily.InterNetworkV6) + if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6) { - return GetWanApiUrl("[" + ipAddress.Address + "]"); + var str = RemoveScopeId(ipAddress.ToString()); + + return GetWanApiUrl("[" + str + "]"); } - return GetWanApiUrl(ipAddress.Address); + return GetWanApiUrl(ipAddress.ToString()); } public string GetWanApiUrl(string host) @@ -1587,17 +1609,18 @@ namespace Emby.Server.Implementations host, ServerConfigurationManager.Configuration.PublicHttpsPort.ToString(CultureInfo.InvariantCulture)); } + return string.Format("http://{0}:{1}", host, ServerConfigurationManager.Configuration.PublicPort.ToString(CultureInfo.InvariantCulture)); } - public Task<List<IpAddressInfo>> GetLocalIpAddresses(CancellationToken cancellationToken) + public Task<List<IPAddress>> GetLocalIpAddresses(CancellationToken cancellationToken) { return GetLocalIpAddressesInternal(true, 0, cancellationToken); } - private async Task<List<IpAddressInfo>> GetLocalIpAddressesInternal(bool allowLoopback, int limit, CancellationToken cancellationToken) + private async Task<List<IPAddress>> GetLocalIpAddressesInternal(bool allowLoopback, int limit, CancellationToken cancellationToken) { var addresses = ServerConfigurationManager .Configuration @@ -1611,13 +1634,13 @@ namespace Emby.Server.Implementations addresses.AddRange(NetworkManager.GetLocalIpAddresses(ServerConfigurationManager.Configuration.IgnoreVirtualInterfaces)); } - var resultList = new List<IpAddressInfo>(); + var resultList = new List<IPAddress>(); foreach (var address in addresses) { if (!allowLoopback) { - if (address.Equals(IpAddressInfo.Loopback) || address.Equals(IpAddressInfo.IPv6Loopback)) + if (address.Equals(IPAddress.Loopback) || address.Equals(IPAddress.IPv6Loopback)) { continue; } @@ -1638,7 +1661,7 @@ namespace Emby.Server.Implementations return resultList; } - private IpAddressInfo NormalizeConfiguredLocalAddress(string address) + private IPAddress NormalizeConfiguredLocalAddress(string address) { var index = address.Trim('/').IndexOf('/'); @@ -1647,7 +1670,7 @@ namespace Emby.Server.Implementations address = address.Substring(index + 1); } - if (NetworkManager.TryParseIpAddress(address.Trim('/'), out IpAddressInfo result)) + if (IPAddress.TryParse(address.Trim('/'), out IPAddress result)) { return result; } @@ -1657,10 +1680,10 @@ namespace Emby.Server.Implementations private readonly ConcurrentDictionary<string, bool> _validAddressResults = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase); - private async Task<bool> IsIpAddressValidAsync(IpAddressInfo address, CancellationToken cancellationToken) + private async Task<bool> IsIpAddressValidAsync(IPAddress address, CancellationToken cancellationToken) { - if (address.Equals(IpAddressInfo.Loopback) || - address.Equals(IpAddressInfo.IPv6Loopback)) + if (address.Equals(IPAddress.Loopback) || + address.Equals(IPAddress.IPv6Loopback)) { return true; } diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs index c9dc6c815..331b5e29d 100644 --- a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs +++ b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs @@ -179,10 +179,7 @@ namespace Emby.Server.Implementations.HttpClientManager /// <param name="httpMethod">The HTTP method.</param> /// <returns>Task{HttpResponseInfo}.</returns> public Task<HttpResponseInfo> SendAsync(HttpRequestOptions options, string httpMethod) - { - var httpMethod2 = GetHttpMethod(httpMethod); - return SendAsync(options, httpMethod2); - } + => SendAsync(options, new HttpMethod(httpMethod)); /// <summary> /// send as an asynchronous operation. @@ -218,40 +215,6 @@ namespace Emby.Server.Implementations.HttpClientManager return response; } - private HttpMethod GetHttpMethod(string httpMethod) - { - if (httpMethod.Equals("DELETE", StringComparison.OrdinalIgnoreCase)) - { - return HttpMethod.Delete; - } - else if (httpMethod.Equals("GET", StringComparison.OrdinalIgnoreCase)) - { - return HttpMethod.Get; - } - else if (httpMethod.Equals("HEAD", StringComparison.OrdinalIgnoreCase)) - { - return HttpMethod.Head; - } - else if (httpMethod.Equals("OPTIONS", StringComparison.OrdinalIgnoreCase)) - { - return HttpMethod.Options; - } - else if (httpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase)) - { - return HttpMethod.Post; - } - else if (httpMethod.Equals("PUT", StringComparison.OrdinalIgnoreCase)) - { - return HttpMethod.Put; - } - else if (httpMethod.Equals("TRACE", StringComparison.OrdinalIgnoreCase)) - { - return HttpMethod.Trace; - } - - throw new ArgumentException("Invalid HTTP method", nameof(httpMethod)); - } - private HttpResponseInfo GetCachedResponse(string responseCachePath, TimeSpan cacheLength, string url) { if (File.Exists(responseCachePath) @@ -303,23 +266,15 @@ namespace Emby.Server.Implementations.HttpClientManager } else if (options.RequestContent != null) { - httpWebRequest.Content = new StringContent(options.RequestContent); + httpWebRequest.Content = new StringContent( + options.RequestContent, + null, + options.RequestContentType); } else { httpWebRequest.Content = new ByteArrayContent(Array.Empty<byte>()); } - - // TODO: add correct content type - /* - var contentType = options.RequestContentType ?? "application/x-www-form-urlencoded"; - - if (options.AppendCharsetToMimeType) - { - contentType = contentType.TrimEnd(';') + "; charset=\"utf-8\""; - } - - httpWebRequest.Headers.Add(HeaderNames.ContentType, contentType);*/ } if (options.LogRequest) @@ -329,47 +284,24 @@ namespace Emby.Server.Implementations.HttpClientManager options.CancellationToken.ThrowIfCancellationRequested(); - if (!options.BufferContent) - { - var response = await client.SendAsync(httpWebRequest, options.CancellationToken).ConfigureAwait(false); - - await EnsureSuccessStatusCode(response, options).ConfigureAwait(false); + var response = await client.SendAsync( + httpWebRequest, + options.BufferContent ? HttpCompletionOption.ResponseContentRead : HttpCompletionOption.ResponseHeadersRead, + options.CancellationToken).ConfigureAwait(false); - options.CancellationToken.ThrowIfCancellationRequested(); + await EnsureSuccessStatusCode(response, options).ConfigureAwait(false); - var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); - return new HttpResponseInfo(response.Headers) - { - Content = stream, - StatusCode = response.StatusCode, - ContentType = response.Content.Headers.ContentType?.MediaType, - ContentLength = stream.Length, - ResponseUrl = response.Content.Headers.ContentLocation?.ToString() - }; - } + options.CancellationToken.ThrowIfCancellationRequested(); - using (var response = await client.SendAsync(httpWebRequest, options.CancellationToken).ConfigureAwait(false)) + var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + return new HttpResponseInfo(response.Headers, response.Content.Headers) { - await EnsureSuccessStatusCode(response, options).ConfigureAwait(false); - - options.CancellationToken.ThrowIfCancellationRequested(); - - using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) - { - var memoryStream = new MemoryStream(); - await stream.CopyToAsync(memoryStream, StreamDefaults.DefaultCopyToBufferSize, options.CancellationToken).ConfigureAwait(false); - memoryStream.Position = 0; - - return new HttpResponseInfo(response.Headers) - { - Content = memoryStream, - StatusCode = response.StatusCode, - ContentType = response.Content.Headers.ContentType?.MediaType, - ContentLength = memoryStream.Length, - ResponseUrl = response.Content.Headers.ContentLocation?.ToString() - }; - } - } + Content = stream, + StatusCode = response.StatusCode, + ContentType = response.Content.Headers.ContentType?.MediaType, + ContentLength = response.Content.Headers.ContentLength, + ResponseUrl = response.Content.Headers.ContentLocation?.ToString() + }; } public Task<HttpResponseInfo> Post(HttpRequestOptions options) @@ -430,7 +362,7 @@ namespace Emby.Server.Implementations.HttpClientManager options.Progress.Report(100); - var responseInfo = new HttpResponseInfo(response.Headers) + var responseInfo = new HttpResponseInfo(response.Headers, response.Content.Headers) { TempFilePath = tempFile, StatusCode = response.StatusCode, diff --git a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs index a70077163..f1ae2fc9c 100644 --- a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs +++ b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs @@ -5,7 +5,6 @@ using System.Text.RegularExpressions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Resolvers; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Library @@ -17,12 +16,10 @@ namespace Emby.Server.Implementations.Library { private readonly ILibraryManager _libraryManager; - private bool _ignoreDotPrefix; - /// <summary> - /// Any folder named in this list will be ignored - can be added to at runtime for extensibility + /// Any folder named in this list will be ignored /// </summary> - public static readonly string[] IgnoreFolders = + private static readonly string[] _ignoreFolders = { "metadata", "ps3_update", @@ -43,25 +40,14 @@ namespace Emby.Server.Implementations.Library "$RECYCLE.BIN", "System Volume Information", ".grab", - - // macos - ".AppleDouble" - }; public CoreResolutionIgnoreRule(ILibraryManager libraryManager) { _libraryManager = libraryManager; - - _ignoreDotPrefix = Environment.OSVersion.Platform != PlatformID.Win32NT; } - /// <summary> - /// Shoulds the ignore. - /// </summary> - /// <param name="fileInfo">The file information.</param> - /// <param name="parent">The parent.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> + /// <inheritdoc /> public bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent) { // Don't ignore top level folders @@ -73,46 +59,17 @@ namespace Emby.Server.Implementations.Library var filename = fileInfo.Name; var path = fileInfo.FullName; - // Handle mac .DS_Store - // https://github.com/MediaBrowser/MediaBrowser/issues/427 - if (_ignoreDotPrefix) + // Ignore hidden files on UNIX + if (Environment.OSVersion.Platform != PlatformID.Win32NT + && filename[0] == '.') { - if (filename.IndexOf('.') == 0) - { - return true; - } + return true; } - // Ignore hidden files and folders - //if (fileInfo.IsHidden) - //{ - // if (parent == null) - // { - // var parentFolderName = Path.GetFileName(_fileSystem.GetDirectoryName(path)); - - // if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) - // { - // return false; - // } - // if (string.Equals(parentFolderName, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase)) - // { - // return false; - // } - // } - - // // Sometimes these are marked hidden - // if (_fileSystem.IsRootPath(path)) - // { - // return false; - // } - - // return true; - //} - if (fileInfo.IsDirectory) { // Ignore any folders in our list - if (IgnoreFolders.Contains(filename, StringComparer.OrdinalIgnoreCase)) + if (_ignoreFolders.Contains(filename, StringComparer.OrdinalIgnoreCase)) { return true; } @@ -120,8 +77,9 @@ namespace Emby.Server.Implementations.Library if (parent != null) { // Ignore trailer folders but allow it at the collection level - if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) && - !(parent is AggregateFolder) && !(parent is UserRootFolder)) + if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) + && !(parent is AggregateFolder) + && !(parent is UserRootFolder)) { return true; } @@ -142,14 +100,15 @@ namespace Emby.Server.Implementations.Library if (parent != null) { // Don't resolve these into audio files - if (string.Equals(Path.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) && _libraryManager.IsAudioFile(filename)) + if (string.Equals(Path.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) + && _libraryManager.IsAudioFile(filename)) { return true; } } // Ignore samples - Match m = Regex.Match(filename,@"\bsample\b",RegexOptions.IgnoreCase); + Match m = Regex.Match(filename, @"\bsample\b", RegexOptions.IgnoreCase); return m.Success; } diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 47c3e71d7..1b63b00a3 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -12,7 +12,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Library.Resolvers.Movies @@ -28,7 +27,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies /// <value>The priority.</value> public override ResolverPriority Priority => ResolverPriority.Third; - public MultiItemResolverResult ResolveMultiple(Folder parent, + public MultiItemResolverResult ResolveMultiple( + Folder parent, List<FileSystemMetadata> files, string collectionType, IDirectoryService directoryService) @@ -46,7 +46,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return result; } - private MultiItemResolverResult ResolveMultipleInternal(Folder parent, + private MultiItemResolverResult ResolveMultipleInternal( + Folder parent, List<FileSystemMetadata> files, string collectionType, IDirectoryService directoryService) @@ -91,7 +92,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return null; } - private MultiItemResolverResult ResolveVideos<T>(Folder parent, IEnumerable<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, bool suppportMultiEditions, string collectionType, bool parseName) + private MultiItemResolverResult ResolveVideos<T>( + Folder parent, + IEnumerable<FileSystemMetadata> fileSystemEntries, + IDirectoryService directoryService, + bool suppportMultiEditions, + string collectionType, + bool parseName) where T : Video, new() { var files = new List<FileSystemMetadata>(); @@ -104,8 +111,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies // This is a hack but currently no better way to resolve a sometimes ambiguous situation if (string.IsNullOrEmpty(collectionType)) { - if (string.Equals(child.Name, "tvshow.nfo", StringComparison.OrdinalIgnoreCase) || - string.Equals(child.Name, "season.nfo", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(child.Name, "tvshow.nfo", StringComparison.OrdinalIgnoreCase) + || string.Equals(child.Name, "season.nfo", StringComparison.OrdinalIgnoreCase)) { return null; } @@ -115,11 +122,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies { leftOver.Add(child); } - else if (IsIgnored(child.Name)) - { - - } - else + else if (!IsIgnored(child.Name)) { files.Add(child); } @@ -168,7 +171,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies private static bool IsIgnored(string filename) { // Ignore samples - Match m = Regex.Match(filename,@"\bsample\b",RegexOptions.IgnoreCase); + Match m = Regex.Match(filename, @"\bsample\b", RegexOptions.IgnoreCase); return m.Success; } diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index d39c91783..94225a0aa 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -2,14 +2,15 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; +using System.IO.Compression; using System.Linq; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Emby.XmlTv.Classes; using Emby.XmlTv.Entities; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; -using MediaBrowser.Common.Progress; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.Dto; @@ -27,7 +28,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings private readonly IFileSystem _fileSystem; private readonly IZipClient _zipClient; - public XmlTvListingsProvider(IServerConfigurationManager config, IHttpClient httpClient, ILogger logger, IFileSystem fileSystem, IZipClient zipClient) + public XmlTvListingsProvider( + IServerConfigurationManager config, + IHttpClient httpClient, + ILogger logger, + IFileSystem fileSystem, + IZipClient zipClient) { _config = config; _httpClient = httpClient; @@ -52,7 +58,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings private async Task<string> GetXml(string path, CancellationToken cancellationToken) { - _logger.LogInformation("xmltv path: {path}", path); + _logger.LogInformation("xmltv path: {Path}", path); if (!path.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { @@ -66,24 +72,33 @@ namespace Emby.Server.Implementations.LiveTv.Listings return UnzipIfNeeded(path, cacheFile); } - _logger.LogInformation("Downloading xmltv listings from {path}", path); - - string tempFile = await _httpClient.GetTempFile(new HttpRequestOptions - { - CancellationToken = cancellationToken, - Url = path, - Progress = new SimpleProgress<double>(), - // It's going to come back gzipped regardless of this value - // So we need to make sure the decompression method is set to gzip - DecompressionMethod = CompressionMethod.Gzip, - - UserAgent = "Emby/3.0" - - }).ConfigureAwait(false); + _logger.LogInformation("Downloading xmltv listings from {Path}", path); Directory.CreateDirectory(Path.GetDirectoryName(cacheFile)); - File.Copy(tempFile, cacheFile, true); + using (var res = await _httpClient.SendAsync( + new HttpRequestOptions + { + CancellationToken = cancellationToken, + Url = path, + DecompressionMethod = CompressionMethod.Gzip, + }, + HttpMethod.Get).ConfigureAwait(false)) + using (var stream = res.Content) + using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew)) + { + if (res.ContentHeaders.ContentEncoding.Contains("gzip")) + { + using (var gzStream = new GZipStream(stream, CompressionMode.Decompress)) + { + await gzStream.CopyToAsync(fileStream).ConfigureAwait(false); + } + } + else + { + await stream.CopyToAsync(fileStream).ConfigureAwait(false); + } + } return UnzipIfNeeded(path, cacheFile); } @@ -101,7 +116,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings } catch (Exception ex) { - _logger.LogError(ex, "Error extracting from gz file {file}", file); + _logger.LogError(ex, "Error extracting from gz file {File}", file); } try @@ -111,7 +126,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings } catch (Exception ex) { - _logger.LogError(ex, "Error extracting from zip file {file}", file); + _logger.LogError(ex, "Error extracting from zip file {File}", file); } } @@ -159,20 +174,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings throw new ArgumentNullException(nameof(channelId)); } - /* - if (!await EmbyTV.EmbyTVRegistration.Instance.EnableXmlTv().ConfigureAwait(false)) - { - var length = endDateUtc - startDateUtc; - if (length.TotalDays > 1) - { - endDateUtc = startDateUtc.AddDays(1); - } - }*/ - - _logger.LogDebug("Getting xmltv programs for channel {id}", channelId); + _logger.LogDebug("Getting xmltv programs for channel {Id}", channelId); string path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); - _logger.LogDebug("Opening XmlTvReader for {path}", path); + _logger.LogDebug("Opening XmlTvReader for {Path}", path); var reader = new XmlTvReader(path, GetLanguage(info)); return reader.GetProgrammes(channelId, startDateUtc, endDateUtc, cancellationToken) @@ -265,7 +270,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { // In theory this should never be called because there is always only one lineup string path = await GetXml(info.Path, CancellationToken.None).ConfigureAwait(false); - _logger.LogDebug("Opening XmlTvReader for {path}", path); + _logger.LogDebug("Opening XmlTvReader for {Path}", path); var reader = new XmlTvReader(path, GetLanguage(info)); IEnumerable<XmlTvChannel> results = reader.GetChannels(); @@ -277,7 +282,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { // In theory this should never be called because there is always only one lineup string path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); - _logger.LogDebug("Opening XmlTvReader for {path}", path); + _logger.LogDebug("Opening XmlTvReader for {Path}", path); var reader = new XmlTvReader(path, GetLanguage(info)); var results = reader.GetChannels(); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 761275f8f..ed524cae3 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; @@ -11,7 +12,6 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -20,7 +20,6 @@ using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Net; using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.System; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun @@ -259,7 +258,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun using (var manager = new HdHomerunManager(_socketFactory, Logger)) { // Legacy HdHomeruns are IPv4 only - var ipInfo = _networkManager.ParseIpAddress(uri.Host); + var ipInfo = IPAddress.Parse(uri.Host); for (int i = 0; i < model.TunerCount; ++i) { @@ -675,13 +674,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun // Need a way to set the Receive timeout on the socket otherwise this might never timeout? try { - await udpClient.SendToAsync(discBytes, 0, discBytes.Length, new IpEndPointInfo(new IpAddressInfo("255.255.255.255", IpAddressFamily.InterNetwork), 65001), cancellationToken); + await udpClient.SendToAsync(discBytes, 0, discBytes.Length, new IPEndPoint(IPAddress.Parse("255.255.255.255"), 65001), cancellationToken); var receiveBuffer = new byte[8192]; while (!cancellationToken.IsCancellationRequested) { var response = await udpClient.ReceiveAsync(receiveBuffer, 0, receiveBuffer.Length, cancellationToken).ConfigureAwait(false); - var deviceIp = response.RemoteEndPoint.IpAddress.Address; + var deviceIp = response.RemoteEndPoint.Address.ToString(); // check to make sure we have enough bytes received to be a valid message and make sure the 2nd byte is the discover reply byte if (response.ReceivedBytes > 13 && response.Buffer[1] == 3) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index 2205c0ecc..6e79441da 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -89,7 +89,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private uint? _lockkey = null; private int _activeTuner = -1; private readonly ISocketFactory _socketFactory; - private IpAddressInfo _remoteIp; + private IPAddress _remoteIp; private ILogger _logger; private ISocket _currentTcpSocket; @@ -114,7 +114,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } } - public async Task<bool> CheckTunerAvailability(IpAddressInfo remoteIp, int tuner, CancellationToken cancellationToken) + public async Task<bool> CheckTunerAvailability(IPAddress remoteIp, int tuner, CancellationToken cancellationToken) { using (var socket = _socketFactory.CreateTcpSocket(remoteIp, HdHomeRunPort)) { @@ -122,9 +122,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } } - private static async Task<bool> CheckTunerAvailability(ISocket socket, IpAddressInfo remoteIp, int tuner, CancellationToken cancellationToken) + private static async Task<bool> CheckTunerAvailability(ISocket socket, IPAddress remoteIp, int tuner, CancellationToken cancellationToken) { - var ipEndPoint = new IpEndPointInfo(remoteIp, HdHomeRunPort); + var ipEndPoint = new IPEndPoint(remoteIp, HdHomeRunPort); var lockkeyMsg = CreateGetMessage(tuner, "lockkey"); await socket.SendToAsync(lockkeyMsg, 0, lockkeyMsg.Length, ipEndPoint, cancellationToken); @@ -137,7 +137,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return string.Equals(returnVal, "none", StringComparison.OrdinalIgnoreCase); } - public async Task StartStreaming(IpAddressInfo remoteIp, IPAddress localIp, int localPort, IHdHomerunChannelCommands commands, int numTuners, CancellationToken cancellationToken) + public async Task StartStreaming(IPAddress remoteIp, IPAddress localIp, int localPort, IHdHomerunChannelCommands commands, int numTuners, CancellationToken cancellationToken) { _remoteIp = remoteIp; @@ -154,7 +154,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var lockKeyValue = _lockkey.Value; - var ipEndPoint = new IpEndPointInfo(_remoteIp, HdHomeRunPort); + var ipEndPoint = new IPEndPoint(_remoteIp, HdHomeRunPort); for (int i = 0; i < numTuners; ++i) { @@ -217,7 +217,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun foreach (Tuple<string, string> command in commandList) { var channelMsg = CreateSetMessage(_activeTuner, command.Item1, command.Item2, _lockkey); - await tcpClient.SendToAsync(channelMsg, 0, channelMsg.Length, new IpEndPointInfo(_remoteIp, HdHomeRunPort), cancellationToken).ConfigureAwait(false); + await tcpClient.SendToAsync(channelMsg, 0, channelMsg.Length, new IPEndPoint(_remoteIp, HdHomeRunPort), cancellationToken).ConfigureAwait(false); var response = await tcpClient.ReceiveAsync(receiveBuffer, 0, receiveBuffer.Length, cancellationToken).ConfigureAwait(false); // parse response to make sure it worked if (!ParseReturnMessage(response.Buffer, response.ReceivedBytes, out string returnVal)) @@ -242,7 +242,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { _logger.LogInformation("HdHomerunManager.ReleaseLockkey {0}", lockKeyValue); - var ipEndPoint = new IpEndPointInfo(_remoteIp, HdHomeRunPort); + var ipEndPoint = new IPEndPoint(_remoteIp, HdHomeRunPort); var releaseTarget = CreateSetMessage(_activeTuner, "target", "none", lockKeyValue); await tcpClient.SendToAsync(releaseTarget, 0, releaseTarget.Length, ipEndPoint, CancellationToken.None).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index 7f426ea31..ec708cf20 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -25,7 +25,19 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private readonly int _numTuners; private readonly INetworkManager _networkManager; - public HdHomerunUdpStream(MediaSourceInfo mediaSource, TunerHostInfo tunerHostInfo, string originalStreamId, IHdHomerunChannelCommands channelCommands, int numTuners, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, MediaBrowser.Model.Net.ISocketFactory socketFactory, INetworkManager networkManager) + public HdHomerunUdpStream( + MediaSourceInfo mediaSource, + TunerHostInfo tunerHostInfo, + string originalStreamId, + IHdHomerunChannelCommands channelCommands, + int numTuners, + IFileSystem fileSystem, + IHttpClient httpClient, + ILogger logger, + IServerApplicationPaths appPaths, + IServerApplicationHost appHost, + MediaBrowser.Model.Net.ISocketFactory socketFactory, + INetworkManager networkManager) : base(mediaSource, tunerHostInfo, fileSystem, logger, appPaths) { _appHost = appHost; @@ -58,7 +70,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun Logger.LogInformation("Opening HDHR UDP Live stream from {host}", uri.Host); var remoteAddress = IPAddress.Parse(uri.Host); - var embyRemoteAddress = _networkManager.ParseIpAddress(uri.Host); IPAddress localAddress = null; using (var tcpSocket = CreateSocket(remoteAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp)) { @@ -81,7 +92,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun try { // send url to start streaming - await hdHomerunManager.StartStreaming(embyRemoteAddress, localAddress, localPort, _channelCommands, _numTuners, openCancellationToken).ConfigureAwait(false); + await hdHomerunManager.StartStreaming(remoteAddress, localAddress, localPort, _channelCommands, _numTuners, openCancellationToken).ConfigureAwait(false); } catch (Exception ex) { diff --git a/Emby.Server.Implementations/Localization/Core/de.json b/Emby.Server.Implementations/Localization/Core/de.json index 6fd63a514..0db201769 100644 --- a/Emby.Server.Implementations/Localization/Core/de.json +++ b/Emby.Server.Implementations/Localization/Core/de.json @@ -27,7 +27,7 @@ "HeaderNextUp": "Als Nächstes", "HeaderRecordingGroups": "Aufnahme-Gruppen", "HomeVideos": "Heimvideos", - "Inherit": "Übernehmen", + "Inherit": "Vererben", "ItemAddedWithName": "{0} wurde der Bibliothek hinzugefügt", "ItemRemovedWithName": "{0} wurde aus der Bibliothek entfernt", "LabelIpAddressValue": "IP-Adresse: {0}", diff --git a/Emby.Server.Implementations/Localization/Core/fa.json b/Emby.Server.Implementations/Localization/Core/fa.json index 0a0c7553b..faa658ed5 100644 --- a/Emby.Server.Implementations/Localization/Core/fa.json +++ b/Emby.Server.Implementations/Localization/Core/fa.json @@ -5,7 +5,7 @@ "Artists": "هنرمندان", "AuthenticationSucceededWithUserName": "{0} با موفقیت تایید اعتبار شد", "Books": "کتاب ها", - "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", + "CameraImageUploadedFrom": "یک عکس جدید از دوربین ارسال شده {0}", "Channels": "کانال ها", "ChapterNameValue": "فصل {0}", "Collections": "کلکسیون ها", @@ -34,17 +34,17 @@ "LabelRunningTimeValue": "زمان اجرا: {0}", "Latest": "آخرین", "MessageApplicationUpdated": "سرور Jellyfin بروزرسانی شد", - "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", + "MessageApplicationUpdatedTo": "سرور جلیفین آپدیت شده به نسخه {0}", "MessageNamedServerConfigurationUpdatedWithValue": "پکربندی بخش {0} سرور بروزرسانی شد", "MessageServerConfigurationUpdated": "پیکربندی سرور بروزرسانی شد", "MixedContent": "محتوای درهم", "Movies": "فیلم های سینمایی", "Music": "موسیقی", "MusicVideos": "موزیک ویدیوها", - "NameInstallFailed": "{0} installation failed", + "NameInstallFailed": "{0} نصب با مشکل مواجه شده", "NameSeasonNumber": "فصل {0}", "NameSeasonUnknown": "فصل های ناشناخته", - "NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.", + "NewVersionIsAvailable": "یک نسخه جدید جلیفین برای بروزرسانی آماده میباشد.", "NotificationOptionApplicationUpdateAvailable": "بروزرسانی برنامه موجود است", "NotificationOptionApplicationUpdateInstalled": "بروزرسانی برنامه نصب شد", "NotificationOptionAudioPlayback": "پخش صدا آغاز شد", @@ -70,12 +70,12 @@ "ProviderValue": "ارائه دهنده: {0}", "ScheduledTaskFailedWithName": "{0} ناموفق بود", "ScheduledTaskStartedWithName": "{0} شروع شد", - "ServerNameNeedsToBeRestarted": "{0} needs to be restarted", + "ServerNameNeedsToBeRestarted": "{0} احتیاج به راه اندازی مجدد", "Shows": "سریال ها", "Songs": "آهنگ ها", "StartupEmbyServerIsLoading": "سرور Jellyfin در حال بارگیری است. لطفا کمی بعد دوباره تلاش کنید.", "SubtitleDownloadFailureForItem": "دانلود زیرنویس برای {0} ناموفق بود", - "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", + "SubtitleDownloadFailureFromForItem": "زیرنویس برای دانلود با مشکل مواجه شده از {0} برای {1}", "SubtitlesDownloadedForItem": "زیرنویس {0} دانلود شد", "Sync": "همگامسازی", "System": "سیستم", @@ -91,7 +91,7 @@ "UserPolicyUpdatedWithName": "سیاست کاربری برای {0} بروزرسانی شد", "UserStartedPlayingItemWithValues": "{0} شروع به پخش {1} کرد", "UserStoppedPlayingItemWithValues": "{0} پخش {1} را متوقف کرد", - "ValueHasBeenAddedToLibrary": "{0} has been added to your media library", + "ValueHasBeenAddedToLibrary": "{0} اضافه شده به کتابخانه رسانه شما", "ValueSpecialEpisodeName": "ویژه- {0}", "VersionNumber": "نسخه {0}" } diff --git a/Emby.Server.Implementations/Localization/Core/ja.json b/Emby.Server.Implementations/Localization/Core/ja.json index 53a43a125..4aa0637c5 100644 --- a/Emby.Server.Implementations/Localization/Core/ja.json +++ b/Emby.Server.Implementations/Localization/Core/ja.json @@ -13,17 +13,17 @@ "DeviceOnlineWithName": "{0} が接続されました", "FailedLoginAttemptWithUserName": "ログインを試行しましたが {0}によって失敗しました", "Favorites": "お気に入り", - "Folders": "フォルダ", + "Folders": "フォルダー", "Genres": "ジャンル", "HeaderAlbumArtists": "アルバムアーティスト", "HeaderCameraUploads": "カメラアップロード", - "HeaderContinueWatching": "視聴中", + "HeaderContinueWatching": "視聴を続ける", "HeaderFavoriteAlbums": "お気に入りのアルバム", "HeaderFavoriteArtists": "お気に入りのアーティスト", "HeaderFavoriteEpisodes": "お気に入りのエピソード", "HeaderFavoriteShows": "お気に入りの番組", "HeaderFavoriteSongs": "お気に入りの曲", - "HeaderLiveTV": "ライブ テレビ", + "HeaderLiveTV": "ライブTV", "HeaderNextUp": "次", "HeaderRecordingGroups": "レコーディンググループ", "HomeVideos": "ホームビデオ", diff --git a/Emby.Server.Implementations/Localization/Core/ko.json b/Emby.Server.Implementations/Localization/Core/ko.json index 5a7ba8ba7..f2b7c408c 100644 --- a/Emby.Server.Implementations/Localization/Core/ko.json +++ b/Emby.Server.Implementations/Localization/Core/ko.json @@ -20,7 +20,7 @@ "HeaderContinueWatching": "계속 시청하기", "HeaderFavoriteAlbums": "좋아하는 앨범", "HeaderFavoriteArtists": "좋아하는 아티스트", - "HeaderFavoriteEpisodes": "Favorite Episodes", + "HeaderFavoriteEpisodes": "좋아하는 에피소드", "HeaderFavoriteShows": "즐겨찾는 쇼", "HeaderFavoriteSongs": "좋아하는 노래", "HeaderLiveTV": "TV 방송", diff --git a/Emby.Server.Implementations/Localization/Core/pt-BR.json b/Emby.Server.Implementations/Localization/Core/pt-BR.json index dbc9c4c4b..5d68416e9 100644 --- a/Emby.Server.Implementations/Localization/Core/pt-BR.json +++ b/Emby.Server.Implementations/Localization/Core/pt-BR.json @@ -5,7 +5,7 @@ "Artists": "Artistas", "AuthenticationSucceededWithUserName": "{0} autenticado com sucesso", "Books": "Livros", - "CameraImageUploadedFrom": "Uma nova imagem da câmera foi submetida de {0}", + "CameraImageUploadedFrom": "Uma nova imagem da câmera foi enviada de {0}", "Channels": "Canais", "ChapterNameValue": "Capítulo {0}", "Collections": "Coletâneas", @@ -21,8 +21,8 @@ "HeaderFavoriteAlbums": "Álbuns Favoritos", "HeaderFavoriteArtists": "Artistas Favoritos", "HeaderFavoriteEpisodes": "Episódios Favoritos", - "HeaderFavoriteShows": "Séries Favoritas", - "HeaderFavoriteSongs": "Músicas Favoritas", + "HeaderFavoriteShows": "Shows Favoritos", + "HeaderFavoriteSongs": "Musicas Favoritas", "HeaderLiveTV": "TV ao Vivo", "HeaderNextUp": "Próximos", "HeaderRecordingGroups": "Grupos de Gravação", @@ -79,7 +79,7 @@ "SubtitlesDownloadedForItem": "Legendas baixadas para {0}", "Sync": "Sincronizar", "System": "Sistema", - "TvShows": "Séries de TV", + "TvShows": "Séries", "User": "Usuário", "UserCreatedWithName": "O usuário {0} foi criado", "UserDeletedWithName": "O usuário {0} foi excluído", diff --git a/Emby.Server.Implementations/Localization/Core/pt-PT.json b/Emby.Server.Implementations/Localization/Core/pt-PT.json index dc69d8af2..387604f03 100644 --- a/Emby.Server.Implementations/Localization/Core/pt-PT.json +++ b/Emby.Server.Implementations/Localization/Core/pt-PT.json @@ -1,97 +1,97 @@ { - "Albums": "Albums", - "AppDeviceValues": "App: {0}, Device: {1}", + "Albums": "Álbuns", + "AppDeviceValues": "Aplicação {0}, Dispositivo:{1}", "Application": "Aplicação", - "Artists": "Artists", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "Books": "Books", - "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", - "Channels": "Channels", - "ChapterNameValue": "Chapter {0}", - "Collections": "Collections", - "DeviceOfflineWithName": "{0} has disconnected", - "DeviceOnlineWithName": "{0} is connected", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "Favorites": "Favorites", - "Folders": "Folders", - "Genres": "Genres", - "HeaderAlbumArtists": "Album Artists", + "Artists": "Artistas", + "AuthenticationSucceededWithUserName": "{0} autenticado com sucesso", + "Books": "Livros", + "CameraImageUploadedFrom": "Uma nova imagem proveniente de uma câmara foi enviada a partir de {0}", + "Channels": "Canais", + "ChapterNameValue": "Capítulo {0}", + "Collections": "Coleções", + "DeviceOfflineWithName": "{0} desligou-se", + "DeviceOnlineWithName": "{0} ligou-se", + "FailedLoginAttemptWithUserName": "Tentativa de login falhada a partir de {0}", + "Favorites": "Favoritos", + "Folders": "Pastas", + "Genres": "Géneros", + "HeaderAlbumArtists": "Artistas do Álbum", "HeaderCameraUploads": "Camera Uploads", - "HeaderContinueWatching": "Continuar a ver", - "HeaderFavoriteAlbums": "Favorite Albums", - "HeaderFavoriteArtists": "Favorite Artists", - "HeaderFavoriteEpisodes": "Favorite Episodes", + "HeaderContinueWatching": "Continuar a Ver", + "HeaderFavoriteAlbums": "Álbuns Favoritos", + "HeaderFavoriteArtists": "Artistas Favoritos", + "HeaderFavoriteEpisodes": "Episódios Favoritos", "HeaderFavoriteShows": "Séries Favoritas", - "HeaderFavoriteSongs": "Favorite Songs", - "HeaderLiveTV": "Live TV", - "HeaderNextUp": "Next Up", - "HeaderRecordingGroups": "Recording Groups", + "HeaderFavoriteSongs": "Músicas Favoritas", + "HeaderLiveTV": "TV em Direto", + "HeaderNextUp": "A Seguir", + "HeaderRecordingGroups": "Grupos de Gravação", "HomeVideos": "Home videos", "Inherit": "Inherit", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "LabelRunningTimeValue": "Running time: {0}", - "Latest": "Latest", - "MessageApplicationUpdated": "Jellyfin Server has been updated", - "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MixedContent": "Mixed content", - "Movies": "Movies", - "Music": "Music", - "MusicVideos": "Music videos", - "NameInstallFailed": "{0} installation failed", - "NameSeasonNumber": "Season {0}", - "NameSeasonUnknown": "Season Unknown", - "NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", + "ItemAddedWithName": "{0} foi adicionado à biblioteca", + "ItemRemovedWithName": "{0} foi removido da biblioteca", + "LabelIpAddressValue": "Endereço IP: {0}", + "LabelRunningTimeValue": "Duração: {0}", + "Latest": "Mais Recente", + "MessageApplicationUpdated": "O servidor Jellyfin foi atualizado", + "MessageApplicationUpdatedTo": "O servidor Jellyfin foi atualizado para a versão {0}", + "MessageNamedServerConfigurationUpdatedWithValue": "Configurações de servidor na secção {0} foram atualizadas", + "MessageServerConfigurationUpdated": "A configuração do servidor foi atualizada", + "MixedContent": "Conteúdo Misto", + "Movies": "Filmes", + "Music": "Música", + "MusicVideos": "Videoclips", + "NameInstallFailed": "{0} falha na instalação", + "NameSeasonNumber": "Temporada {0}", + "NameSeasonUnknown": "Temporada Desconhecida", + "NewVersionIsAvailable": "Está disponível para transferência uma nova versão do servidor Jellyfin.", + "NotificationOptionApplicationUpdateAvailable": "Atualização de aplicação disponível", + "NotificationOptionApplicationUpdateInstalled": "Atualização de aplicação instalada", + "NotificationOptionAudioPlayback": "Reprodução Iniciada", + "NotificationOptionAudioPlaybackStopped": "Reprodução Parada", "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionServerRestartRequired": "Server restart required", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "Photos": "Photos", - "Playlists": "Playlists", - "Plugin": "Plugin", - "PluginInstalledWithName": "{0} was installed", - "PluginUninstalledWithName": "{0} was uninstalled", - "PluginUpdatedWithName": "{0} was updated", + "NotificationOptionInstallationFailed": "Falha na instalação", + "NotificationOptionNewLibraryContent": "Novo conteúdo adicionado", + "NotificationOptionPluginError": "Falha na extensão", + "NotificationOptionPluginInstalled": "Extensão instalada", + "NotificationOptionPluginUninstalled": "Extensão desinstalada", + "NotificationOptionPluginUpdateInstalled": "Extensão atualizada", + "NotificationOptionServerRestartRequired": "Necessário reiniciar o servidor", + "NotificationOptionTaskFailed": "Falha em tarefa agendada", + "NotificationOptionUserLockedOut": "Utilizador bloqueado", + "NotificationOptionVideoPlayback": "Reprodução do vídeo iniciada", + "NotificationOptionVideoPlaybackStopped": "Reprodução do vídeo parada", + "Photos": "Fotografias", + "Playlists": "Listas de Reprodução", + "Plugin": "Extensão", + "PluginInstalledWithName": "{0} foi instalado", + "PluginUninstalledWithName": "{0} foi desinstalado", + "PluginUpdatedWithName": "{0} foi atualizado", "ProviderValue": "Provider: {0}", - "ScheduledTaskFailedWithName": "{0} failed", - "ScheduledTaskStartedWithName": "{0} started", - "ServerNameNeedsToBeRestarted": "{0} needs to be restarted", - "Shows": "Shows", - "Songs": "Songs", - "StartupEmbyServerIsLoading": "Jellyfin Server is loading. Please try again shortly.", + "ScheduledTaskFailedWithName": "{0} falhou", + "ScheduledTaskStartedWithName": "{0} iniciou", + "ServerNameNeedsToBeRestarted": "{0} necessita de ser reiniciado", + "Shows": "Séries", + "Songs": "Músicas", + "StartupEmbyServerIsLoading": "O servidor Jellyfin está a iniciar. Tente novamente mais tarde.", "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "Sync": "Sync", - "System": "System", - "TvShows": "TV Shows", - "User": "User", - "UserCreatedWithName": "User {0} has been created", - "UserDeletedWithName": "User {0} has been deleted", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserOnlineFromDevice": "{0} is online from {1}", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserPolicyUpdatedWithName": "User policy has been updated for {0}", - "UserStartedPlayingItemWithValues": "{0} is playing {1} on {2}", - "UserStoppedPlayingItemWithValues": "{0} has finished playing {1} on {2}", - "ValueHasBeenAddedToLibrary": "{0} has been added to your media library", - "ValueSpecialEpisodeName": "Especial - {0}", - "VersionNumber": "Version {0}" + "SubtitleDownloadFailureFromForItem": "Falha na transferência de legendas a partir de {0} para {1}", + "SubtitlesDownloadedForItem": "Transferidas legendas para {0}", + "Sync": "Sincronização", + "System": "Sistema", + "TvShows": "Programas TV", + "User": "Utilizador", + "UserCreatedWithName": "Utilizador {0} criado", + "UserDeletedWithName": "Utilizador {0} apagado", + "UserDownloadingItemWithValues": "{0} está a transferir {1}", + "UserLockedOutWithName": "Utilizador {0} bloqueado", + "UserOfflineFromDevice": "{0} desligou-se a partir de {1}", + "UserOnlineFromDevice": "{0} ligou-se a partir de {1}", + "UserPasswordChangedWithName": "Palavra-passe alterada para o utilizador {0}", + "UserPolicyUpdatedWithName": "Política de utilizador alterada para {0}", + "UserStartedPlayingItemWithValues": "{0} está a reproduzir {1} em {2}", + "UserStoppedPlayingItemWithValues": "{0} terminou a reprodução de {1} em {2}", + "ValueHasBeenAddedToLibrary": "{0} foi adicionado à sua biblioteca multimédia", + "ValueSpecialEpisodeName": "Especial - {0}", + "VersionNumber": "Versão {0}" } diff --git a/Emby.Server.Implementations/Localization/Core/sk.json b/Emby.Server.Implementations/Localization/Core/sk.json index bc7e7184e..6eade7942 100644 --- a/Emby.Server.Implementations/Localization/Core/sk.json +++ b/Emby.Server.Implementations/Localization/Core/sk.json @@ -1,6 +1,6 @@ { "Albums": "Albumy", - "AppDeviceValues": "Aplikácia: {0}, Zariadenie: {1}", + "AppDeviceValues": "Apka: {0}, Zariadenie: {1}", "Application": "Aplikácia", "Artists": "Umelci", "AuthenticationSucceededWithUserName": "{0} úspešne overený", @@ -9,14 +9,14 @@ "Channels": "Kanály", "ChapterNameValue": "Kapitola {0}", "Collections": "Zbierky", - "DeviceOfflineWithName": "{0} je odpojený", + "DeviceOfflineWithName": "{0} sa odpojil", "DeviceOnlineWithName": "{0} je pripojený", "FailedLoginAttemptWithUserName": "Neúspešný pokus o prihlásenie z {0}", "Favorites": "Obľúbené", "Folders": "Priečinky", "Genres": "Žánre", "HeaderAlbumArtists": "Album Artists", - "HeaderCameraUploads": "Camera Uploads", + "HeaderCameraUploads": "Nahrané fotografie", "HeaderContinueWatching": "Pokračujte v pozeraní", "HeaderFavoriteAlbums": "Obľúbené albumy", "HeaderFavoriteArtists": "Obľúbení umelci", @@ -25,7 +25,7 @@ "HeaderFavoriteSongs": "Obľúbené pesničky", "HeaderLiveTV": "Živá TV", "HeaderNextUp": "Nasleduje", - "HeaderRecordingGroups": "Recording Groups", + "HeaderRecordingGroups": "Skupiny nahrávok", "HomeVideos": "Domáce videá", "Inherit": "Zdediť", "ItemAddedWithName": "{0} bol pridaný do knižnice", @@ -34,17 +34,17 @@ "LabelRunningTimeValue": "Dĺžka: {0}", "Latest": "Najnovšie", "MessageApplicationUpdated": "Jellyfin Server bol aktualizovaný", - "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", + "MessageApplicationUpdatedTo": "Jellyfin Server bol aktualizový na {0}", "MessageNamedServerConfigurationUpdatedWithValue": "Sekcia {0} konfigurácie servera bola aktualizovaná", - "MessageServerConfigurationUpdated": "Konfigurácia servera aktualizovaná", + "MessageServerConfigurationUpdated": "Konfigurácia servera bola aktualizovaná", "MixedContent": "Zmiešaný obsah", "Movies": "Filmy", "Music": "Hudba", "MusicVideos": "Hudobné videá", - "NameInstallFailed": "{0} installation failed", + "NameInstallFailed": "Inštalácia {0} zlyhala", "NameSeasonNumber": "Sezóna {0}", "NameSeasonUnknown": "Neznáma sezóna", - "NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.", + "NewVersionIsAvailable": "Nová verzia Jellyfin Server je dostupná na stiahnutie.", "NotificationOptionApplicationUpdateAvailable": "Je dostupná aktualizácia aplikácie", "NotificationOptionApplicationUpdateInstalled": "Aktualizácia aplikácie nainštalovaná", "NotificationOptionAudioPlayback": "Spustené prehrávanie audia", @@ -70,16 +70,16 @@ "ProviderValue": "Poskytovateľ: {0}", "ScheduledTaskFailedWithName": "{0} zlyhalo", "ScheduledTaskStartedWithName": "{0} started", - "ServerNameNeedsToBeRestarted": "{0} needs to be restarted", + "ServerNameNeedsToBeRestarted": "{0} vyžaduje reštart", "Shows": "Series", "Songs": "Skladby", "StartupEmbyServerIsLoading": "Jellyfin Server sa spúšťa. Skúste to prosím o chvíľu znova.", "SubtitleDownloadFailureForItem": "Sťahovanie titulkov pre {0} zlyhalo", - "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", + "SubtitleDownloadFailureFromForItem": "Sťahovanie titulkov z {0} pre {1} zlyhalo", "SubtitlesDownloadedForItem": "Titulky pre {0} stiahnuté", - "Sync": "Sync", + "Sync": "Synchronizácia", "System": "Systém", - "TvShows": "TV Shows", + "TvShows": "TV seriály", "User": "Používateľ", "UserCreatedWithName": "Používateľ {0} bol vytvorený", "UserDeletedWithName": "Používateľ {0} bol vymazaný", @@ -91,7 +91,7 @@ "UserPolicyUpdatedWithName": "User policy has been updated for {0}", "UserStartedPlayingItemWithValues": "{0} spustil prehrávanie {1}", "UserStoppedPlayingItemWithValues": "{0} zastavil prehrávanie {1}", - "ValueHasBeenAddedToLibrary": "{0} has been added to your media library", + "ValueHasBeenAddedToLibrary": "{0} bolo pridané do vašej knižnice médií", "ValueSpecialEpisodeName": "Špeciál - {0}", "VersionNumber": "Verzia {0}" } diff --git a/Emby.Server.Implementations/Localization/Core/zh-CN.json b/Emby.Server.Implementations/Localization/Core/zh-CN.json index 6f7d362d3..63aa6a557 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-CN.json +++ b/Emby.Server.Implementations/Localization/Core/zh-CN.json @@ -5,7 +5,7 @@ "Artists": "艺术家", "AuthenticationSucceededWithUserName": "{0} 成功验证", "Books": "书籍", - "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", + "CameraImageUploadedFrom": "已从 {0} 上传了一张新的相机图像", "Channels": "频道", "ChapterNameValue": "章节 {0}", "Collections": "合集", @@ -44,7 +44,7 @@ "NameInstallFailed": "{0} 安装失败", "NameSeasonNumber": "季 {0}", "NameSeasonUnknown": "未知季", - "NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.", + "NewVersionIsAvailable": "Jellyfin Server 有新版本可以下载。", "NotificationOptionApplicationUpdateAvailable": "有可用的应用程序更新", "NotificationOptionApplicationUpdateInstalled": "应用程序更新已安装", "NotificationOptionAudioPlayback": "音频开始播放", @@ -75,7 +75,7 @@ "Songs": "歌曲", "StartupEmbyServerIsLoading": "Jellyfin 服务器加载中。请稍后再试。", "SubtitleDownloadFailureForItem": "为 {0} 下载字幕失败", - "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", + "SubtitleDownloadFailureFromForItem": "无法从 {0} 下载 {1} 的字幕", "SubtitlesDownloadedForItem": "已为 {0} 下载了字幕", "Sync": "同步", "System": "系统", @@ -91,7 +91,7 @@ "UserPolicyUpdatedWithName": "用户协议已经被更新为 {0}", "UserStartedPlayingItemWithValues": "{0} 已开始播放 {1}", "UserStoppedPlayingItemWithValues": "{0} 已停止播放 {1}", - "ValueHasBeenAddedToLibrary": "{0} has been added to your media library", + "ValueHasBeenAddedToLibrary": "{0} 已添加至您的媒体库中", "ValueSpecialEpisodeName": "特典 - {0}", "VersionNumber": "版本 {0}" } diff --git a/Emby.Server.Implementations/Net/SocketFactory.cs b/Emby.Server.Implementations/Net/SocketFactory.cs index 492f48abe..42ffa4e22 100644 --- a/Emby.Server.Implementations/Net/SocketFactory.cs +++ b/Emby.Server.Implementations/Net/SocketFactory.cs @@ -16,14 +16,14 @@ namespace Emby.Server.Implementations.Net // but that wasn't really the point so kept to YAGNI principal for now, even if the // interfaces are a bit ugly, specific and make assumptions. - public ISocket CreateTcpSocket(IpAddressInfo remoteAddress, int remotePort) + public ISocket CreateTcpSocket(IPAddress remoteAddress, int remotePort) { if (remotePort < 0) { throw new ArgumentException("remotePort cannot be less than zero.", nameof(remotePort)); } - var addressFamily = remoteAddress.AddressFamily == IpAddressFamily.InterNetwork + var addressFamily = remoteAddress.AddressFamily == AddressFamily.InterNetwork ? AddressFamily.InterNetwork : AddressFamily.InterNetworkV6; @@ -40,7 +40,7 @@ namespace Emby.Server.Implementations.Net try { - return new UdpSocket(retVal, new IpEndPointInfo(remoteAddress, remotePort)); + return new UdpSocket(retVal, new IPEndPoint(remoteAddress, remotePort)); } catch { @@ -102,7 +102,7 @@ namespace Emby.Server.Implementations.Net /// Creates a new UDP acceptSocket that is a member of the SSDP multicast local admin group and binds it to the specified local port. /// </summary> /// <returns>An implementation of the <see cref="ISocket"/> interface used by RSSDP components to perform acceptSocket operations.</returns> - public ISocket CreateSsdpUdpSocket(IpAddressInfo localIpAddress, int localPort) + public ISocket CreateSsdpUdpSocket(IPAddress localIpAddress, int localPort) { if (localPort < 0) { @@ -115,10 +115,8 @@ namespace Emby.Server.Implementations.Net retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4); - var localIp = NetworkManager.ToIPAddress(localIpAddress); - - retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), localIp)); - return new UdpSocket(retVal, localPort, localIp); + retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), localIpAddress)); + return new UdpSocket(retVal, localPort, localIpAddress); } catch { diff --git a/Emby.Server.Implementations/Net/UdpSocket.cs b/Emby.Server.Implementations/Net/UdpSocket.cs index 6c55085c8..2908ee9af 100644 --- a/Emby.Server.Implementations/Net/UdpSocket.cs +++ b/Emby.Server.Implementations/Net/UdpSocket.cs @@ -19,7 +19,7 @@ namespace Emby.Server.Implementations.Net public Socket Socket => _socket; - public IpAddressInfo LocalIPAddress { get; } + public IPAddress LocalIPAddress { get; } private readonly SocketAsyncEventArgs _receiveSocketAsyncEventArgs = new SocketAsyncEventArgs() { @@ -40,7 +40,7 @@ namespace Emby.Server.Implementations.Net _socket = socket; _localPort = localPort; - LocalIPAddress = NetworkManager.ToIpAddressInfo(ip); + LocalIPAddress = ip; _socket.Bind(new IPEndPoint(ip, _localPort)); @@ -71,7 +71,7 @@ namespace Emby.Server.Implementations.Net { Buffer = e.Buffer, ReceivedBytes = e.BytesTransferred, - RemoteEndPoint = ToIpEndPointInfo(e.RemoteEndPoint as IPEndPoint), + RemoteEndPoint = e.RemoteEndPoint as IPEndPoint, LocalIPAddress = LocalIPAddress }); } @@ -100,12 +100,12 @@ namespace Emby.Server.Implementations.Net } } - public UdpSocket(Socket socket, IpEndPointInfo endPoint) + public UdpSocket(Socket socket, IPEndPoint endPoint) { if (socket == null) throw new ArgumentNullException(nameof(socket)); _socket = socket; - _socket.Connect(NetworkManager.ToIPEndPoint(endPoint)); + _socket.Connect(endPoint); InitReceiveSocketAsyncEventArgs(); } @@ -140,7 +140,7 @@ namespace Emby.Server.Implementations.Net return new SocketReceiveResult { ReceivedBytes = receivedBytes, - RemoteEndPoint = ToIpEndPointInfo((IPEndPoint)remoteEndPoint), + RemoteEndPoint = (IPEndPoint)remoteEndPoint, Buffer = buffer, LocalIPAddress = LocalIPAddress }; @@ -191,7 +191,7 @@ namespace Emby.Server.Implementations.Net return ReceiveAsync(buffer, 0, buffer.Length, cancellationToken); } - public Task SendToAsync(byte[] buffer, int offset, int size, IpEndPointInfo endPoint, CancellationToken cancellationToken) + public Task SendToAsync(byte[] buffer, int offset, int size, IPEndPoint endPoint, CancellationToken cancellationToken) { ThrowIfDisposed(); @@ -227,13 +227,11 @@ namespace Emby.Server.Implementations.Net return taskCompletion.Task; } - public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, IpEndPointInfo endPoint, AsyncCallback callback, object state) + public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, IPEndPoint endPoint, AsyncCallback callback, object state) { ThrowIfDisposed(); - var ipEndPoint = NetworkManager.ToIPEndPoint(endPoint); - - return _socket.BeginSendTo(buffer, offset, size, SocketFlags.None, ipEndPoint, callback, state); + return _socket.BeginSendTo(buffer, offset, size, SocketFlags.None, endPoint, callback, state); } public int EndSendTo(IAsyncResult result) @@ -268,15 +266,5 @@ namespace Emby.Server.Implementations.Net _disposed = true; } - - private static IpEndPointInfo ToIpEndPointInfo(IPEndPoint endpoint) - { - if (endpoint == null) - { - return null; - } - - return NetworkManager.ToIpEndPointInfo(endpoint); - } } } diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs index c102f9eb5..3cacacf07 100644 --- a/Emby.Server.Implementations/Networking/NetworkManager.cs +++ b/Emby.Server.Implementations/Networking/NetworkManager.cs @@ -9,55 +9,38 @@ using System.Threading.Tasks; using MediaBrowser.Common.Net; using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; -using MediaBrowser.Model.System; using Microsoft.Extensions.Logging; -using OperatingSystem = MediaBrowser.Common.System.OperatingSystem; namespace Emby.Server.Implementations.Networking { public class NetworkManager : INetworkManager { - protected ILogger Logger { get; private set; } + private readonly ILogger _logger; - public event EventHandler NetworkChanged; - public Func<string[]> LocalSubnetsFn { get; set; } + private IPAddress[] _localIpAddresses; + private readonly object _localIpAddressSyncLock = new object(); - public NetworkManager(ILoggerFactory loggerFactory) + public NetworkManager(ILogger<NetworkManager> logger) { - Logger = loggerFactory.CreateLogger(nameof(NetworkManager)); - - // In FreeBSD these events cause a crash - if (OperatingSystem.Id != OperatingSystemId.BSD) - { - try - { - NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged; - } - catch (Exception ex) - { - Logger.LogError(ex, "Error binding to NetworkAddressChanged event"); - } + _logger = logger; - try - { - NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged; - } - catch (Exception ex) - { - Logger.LogError(ex, "Error binding to NetworkChange_NetworkAvailabilityChanged event"); - } - } + NetworkChange.NetworkAddressChanged += OnNetworkAddressChanged; + NetworkChange.NetworkAvailabilityChanged += OnNetworkAvailabilityChanged; } - private void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e) + public Func<string[]> LocalSubnetsFn { get; set; } + + public event EventHandler NetworkChanged; + + private void OnNetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e) { - Logger.LogDebug("NetworkAvailabilityChanged"); + _logger.LogDebug("NetworkAvailabilityChanged"); OnNetworkChanged(); } - private void NetworkChange_NetworkAddressChanged(object sender, EventArgs e) + private void OnNetworkAddressChanged(object sender, EventArgs e) { - Logger.LogDebug("NetworkAddressChanged"); + _logger.LogDebug("NetworkAddressChanged"); OnNetworkChanged(); } @@ -68,39 +51,35 @@ namespace Emby.Server.Implementations.Networking _localIpAddresses = null; _macAddresses = null; } + if (NetworkChanged != null) { NetworkChanged(this, EventArgs.Empty); } } - private IpAddressInfo[] _localIpAddresses; - private readonly object _localIpAddressSyncLock = new object(); - - public IpAddressInfo[] GetLocalIpAddresses(bool ignoreVirtualInterface = true) + public IPAddress[] GetLocalIpAddresses(bool ignoreVirtualInterface = true) { lock (_localIpAddressSyncLock) { if (_localIpAddresses == null) { - var addresses = GetLocalIpAddressesInternal(ignoreVirtualInterface).Result.Select(ToIpAddressInfo).ToArray(); + var addresses = GetLocalIpAddressesInternal(ignoreVirtualInterface).ToArray(); _localIpAddresses = addresses; - - return addresses; } + return _localIpAddresses; } } - private async Task<List<IPAddress>> GetLocalIpAddressesInternal(bool ignoreVirtualInterface) + private List<IPAddress> GetLocalIpAddressesInternal(bool ignoreVirtualInterface) { - var list = GetIPsDefault(ignoreVirtualInterface) - .ToList(); + var list = GetIPsDefault(ignoreVirtualInterface).ToList(); if (list.Count == 0) { - list.AddRange(await GetLocalIpAddressesFallback().ConfigureAwait(false)); + list = GetLocalIpAddressesFallback().GetAwaiter().GetResult().ToList(); } var listClone = list.ToList(); @@ -351,13 +330,13 @@ namespace Emby.Server.Implementations.Networking try { var host = uri.DnsSafeHost; - Logger.LogDebug("Resolving host {0}", host); + _logger.LogDebug("Resolving host {0}", host); address = GetIpAddresses(host).Result.FirstOrDefault(); if (address != null) { - Logger.LogDebug("{0} resolved to {1}", host, address); + _logger.LogDebug("{0} resolved to {1}", host, address); return IsInLocalNetworkInternal(address.ToString(), false); } @@ -368,7 +347,7 @@ namespace Emby.Server.Implementations.Networking } catch (Exception ex) { - Logger.LogError(ex, "Error resolving hostname"); + _logger.LogError(ex, "Error resolving hostname"); } } } @@ -381,56 +360,41 @@ namespace Emby.Server.Implementations.Networking return Dns.GetHostAddressesAsync(hostName); } - private List<IPAddress> GetIPsDefault(bool ignoreVirtualInterface) + private IEnumerable<IPAddress> GetIPsDefault(bool ignoreVirtualInterface) { - NetworkInterface[] interfaces; + IEnumerable<NetworkInterface> interfaces; try { - var validStatuses = new[] { OperationalStatus.Up, OperationalStatus.Unknown }; - interfaces = NetworkInterface.GetAllNetworkInterfaces() - .Where(i => validStatuses.Contains(i.OperationalStatus)) - .ToArray(); + .Where(x => x.OperationalStatus == OperationalStatus.Up + || x.OperationalStatus == OperationalStatus.Unknown); } - catch (Exception ex) + catch (NetworkInformationException ex) { - Logger.LogError(ex, "Error in GetAllNetworkInterfaces"); - return new List<IPAddress>(); + _logger.LogError(ex, "Error in GetAllNetworkInterfaces"); + return Enumerable.Empty<IPAddress>(); } return interfaces.SelectMany(network => { + var ipProperties = network.GetIPProperties(); - try - { - // suppress logging because it might be causing nas device wake up - //logger.LogDebug("Querying interface: {0}. Type: {1}. Status: {2}", network.Name, network.NetworkInterfaceType, network.OperationalStatus); - - var ipProperties = network.GetIPProperties(); - - // Try to exclude virtual adapters - // http://stackoverflow.com/questions/8089685/c-sharp-finding-my-machines-local-ip-address-and-not-the-vms - var addr = ipProperties.GatewayAddresses.FirstOrDefault(); - if (addr == null || ignoreVirtualInterface && string.Equals(addr.Address.ToString(), "0.0.0.0", StringComparison.OrdinalIgnoreCase)) - { - return new List<IPAddress>(); - } - - return ipProperties.UnicastAddresses - .Select(i => i.Address) - .Where(i => i.AddressFamily == AddressFamily.InterNetwork || i.AddressFamily == AddressFamily.InterNetworkV6) - .ToList(); - } - catch (Exception ex) + // Try to exclude virtual adapters + // http://stackoverflow.com/questions/8089685/c-sharp-finding-my-machines-local-ip-address-and-not-the-vms + var addr = ipProperties.GatewayAddresses.FirstOrDefault(); + if (addr == null + || (ignoreVirtualInterface + && (addr.Address.Equals(IPAddress.Any) || addr.Address.Equals(IPAddress.IPv6Any)))) { - Logger.LogError(ex, "Error querying network interface"); - return new List<IPAddress>(); + return Enumerable.Empty<IPAddress>(); } + return ipProperties.UnicastAddresses + .Select(i => i.Address) + .Where(i => i.AddressFamily == AddressFamily.InterNetwork || i.AddressFamily == AddressFamily.InterNetworkV6); }).GroupBy(i => i.ToString()) - .Select(x => x.First()) - .ToList(); + .Select(x => x.First()); } private static async Task<IEnumerable<IPAddress>> GetLocalIpAddressesFallback() @@ -612,32 +576,10 @@ namespace Emby.Server.Implementations.Networking return hosts[0]; } - public IpAddressInfo ParseIpAddress(string ipAddress) - { - if (TryParseIpAddress(ipAddress, out var info)) - { - return info; - } - - throw new ArgumentException("Invalid ip address: " + ipAddress); - } - - public bool TryParseIpAddress(string ipAddress, out IpAddressInfo ipAddressInfo) + public bool IsInSameSubnet(IPAddress address1, IPAddress address2, IPAddress subnetMask) { - if (IPAddress.TryParse(ipAddress, out var address)) - { - ipAddressInfo = ToIpAddressInfo(address); - return true; - } - - ipAddressInfo = null; - return false; - } - - public bool IsInSameSubnet(IpAddressInfo address1, IpAddressInfo address2, IpAddressInfo subnetMask) - { - IPAddress network1 = GetNetworkAddress(ToIPAddress(address1), ToIPAddress(subnetMask)); - IPAddress network2 = GetNetworkAddress(ToIPAddress(address2), ToIPAddress(subnetMask)); + IPAddress network1 = GetNetworkAddress(address1, subnetMask); + IPAddress network2 = GetNetworkAddress(address2, subnetMask); return network1.Equals(network2); } @@ -656,13 +598,13 @@ namespace Emby.Server.Implementations.Networking { broadcastAddress[i] = (byte)(ipAdressBytes[i] & (subnetMaskBytes[i])); } + return new IPAddress(broadcastAddress); } - public IpAddressInfo GetLocalIpSubnetMask(IpAddressInfo address) + public IPAddress GetLocalIpSubnetMask(IPAddress address) { NetworkInterface[] interfaces; - IPAddress ipaddress = ToIPAddress(address); try { @@ -674,7 +616,7 @@ namespace Emby.Server.Implementations.Networking } catch (Exception ex) { - Logger.LogError(ex, "Error in GetAllNetworkInterfaces"); + _logger.LogError(ex, "Error in GetAllNetworkInterfaces"); return null; } @@ -684,83 +626,15 @@ namespace Emby.Server.Implementations.Networking { foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses) { - if (ip.Address.Equals(ipaddress) && ip.IPv4Mask != null) + if (ip.Address.Equals(address) && ip.IPv4Mask != null) { - return ToIpAddressInfo(ip.IPv4Mask); + return ip.IPv4Mask; } } } } - return null; - } - - public static IpEndPointInfo ToIpEndPointInfo(IPEndPoint endpoint) - { - if (endpoint == null) - { - return null; - } - - return new IpEndPointInfo(ToIpAddressInfo(endpoint.Address), endpoint.Port); - } - - public static IPEndPoint ToIPEndPoint(IpEndPointInfo endpoint) - { - if (endpoint == null) - { - return null; - } - - return new IPEndPoint(ToIPAddress(endpoint.IpAddress), endpoint.Port); - } - public static IPAddress ToIPAddress(IpAddressInfo address) - { - if (address.Equals(IpAddressInfo.Any)) - { - return IPAddress.Any; - } - if (address.Equals(IpAddressInfo.IPv6Any)) - { - return IPAddress.IPv6Any; - } - if (address.Equals(IpAddressInfo.Loopback)) - { - return IPAddress.Loopback; - } - if (address.Equals(IpAddressInfo.IPv6Loopback)) - { - return IPAddress.IPv6Loopback; - } - - return IPAddress.Parse(address.Address); - } - - public static IpAddressInfo ToIpAddressInfo(IPAddress address) - { - if (address.Equals(IPAddress.Any)) - { - return IpAddressInfo.Any; - } - if (address.Equals(IPAddress.IPv6Any)) - { - return IpAddressInfo.IPv6Any; - } - if (address.Equals(IPAddress.Loopback)) - { - return IpAddressInfo.Loopback; - } - if (address.Equals(IPAddress.IPv6Loopback)) - { - return IpAddressInfo.IPv6Loopback; - } - return new IpAddressInfo(address.ToString(), address.AddressFamily == AddressFamily.InterNetworkV6 ? IpAddressFamily.InterNetworkV6 : IpAddressFamily.InterNetwork); - } - - public async Task<IpAddressInfo[]> GetHostAddressesAsync(string host) - { - var addresses = await Dns.GetHostAddressesAsync(host).ConfigureAwait(false); - return addresses.Select(ToIpAddressInfo).ToArray(); + return null; } /// <summary> diff --git a/Emby.Server.Implementations/Udp/UdpServer.cs b/Emby.Server.Implementations/Udp/UdpServer.cs index e7cda2993..185a282ac 100644 --- a/Emby.Server.Implementations/Udp/UdpServer.cs +++ b/Emby.Server.Implementations/Udp/UdpServer.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -25,7 +26,7 @@ namespace Emby.Server.Implementations.Udp private bool _isDisposed; - private readonly List<Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>> _responders = new List<Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>>(); + private readonly List<Tuple<string, bool, Func<string, IPEndPoint, Encoding, CancellationToken, Task>>> _responders = new List<Tuple<string, bool, Func<string, IPEndPoint, Encoding, CancellationToken, Task>>>(); private readonly IServerApplicationHost _appHost; private readonly IJsonSerializer _json; @@ -43,9 +44,9 @@ namespace Emby.Server.Implementations.Udp AddMessageResponder("who is JellyfinServer?", true, RespondToV2Message); } - private void AddMessageResponder(string message, bool isSubstring, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task> responder) + private void AddMessageResponder(string message, bool isSubstring, Func<string, IPEndPoint, Encoding, CancellationToken, Task> responder) { - _responders.Add(new Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>(message, isSubstring, responder)); + _responders.Add(new Tuple<string, bool, Func<string, IPEndPoint, Encoding, CancellationToken, Task>>(message, isSubstring, responder)); } /// <summary> @@ -83,7 +84,7 @@ namespace Emby.Server.Implementations.Udp } } - private Tuple<string, Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>> GetResponder(byte[] buffer, int bytesReceived, Encoding encoding) + private Tuple<string, Tuple<string, bool, Func<string, IPEndPoint, Encoding, CancellationToken, Task>>> GetResponder(byte[] buffer, int bytesReceived, Encoding encoding) { var text = encoding.GetString(buffer, 0, bytesReceived); var responder = _responders.FirstOrDefault(i => @@ -99,10 +100,10 @@ namespace Emby.Server.Implementations.Udp { return null; } - return new Tuple<string, Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>>(text, responder); + return new Tuple<string, Tuple<string, bool, Func<string, IPEndPoint, Encoding, CancellationToken, Task>>>(text, responder); } - private async Task RespondToV2Message(string messageText, IpEndPointInfo endpoint, Encoding encoding, CancellationToken cancellationToken) + private async Task RespondToV2Message(string messageText, IPEndPoint endpoint, Encoding encoding, CancellationToken cancellationToken) { var parts = messageText.Split('|'); @@ -254,7 +255,7 @@ namespace Emby.Server.Implementations.Udp } } - public async Task SendAsync(byte[] bytes, IpEndPointInfo remoteEndPoint, CancellationToken cancellationToken) + public async Task SendAsync(byte[] bytes, IPEndPoint remoteEndPoint, CancellationToken cancellationToken) { if (_isDisposed) { diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 94308a98e..08c0983be 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -143,7 +143,7 @@ namespace Jellyfin.Server options, new ManagedFileSystem(_loggerFactory.CreateLogger<ManagedFileSystem>(), appPaths), new NullImageEncoder(), - new NetworkManager(_loggerFactory), + new NetworkManager(_loggerFactory.CreateLogger<NetworkManager>()), appConfig)) { await appHost.InitAsync(new ServiceCollection()).ConfigureAwait(false); diff --git a/MediaBrowser.Common/Net/HttpRequestOptions.cs b/MediaBrowser.Common/Net/HttpRequestOptions.cs index 0576a1a5d..76bd35e57 100644 --- a/MediaBrowser.Common/Net/HttpRequestOptions.cs +++ b/MediaBrowser.Common/Net/HttpRequestOptions.cs @@ -91,8 +91,6 @@ namespace MediaBrowser.Common.Net public bool EnableDefaultUserAgent { get; set; } - public bool AppendCharsetToMimeType { get; set; } - private string GetHeaderValue(string name) { RequestHeaders.TryGetValue(name, out var value); diff --git a/MediaBrowser.Common/Net/HttpResponseInfo.cs b/MediaBrowser.Common/Net/HttpResponseInfo.cs index cd9feabfe..d65ce897a 100644 --- a/MediaBrowser.Common/Net/HttpResponseInfo.cs +++ b/MediaBrowser.Common/Net/HttpResponseInfo.cs @@ -52,14 +52,21 @@ namespace MediaBrowser.Common.Net /// <value>The headers.</value> public HttpResponseHeaders Headers { get; set; } + /// <summary> + /// Gets or sets the content headers. + /// </summary> + /// <value>The content headers.</value> + public HttpContentHeaders ContentHeaders { get; set; } + public HttpResponseInfo() { } - public HttpResponseInfo(HttpResponseHeaders headers) + public HttpResponseInfo(HttpResponseHeaders headers, HttpContentHeaders contentHeader) { Headers = headers; + ContentHeaders = contentHeader; } public void Dispose() diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs index 34c6f5866..61f2bc2f9 100644 --- a/MediaBrowser.Common/Net/INetworkManager.cs +++ b/MediaBrowser.Common/Net/INetworkManager.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Net; using System.Threading.Tasks; using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; @@ -53,17 +54,12 @@ namespace MediaBrowser.Common.Net /// <returns><c>true</c> if [is in local network] [the specified endpoint]; otherwise, <c>false</c>.</returns> bool IsInLocalNetwork(string endpoint); - IpAddressInfo[] GetLocalIpAddresses(bool ignoreVirtualInterface); - - IpAddressInfo ParseIpAddress(string ipAddress); - - bool TryParseIpAddress(string ipAddress, out IpAddressInfo ipAddressInfo); - - Task<IpAddressInfo[]> GetHostAddressesAsync(string host); + IPAddress[] GetLocalIpAddresses(bool ignoreVirtualInterface); bool IsAddressInSubnets(string addressString, string[] subnets); - bool IsInSameSubnet(IpAddressInfo address1, IpAddressInfo address2, IpAddressInfo subnetMask); - IpAddressInfo GetLocalIpSubnetMask(IpAddressInfo address); + bool IsInSameSubnet(IPAddress address1, IPAddress address2, IPAddress subnetMask); + + IPAddress GetLocalIpSubnetMask(IPAddress address); } } diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 81b9ff0a5..3f8cc0b83 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; +using System.Net; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; -using MediaBrowser.Model.Net; using MediaBrowser.Model.System; namespace MediaBrowser.Controller @@ -59,7 +59,7 @@ namespace MediaBrowser.Controller /// Gets the local ip address. /// </summary> /// <value>The local ip address.</value> - Task<List<IpAddressInfo>> GetLocalIpAddresses(CancellationToken cancellationToken); + Task<List<IPAddress>> GetLocalIpAddresses(CancellationToken cancellationToken); /// <summary> /// Gets the local API URL. @@ -77,7 +77,7 @@ namespace MediaBrowser.Controller /// <summary> /// Gets the local API URL. /// </summary> - string GetLocalApiUrl(IpAddressInfo address); + string GetLocalApiUrl(IPAddress address); void LaunchUrl(string url); diff --git a/MediaBrowser.Controller/Resolvers/IResolverIgnoreRule.cs b/MediaBrowser.Controller/Resolvers/IResolverIgnoreRule.cs index b40cc157a..bb80e6025 100644 --- a/MediaBrowser.Controller/Resolvers/IResolverIgnoreRule.cs +++ b/MediaBrowser.Controller/Resolvers/IResolverIgnoreRule.cs @@ -8,6 +8,12 @@ namespace MediaBrowser.Controller.Resolvers /// </summary> public interface IResolverIgnoreRule { + /// <summary> + /// Checks whether or not the file should be ignored. + /// </summary> + /// <param name="fileInfo">The file information.</param> + /// <param name="parent">The parent BaseItem.</param> + /// <returns>True if the file should be ignored.</returns> bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent); } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 8677b363f..9ddfb9b01 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -425,7 +425,13 @@ namespace MediaBrowser.MediaEncoding.Subtitles var encodingParam = await GetSubtitleFileCharacterSet(inputPath, language, inputProtocol, cancellationToken).ConfigureAwait(false); - if (!string.IsNullOrEmpty(encodingParam)) + // FFmpeg automatically convert character encoding when it is UTF-16 + // If we specify character encoding, it rejects with "do not specify a character encoding" and "Unable to recode subtitle event" + if ((inputPath.EndsWith(".smi") || inputPath.EndsWith(".sami")) && (encodingParam == "UTF-16BE" || encodingParam == "UTF-16LE")) + { + encodingParam = ""; + } + else if (!string.IsNullOrEmpty(encodingParam)) { encodingParam = " -sub_charenc " + encodingParam; } diff --git a/MediaBrowser.Model/Dlna/UpnpDeviceInfo.cs b/MediaBrowser.Model/Dlna/UpnpDeviceInfo.cs index 4edbb503b..c443a8ad1 100644 --- a/MediaBrowser.Model/Dlna/UpnpDeviceInfo.cs +++ b/MediaBrowser.Model/Dlna/UpnpDeviceInfo.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using MediaBrowser.Model.Net; +using System.Net; namespace MediaBrowser.Model.Dlna { @@ -8,7 +8,7 @@ namespace MediaBrowser.Model.Dlna { public Uri Location { get; set; } public Dictionary<string, string> Headers { get; set; } - public IpAddressInfo LocalIpAddress { get; set; } + public IPAddress LocalIpAddress { get; set; } public int LocalPort { get; set; } } } diff --git a/MediaBrowser.Model/Net/ISocket.cs b/MediaBrowser.Model/Net/ISocket.cs index 992ccb49b..f80de5524 100644 --- a/MediaBrowser.Model/Net/ISocket.cs +++ b/MediaBrowser.Model/Net/ISocket.cs @@ -1,4 +1,5 @@ using System; +using System.Net; using System.Threading; using System.Threading.Tasks; @@ -9,7 +10,7 @@ namespace MediaBrowser.Model.Net /// </summary> public interface ISocket : IDisposable { - IpAddressInfo LocalIPAddress { get; } + IPAddress LocalIPAddress { get; } Task<SocketReceiveResult> ReceiveAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken); @@ -21,6 +22,6 @@ namespace MediaBrowser.Model.Net /// <summary> /// Sends a UDP message to a particular end point (uni or multicast). /// </summary> - Task SendToAsync(byte[] buffer, int offset, int bytes, IpEndPointInfo endPoint, CancellationToken cancellationToken); + Task SendToAsync(byte[] buffer, int offset, int bytes, IPEndPoint endPoint, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Model/Net/ISocketFactory.cs b/MediaBrowser.Model/Net/ISocketFactory.cs index 69fe134bc..e58f4cc14 100644 --- a/MediaBrowser.Model/Net/ISocketFactory.cs +++ b/MediaBrowser.Model/Net/ISocketFactory.cs @@ -1,4 +1,5 @@ using System.IO; +using System.Net; namespace MediaBrowser.Model.Net { @@ -8,7 +9,7 @@ namespace MediaBrowser.Model.Net public interface ISocketFactory { /// <summary> - /// Createa a new unicast socket using the specified local port number. + /// Creates a new unicast socket using the specified local port number. /// </summary> /// <param name="localPort">The local port to bind to.</param> /// <returns>A <see cref="ISocket"/> implementation.</returns> @@ -16,15 +17,15 @@ namespace MediaBrowser.Model.Net ISocket CreateUdpBroadcastSocket(int localPort); - ISocket CreateTcpSocket(IpAddressInfo remoteAddress, int remotePort); + ISocket CreateTcpSocket(IPAddress remoteAddress, int remotePort); /// <summary> - /// Createa a new unicast socket using the specified local port number. + /// Creates a new unicast socket using the specified local port number. /// </summary> - ISocket CreateSsdpUdpSocket(IpAddressInfo localIp, int localPort); + ISocket CreateSsdpUdpSocket(IPAddress localIp, int localPort); /// <summary> - /// Createa a new multicast socket using the specified multicast IP address, multicast time to live and local port. + /// Creates a new multicast socket using the specified multicast IP address, multicast time to live and local port. /// </summary> /// <param name="ipAddress">The multicast IP address to bind to.</param> /// <param name="multicastTimeToLive">The multicast time to live value. Actually a maximum number of network hops for UDP packets.</param> diff --git a/MediaBrowser.Model/Net/IpAddressInfo.cs b/MediaBrowser.Model/Net/IpAddressInfo.cs deleted file mode 100644 index 87fa55bca..000000000 --- a/MediaBrowser.Model/Net/IpAddressInfo.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; - -namespace MediaBrowser.Model.Net -{ - public class IpAddressInfo - { - public static IpAddressInfo Any = new IpAddressInfo("0.0.0.0", IpAddressFamily.InterNetwork); - public static IpAddressInfo IPv6Any = new IpAddressInfo("00000000000000000000", IpAddressFamily.InterNetworkV6); - public static IpAddressInfo Loopback = new IpAddressInfo("127.0.0.1", IpAddressFamily.InterNetwork); - public static IpAddressInfo IPv6Loopback = new IpAddressInfo("::1", IpAddressFamily.InterNetworkV6); - - public string Address { get; set; } - public IpAddressInfo SubnetMask { get; set; } - public IpAddressFamily AddressFamily { get; set; } - - public IpAddressInfo(string address, IpAddressFamily addressFamily) - { - Address = address; - AddressFamily = addressFamily; - } - - public bool Equals(IpAddressInfo address) - { - return string.Equals(address.Address, Address, StringComparison.OrdinalIgnoreCase); - } - - public override string ToString() - { - return Address; - } - } - - public enum IpAddressFamily - { - InterNetwork, - InterNetworkV6 - } -} diff --git a/MediaBrowser.Model/Net/IpEndPointInfo.cs b/MediaBrowser.Model/Net/IpEndPointInfo.cs deleted file mode 100644 index f8c125144..000000000 --- a/MediaBrowser.Model/Net/IpEndPointInfo.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Globalization; - -namespace MediaBrowser.Model.Net -{ - public class IpEndPointInfo - { - public IpAddressInfo IpAddress { get; set; } - - public int Port { get; set; } - - public IpEndPointInfo() - { - - } - - public IpEndPointInfo(IpAddressInfo address, int port) - { - IpAddress = address; - Port = port; - } - - public override string ToString() - { - var ipAddresString = IpAddress == null ? string.Empty : IpAddress.ToString(); - - return ipAddresString + ":" + Port.ToString(CultureInfo.InvariantCulture); - } - } -} diff --git a/MediaBrowser.Model/Net/SocketReceiveResult.cs b/MediaBrowser.Model/Net/SocketReceiveResult.cs index 8c394f7c7..cd7a2e55f 100644 --- a/MediaBrowser.Model/Net/SocketReceiveResult.cs +++ b/MediaBrowser.Model/Net/SocketReceiveResult.cs @@ -1,3 +1,5 @@ +using System.Net; + namespace MediaBrowser.Model.Net { /// <summary> @@ -18,7 +20,7 @@ namespace MediaBrowser.Model.Net /// <summary> /// The <see cref="IpEndPointInfo"/> the data was received from. /// </summary> - public IpEndPointInfo RemoteEndPoint { get; set; } - public IpAddressInfo LocalIPAddress { get; set; } + public IPEndPoint RemoteEndPoint { get; set; } + public IPAddress LocalIPAddress { get; set; } } } diff --git a/MediaBrowser.WebDashboard/jellyfin-web b/MediaBrowser.WebDashboard/jellyfin-web -Subproject c9e70d95643e84437189dd500b0380ec0fbbf65 +Subproject 1d0fd79eb1e4d0bf6a9f62f769a951970383bcf diff --git a/Mono.Nat/Upnp/Messages/UpnpMessage.cs b/Mono.Nat/Upnp/Messages/UpnpMessage.cs index 1151dd997..ade9df50b 100644 --- a/Mono.Nat/Upnp/Messages/UpnpMessage.cs +++ b/Mono.Nat/Upnp/Messages/UpnpMessage.cs @@ -57,10 +57,9 @@ namespace Mono.Nat.Upnp req.Url = ss; req.EnableKeepAlive = false; req.RequestContentType = "text/xml"; - req.AppendCharsetToMimeType = true; req.RequestHeaders.Add("SOAPACTION", "\"" + device.ServiceType + "#" + upnpMethod + "\""); - string bodyString = "<s:Envelope " + req.RequestContent = "<s:Envelope " + "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " + "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" + "<s:Body>" @@ -70,8 +69,6 @@ namespace Mono.Nat.Upnp + "</u:" + upnpMethod + ">" + "</s:Body>" + "</s:Envelope>\r\n\r\n"; - - req.RequestContentBytes = System.Text.Encoding.UTF8.GetBytes(bodyString); return req; } diff --git a/RSSDP/DeviceAvailableEventArgs.cs b/RSSDP/DeviceAvailableEventArgs.cs index 9106e27e5..21ac7c631 100644 --- a/RSSDP/DeviceAvailableEventArgs.cs +++ b/RSSDP/DeviceAvailableEventArgs.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; -using MediaBrowser.Model.Net; +using System.Net; namespace Rssdp { @@ -11,12 +8,12 @@ namespace Rssdp /// </summary> public sealed class DeviceAvailableEventArgs : EventArgs { - public IpAddressInfo LocalIpAddress { get; set; } + public IPAddress LocalIpAddress { get; set; } #region Fields private readonly DiscoveredSsdpDevice _DiscoveredDevice; - private readonly bool _IsNewlyDiscovered; + private readonly bool _IsNewlyDiscovered; #endregion @@ -29,34 +26,34 @@ namespace Rssdp /// <param name="isNewlyDiscovered">A boolean value indicating whether or not this device came from the cache. See <see cref="IsNewlyDiscovered"/> for more detail.</param> /// <exception cref="ArgumentNullException">Thrown if the <paramref name="discoveredDevice"/> parameter is null.</exception> public DeviceAvailableEventArgs(DiscoveredSsdpDevice discoveredDevice, bool isNewlyDiscovered) - { - if (discoveredDevice == null) throw new ArgumentNullException(nameof(discoveredDevice)); + { + if (discoveredDevice == null) throw new ArgumentNullException(nameof(discoveredDevice)); - _DiscoveredDevice = discoveredDevice; - _IsNewlyDiscovered = isNewlyDiscovered; - } + _DiscoveredDevice = discoveredDevice; + _IsNewlyDiscovered = isNewlyDiscovered; + } - #endregion + #endregion - #region Public Properties + #region Public Properties - /// <summary> - /// Returns true if the device was discovered due to an alive notification, or a search and was not already in the cache. Returns false if the item came from the cache but matched the current search request. - /// </summary> - public bool IsNewlyDiscovered - { - get { return _IsNewlyDiscovered; } - } + /// <summary> + /// Returns true if the device was discovered due to an alive notification, or a search and was not already in the cache. Returns false if the item came from the cache but matched the current search request. + /// </summary> + public bool IsNewlyDiscovered + { + get { return _IsNewlyDiscovered; } + } /// <summary> /// A reference to a <see cref="DiscoveredSsdpDevice"/> instance containing the discovered details and allowing access to the full device description. /// </summary> public DiscoveredSsdpDevice DiscoveredDevice - { - get { return _DiscoveredDevice; } - } - - #endregion - - } -}
\ No newline at end of file + { + get { return _DiscoveredDevice; } + } + + #endregion + + } +} diff --git a/RSSDP/ISsdpCommunicationsServer.cs b/RSSDP/ISsdpCommunicationsServer.cs index c99d684a1..8cf65df11 100644 --- a/RSSDP/ISsdpCommunicationsServer.cs +++ b/RSSDP/ISsdpCommunicationsServer.cs @@ -1,7 +1,7 @@ using System; +using System.Net; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.Net; namespace Rssdp.Infrastructure { @@ -40,13 +40,13 @@ namespace Rssdp.Infrastructure /// <summary> /// Sends a message to a particular address (uni or multicast) and port. /// </summary> - Task SendMessage(byte[] messageData, IpEndPointInfo destination, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken); + Task SendMessage(byte[] messageData, IPEndPoint destination, IPAddress fromLocalIpAddress, CancellationToken cancellationToken); /// <summary> /// Sends a message to the SSDP multicast address and port. /// </summary> - Task SendMulticastMessage(string message, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken); - Task SendMulticastMessage(string message, int sendCount, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken); + Task SendMulticastMessage(string message, IPAddress fromLocalIpAddress, CancellationToken cancellationToken); + Task SendMulticastMessage(string message, int sendCount, IPAddress fromLocalIpAddress, CancellationToken cancellationToken); #endregion diff --git a/RSSDP/RequestReceivedEventArgs.cs b/RSSDP/RequestReceivedEventArgs.cs index fd3cd9e3a..b753950f0 100644 --- a/RSSDP/RequestReceivedEventArgs.cs +++ b/RSSDP/RequestReceivedEventArgs.cs @@ -1,10 +1,6 @@ using System; -using System.Collections.Generic; using System.Net; using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using MediaBrowser.Model.Net; namespace Rssdp.Infrastructure { @@ -16,18 +12,18 @@ namespace Rssdp.Infrastructure #region Fields private readonly HttpRequestMessage _Message; - private readonly IpEndPointInfo _ReceivedFrom; + private readonly IPEndPoint _ReceivedFrom; #endregion - public IpAddressInfo LocalIpAddress { get; private set; } + public IPAddress LocalIpAddress { get; private set; } #region Constructors /// <summary> /// Full constructor. /// </summary> - public RequestReceivedEventArgs(HttpRequestMessage message, IpEndPointInfo receivedFrom, IpAddressInfo localIpAddress) + public RequestReceivedEventArgs(HttpRequestMessage message, IPEndPoint receivedFrom, IPAddress localIpAddress) { _Message = message; _ReceivedFrom = receivedFrom; @@ -49,7 +45,7 @@ namespace Rssdp.Infrastructure /// <summary> /// The <see cref="UdpEndPoint"/> the request came from. /// </summary> - public IpEndPointInfo ReceivedFrom + public IPEndPoint ReceivedFrom { get { return _ReceivedFrom; } } diff --git a/RSSDP/ResponseReceivedEventArgs.cs b/RSSDP/ResponseReceivedEventArgs.cs index 5ed9664ed..f9f9c3040 100644 --- a/RSSDP/ResponseReceivedEventArgs.cs +++ b/RSSDP/ResponseReceivedEventArgs.cs @@ -1,10 +1,6 @@ using System; -using System.Collections.Generic; using System.Net; using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using MediaBrowser.Model.Net; namespace Rssdp.Infrastructure { @@ -14,12 +10,12 @@ namespace Rssdp.Infrastructure public sealed class ResponseReceivedEventArgs : EventArgs { - public IpAddressInfo LocalIpAddress { get; set; } + public IPAddress LocalIpAddress { get; set; } #region Fields private readonly HttpResponseMessage _Message; - private readonly IpEndPointInfo _ReceivedFrom; + private readonly IPEndPoint _ReceivedFrom; #endregion @@ -28,7 +24,7 @@ namespace Rssdp.Infrastructure /// <summary> /// Full constructor. /// </summary> - public ResponseReceivedEventArgs(HttpResponseMessage message, IpEndPointInfo receivedFrom) + public ResponseReceivedEventArgs(HttpResponseMessage message, IPEndPoint receivedFrom) { _Message = message; _ReceivedFrom = receivedFrom; @@ -49,7 +45,7 @@ namespace Rssdp.Infrastructure /// <summary> /// The <see cref="UdpEndPoint"/> the response came from. /// </summary> - public IpEndPointInfo ReceivedFrom + public IPEndPoint ReceivedFrom { get { return _ReceivedFrom; } } diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs index 5d2afc37a..0aa985a26 100644 --- a/RSSDP/SsdpCommunicationsServer.cs +++ b/RSSDP/SsdpCommunicationsServer.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Net.Http; using System.Net.Sockets; using System.Text; @@ -163,7 +164,7 @@ namespace Rssdp.Infrastructure /// <summary> /// Sends a message to a particular address (uni or multicast) and port. /// </summary> - public async Task SendMessage(byte[] messageData, IpEndPointInfo destination, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken) + public async Task SendMessage(byte[] messageData, IPEndPoint destination, IPAddress fromLocalIpAddress, CancellationToken cancellationToken) { if (messageData == null) throw new ArgumentNullException(nameof(messageData)); @@ -186,7 +187,7 @@ namespace Rssdp.Infrastructure } } - private async Task SendFromSocket(ISocket socket, byte[] messageData, IpEndPointInfo destination, CancellationToken cancellationToken) + private async Task SendFromSocket(ISocket socket, byte[] messageData, IPEndPoint destination, CancellationToken cancellationToken) { try { @@ -206,7 +207,7 @@ namespace Rssdp.Infrastructure } } - private List<ISocket> GetSendSockets(IpAddressInfo fromLocalIpAddress, IpEndPointInfo destination) + private List<ISocket> GetSendSockets(IPAddress fromLocalIpAddress, IPEndPoint destination) { EnsureSendSocketCreated(); @@ -215,24 +216,24 @@ namespace Rssdp.Infrastructure var sockets = _sendSockets.Where(i => i.LocalIPAddress.AddressFamily == fromLocalIpAddress.AddressFamily); // Send from the Any socket and the socket with the matching address - if (fromLocalIpAddress.AddressFamily == IpAddressFamily.InterNetwork) + if (fromLocalIpAddress.AddressFamily == AddressFamily.InterNetwork) { - sockets = sockets.Where(i => i.LocalIPAddress.Equals(IpAddressInfo.Any) || fromLocalIpAddress.Equals(i.LocalIPAddress)); + sockets = sockets.Where(i => i.LocalIPAddress.Equals(IPAddress.Any) || fromLocalIpAddress.Equals(i.LocalIPAddress)); // If sending to the loopback address, filter the socket list as well - if (destination.IpAddress.Equals(IpAddressInfo.Loopback)) + if (destination.Address.Equals(IPAddress.Loopback)) { - sockets = sockets.Where(i => i.LocalIPAddress.Equals(IpAddressInfo.Any) || i.LocalIPAddress.Equals(IpAddressInfo.Loopback)); + sockets = sockets.Where(i => i.LocalIPAddress.Equals(IPAddress.Any) || i.LocalIPAddress.Equals(IPAddress.Loopback)); } } - else if (fromLocalIpAddress.AddressFamily == IpAddressFamily.InterNetworkV6) + else if (fromLocalIpAddress.AddressFamily == AddressFamily.InterNetworkV6) { - sockets = sockets.Where(i => i.LocalIPAddress.Equals(IpAddressInfo.IPv6Any) || fromLocalIpAddress.Equals(i.LocalIPAddress)); + sockets = sockets.Where(i => i.LocalIPAddress.Equals(IPAddress.IPv6Any) || fromLocalIpAddress.Equals(i.LocalIPAddress)); // If sending to the loopback address, filter the socket list as well - if (destination.IpAddress.Equals(IpAddressInfo.IPv6Loopback)) + if (destination.Address.Equals(IPAddress.IPv6Loopback)) { - sockets = sockets.Where(i => i.LocalIPAddress.Equals(IpAddressInfo.IPv6Any) || i.LocalIPAddress.Equals(IpAddressInfo.IPv6Loopback)); + sockets = sockets.Where(i => i.LocalIPAddress.Equals(IPAddress.IPv6Any) || i.LocalIPAddress.Equals(IPAddress.IPv6Loopback)); } } @@ -240,7 +241,7 @@ namespace Rssdp.Infrastructure } } - public Task SendMulticastMessage(string message, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken) + public Task SendMulticastMessage(string message, IPAddress fromLocalIpAddress, CancellationToken cancellationToken) { return SendMulticastMessage(message, SsdpConstants.UdpResendCount, fromLocalIpAddress, cancellationToken); } @@ -248,7 +249,7 @@ namespace Rssdp.Infrastructure /// <summary> /// Sends a message to the SSDP multicast address and port. /// </summary> - public async Task SendMulticastMessage(string message, int sendCount, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken) + public async Task SendMulticastMessage(string message, int sendCount, IPAddress fromLocalIpAddress, CancellationToken cancellationToken) { if (message == null) throw new ArgumentNullException(nameof(message)); @@ -263,12 +264,13 @@ namespace Rssdp.Infrastructure // SSDP spec recommends sending messages multiple times (not more than 3) to account for possible packet loss over UDP. for (var i = 0; i < sendCount; i++) { - await SendMessageIfSocketNotDisposed(messageData, new IpEndPointInfo - { - IpAddress = new IpAddressInfo(SsdpConstants.MulticastLocalAdminAddress, IpAddressFamily.InterNetwork), - Port = SsdpConstants.MulticastPort - - }, fromLocalIpAddress, cancellationToken).ConfigureAwait(false); + await SendMessageIfSocketNotDisposed( + messageData, + new IPEndPoint( + IPAddress.Parse(SsdpConstants.MulticastLocalAdminAddress), + SsdpConstants.MulticastPort), + fromLocalIpAddress, + cancellationToken).ConfigureAwait(false); await Task.Delay(100, cancellationToken).ConfigureAwait(false); } @@ -336,7 +338,7 @@ namespace Rssdp.Infrastructure #region Private Methods - private Task SendMessageIfSocketNotDisposed(byte[] messageData, IpEndPointInfo destination, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken) + private Task SendMessageIfSocketNotDisposed(byte[] messageData, IPEndPoint destination, IPAddress fromLocalIpAddress, CancellationToken cancellationToken) { var sockets = _sendSockets; if (sockets != null) @@ -364,13 +366,13 @@ namespace Rssdp.Infrastructure { var sockets = new List<ISocket>(); - sockets.Add(_SocketFactory.CreateSsdpUdpSocket(IpAddressInfo.Any, _LocalPort)); + sockets.Add(_SocketFactory.CreateSsdpUdpSocket(IPAddress.Any, _LocalPort)); if (_enableMultiSocketBinding) { foreach (var address in _networkManager.GetLocalIpAddresses(_config.Configuration.IgnoreVirtualInterfaces)) { - if (address.AddressFamily == IpAddressFamily.InterNetworkV6) + if (address.AddressFamily == AddressFamily.InterNetworkV6) { // Not support IPv6 right now continue; @@ -439,7 +441,7 @@ namespace Rssdp.Infrastructure } } - private void ProcessMessage(string data, IpEndPointInfo endPoint, IpAddressInfo receivedOnLocalIpAddress) + private void ProcessMessage(string data, IPEndPoint endPoint, IPAddress receivedOnLocalIpAddress) { // Responses start with the HTTP version, prefixed with HTTP/ while // requests start with a method which can vary and might be one we haven't @@ -481,7 +483,7 @@ namespace Rssdp.Infrastructure } } - private void OnRequestReceived(HttpRequestMessage data, IpEndPointInfo remoteEndPoint, IpAddressInfo receivedOnLocalIpAddress) + private void OnRequestReceived(HttpRequestMessage data, IPEndPoint remoteEndPoint, IPAddress receivedOnLocalIpAddress) { //SSDP specification says only * is currently used but other uri's might //be implemented in the future and should be ignored unless understood. @@ -496,7 +498,7 @@ namespace Rssdp.Infrastructure handlers(this, new RequestReceivedEventArgs(data, remoteEndPoint, receivedOnLocalIpAddress)); } - private void OnResponseReceived(HttpResponseMessage data, IpEndPointInfo endPoint, IpAddressInfo localIpAddress) + private void OnResponseReceived(HttpResponseMessage data, IPEndPoint endPoint, IPAddress localIpAddress) { var handlers = this.ResponseReceived; if (handlers != null) diff --git a/RSSDP/SsdpDevice.cs b/RSSDP/SsdpDevice.cs index b4c4a88fd..09f729e83 100644 --- a/RSSDP/SsdpDevice.cs +++ b/RSSDP/SsdpDevice.cs @@ -1,9 +1,6 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Text; -using System.Threading.Tasks; -using System.Xml; using Rssdp.Infrastructure; namespace Rssdp diff --git a/RSSDP/SsdpDeviceLocator.cs b/RSSDP/SsdpDeviceLocator.cs index e17e14c1a..59a2710d5 100644 --- a/RSSDP/SsdpDeviceLocator.cs +++ b/RSSDP/SsdpDeviceLocator.cs @@ -1,13 +1,10 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.IO; using System.Linq; +using System.Net; using System.Net.Http; -using System.Text; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.Net; namespace Rssdp.Infrastructure { @@ -213,7 +210,7 @@ namespace Rssdp.Infrastructure /// Raises the <see cref="DeviceAvailable"/> event. /// </summary> /// <seealso cref="DeviceAvailable"/> - protected virtual void OnDeviceAvailable(DiscoveredSsdpDevice device, bool isNewDevice, IpAddressInfo localIpAddress) + protected virtual void OnDeviceAvailable(DiscoveredSsdpDevice device, bool isNewDevice, IPAddress localIpAddress) { if (this.IsDisposed) return; @@ -295,7 +292,7 @@ namespace Rssdp.Infrastructure #region Discovery/Device Add - private void AddOrUpdateDiscoveredDevice(DiscoveredSsdpDevice device, IpAddressInfo localIpAddress) + private void AddOrUpdateDiscoveredDevice(DiscoveredSsdpDevice device, IPAddress localIpAddress) { bool isNewDevice = false; lock (_Devices) @@ -316,7 +313,7 @@ namespace Rssdp.Infrastructure DeviceFound(device, isNewDevice, localIpAddress); } - private void DeviceFound(DiscoveredSsdpDevice device, bool isNewDevice, IpAddressInfo localIpAddress) + private void DeviceFound(DiscoveredSsdpDevice device, bool isNewDevice, IPAddress localIpAddress) { if (!NotificationTypeMatchesFilter(device)) return; @@ -357,7 +354,7 @@ namespace Rssdp.Infrastructure return _CommunicationsServer.SendMulticastMessage(message, null, cancellationToken); } - private void ProcessSearchResponseMessage(HttpResponseMessage message, IpAddressInfo localIpAddress) + private void ProcessSearchResponseMessage(HttpResponseMessage message, IPAddress localIpAddress) { if (!message.IsSuccessStatusCode) return; @@ -378,7 +375,7 @@ namespace Rssdp.Infrastructure } } - private void ProcessNotificationMessage(HttpRequestMessage message, IpAddressInfo localIpAddress) + private void ProcessNotificationMessage(HttpRequestMessage message, IPAddress localIpAddress) { if (String.Compare(message.Method.Method, "Notify", StringComparison.OrdinalIgnoreCase) != 0) return; @@ -389,7 +386,7 @@ namespace Rssdp.Infrastructure ProcessByeByeNotification(message); } - private void ProcessAliveNotification(HttpRequestMessage message, IpAddressInfo localIpAddress) + private void ProcessAliveNotification(HttpRequestMessage message, IPAddress localIpAddress) { var location = GetFirstHeaderUriValue("Location", message); if (location != null) diff --git a/RSSDP/SsdpDevicePublisher.cs b/RSSDP/SsdpDevicePublisher.cs index 921f33c21..7f3e56394 100644 --- a/RSSDP/SsdpDevicePublisher.cs +++ b/RSSDP/SsdpDevicePublisher.cs @@ -2,13 +2,10 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using System.Net.Http; -using System.Text; +using System.Net; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.Net; using MediaBrowser.Common.Net; -using Rssdp; namespace Rssdp.Infrastructure { @@ -199,7 +196,12 @@ namespace Rssdp.Infrastructure } } - private void ProcessSearchRequest(string mx, string searchTarget, IpEndPointInfo remoteEndPoint, IpAddressInfo receivedOnlocalIpAddress, CancellationToken cancellationToken) + private void ProcessSearchRequest( + string mx, + string searchTarget, + IPEndPoint remoteEndPoint, + IPAddress receivedOnlocalIpAddress, + CancellationToken cancellationToken) { if (String.IsNullOrEmpty(searchTarget)) { @@ -258,7 +260,7 @@ namespace Rssdp.Infrastructure foreach (var device in deviceList) { if (!_sendOnlyMatchedHost || - _networkManager.IsInSameSubnet(device.ToRootDevice().Address, remoteEndPoint.IpAddress, device.ToRootDevice().SubnetMask)) + _networkManager.IsInSameSubnet(device.ToRootDevice().Address, remoteEndPoint.Address, device.ToRootDevice().SubnetMask)) { SendDeviceSearchResponses(device, remoteEndPoint, receivedOnlocalIpAddress, cancellationToken); } @@ -276,7 +278,11 @@ namespace Rssdp.Infrastructure return _Devices.Union(_Devices.SelectManyRecursive<SsdpDevice>((d) => d.Devices)); } - private void SendDeviceSearchResponses(SsdpDevice device, IpEndPointInfo endPoint, IpAddressInfo receivedOnlocalIpAddress, CancellationToken cancellationToken) + private void SendDeviceSearchResponses( + SsdpDevice device, + IPEndPoint endPoint, + IPAddress receivedOnlocalIpAddress, + CancellationToken cancellationToken) { bool isRootDevice = (device as SsdpRootDevice) != null; if (isRootDevice) @@ -296,7 +302,13 @@ namespace Rssdp.Infrastructure return String.Format("{0}::{1}", udn, fullDeviceType); } - private async void SendSearchResponse(string searchTarget, SsdpDevice device, string uniqueServiceName, IpEndPointInfo endPoint, IpAddressInfo receivedOnlocalIpAddress, CancellationToken cancellationToken) + private async void SendSearchResponse( + string searchTarget, + SsdpDevice device, + string uniqueServiceName, + IPEndPoint endPoint, + IPAddress receivedOnlocalIpAddress, + CancellationToken cancellationToken) { var rootDevice = device.ToRootDevice(); @@ -333,7 +345,7 @@ namespace Rssdp.Infrastructure //WriteTrace(String.Format("Sent search response to " + endPoint.ToString()), device); } - private bool IsDuplicateSearchRequest(string searchTarget, IpEndPointInfo endPoint) + private bool IsDuplicateSearchRequest(string searchTarget, IPEndPoint endPoint) { var isDuplicateRequest = false; @@ -556,7 +568,7 @@ namespace Rssdp.Infrastructure private class SearchRequest { - public IpEndPointInfo EndPoint { get; set; } + public IPEndPoint EndPoint { get; set; } public DateTime Received { get; set; } public string SearchTarget { get; set; } diff --git a/RSSDP/SsdpRootDevice.cs b/RSSDP/SsdpRootDevice.cs index d918b9040..0f2de7b15 100644 --- a/RSSDP/SsdpRootDevice.cs +++ b/RSSDP/SsdpRootDevice.cs @@ -1,9 +1,5 @@ using System; -using System.Collections.Generic; -using System.Text; -using System.Xml; -using Rssdp.Infrastructure; -using MediaBrowser.Model.Net; +using System.Net; namespace Rssdp { @@ -56,12 +52,12 @@ namespace Rssdp /// <summary> /// Gets or sets the Address used to check if the received message from same interface with this device/tree. Required. /// </summary> - public IpAddressInfo Address { get; set; } + public IPAddress Address { get; set; } /// <summary> /// Gets or sets the SubnetMask used to check if the received message from same interface with this device/tree. Required. /// </summary> - public IpAddressInfo SubnetMask { get; set; } + public IPAddress SubnetMask { get; set; } /// <summary> /// The base URL to use for all relative url's provided in other propertise (and those of child devices). Optional. diff --git a/SharedVersion.cs b/SharedVersion.cs index 1e74d8f7d..500e6fe55 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; -[assembly: AssemblyVersion("10.3.6")] -[assembly: AssemblyFileVersion("10.3.6")] +[assembly: AssemblyVersion("10.3.7")] +[assembly: AssemblyFileVersion("10.3.7")] diff --git a/build.yaml b/build.yaml index 7a5e66b11..2d4bc29f4 100644 --- a/build.yaml +++ b/build.yaml @@ -1,7 +1,7 @@ --- # We just wrap `build` so this is really it name: "jellyfin" -version: "10.3.6" +version: "10.3.7" packages: - debian-package-x64 - debian-package-armhf diff --git a/deployment/debian-package-x64/pkg-src/changelog b/deployment/debian-package-x64/pkg-src/changelog index 64912a11d..aa15827a7 100644 --- a/deployment/debian-package-x64/pkg-src/changelog +++ b/deployment/debian-package-x64/pkg-src/changelog @@ -1,3 +1,9 @@ +jellyfin (10.3.7-1) unstable; urgency=medium + + * New upstream version 10.3.7; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.7 + + -- Jellyfin Packaging Team <packaging@jellyfin.org> Wed, 24 Jul 2019 10:48:28 -0400 + jellyfin (10.3.6-1) unstable; urgency=medium * New upstream version 10.3.6; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.6 diff --git a/deployment/fedora-package-x64/pkg-src/jellyfin.spec b/deployment/fedora-package-x64/pkg-src/jellyfin.spec index 809bde39d..91b74ffe1 100644 --- a/deployment/fedora-package-x64/pkg-src/jellyfin.spec +++ b/deployment/fedora-package-x64/pkg-src/jellyfin.spec @@ -7,7 +7,7 @@ %endif Name: jellyfin -Version: 10.3.6 +Version: 10.3.7 Release: 1%{?dist} Summary: The Free Software Media Browser License: GPLv2 @@ -140,6 +140,8 @@ fi %systemd_postun_with_restart jellyfin.service %changelog +* Wed Jul 24 2019 Jellyfin Packaging Team <packaging@jellyfin.org> +- New upstream version 10.3.7; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.7 * Sat Jul 06 2019 Jellyfin Packaging Team <packaging@jellyfin.org> - New upstream version 10.3.6; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.6 * Sun Jun 09 2019 Jellyfin Packaging Team <packaging@jellyfin.org> |
