diff options
| -rw-r--r-- | Emby.Server.Implementations/ApplicationHost.cs | 1 | ||||
| -rw-r--r-- | Emby.Server.Implementations/Localization/Core/it.json | 5 | ||||
| -rw-r--r-- | Emby.Server.Implementations/ResourceFileManager.cs | 45 | ||||
| -rw-r--r-- | Emby.Server.Implementations/Updates/InstallationManager.cs | 57 | ||||
| -rw-r--r-- | Jellyfin.Networking/Manager/NetworkManager.cs | 37 | ||||
| -rw-r--r-- | Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStopLogger.cs | 8 | ||||
| -rw-r--r-- | MediaBrowser.Common/Net/INetworkManager.cs | 12 | ||||
| -rw-r--r-- | MediaBrowser.Controller/IResourceFileManager.cs | 9 | ||||
| -rwxr-xr-x | debian/bin/restart.sh | 6 | ||||
| -rw-r--r-- | fedora/jellyfin.spec | 6 | ||||
| -rwxr-xr-x | fedora/restart.sh | 6 | ||||
| -rw-r--r-- | tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs | 16 |
12 files changed, 88 insertions, 120 deletions
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index c695c0231..30ccaf8de 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -640,7 +640,6 @@ namespace Emby.Server.Implementations ServiceCollection.AddSingleton<ISubtitleEncoder, MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder>(); - ServiceCollection.AddSingleton<IResourceFileManager, ResourceFileManager>(); ServiceCollection.AddSingleton<EncodingHelper>(); ServiceCollection.AddSingleton<IAttachmentExtractor, MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor>(); diff --git a/Emby.Server.Implementations/Localization/Core/it.json b/Emby.Server.Implementations/Localization/Core/it.json index 9e37ddc27..110f8043d 100644 --- a/Emby.Server.Implementations/Localization/Core/it.json +++ b/Emby.Server.Implementations/Localization/Core/it.json @@ -115,5 +115,8 @@ "TasksLibraryCategory": "Libreria", "TasksMaintenanceCategory": "Manutenzione", "TaskCleanActivityLog": "Attività di Registro Completate", - "TaskCleanActivityLogDescription": "Elimina gli inserimenti nel registro delle attività più vecchie dell’età configurata." + "TaskCleanActivityLogDescription": "Elimina gli inserimenti nel registro delle attività più vecchie dell’età configurata.", + "Undefined": "Non Definito", + "Forced": "Forzato", + "Default": "Predefinito" } diff --git a/Emby.Server.Implementations/ResourceFileManager.cs b/Emby.Server.Implementations/ResourceFileManager.cs deleted file mode 100644 index 22fc62293..000000000 --- a/Emby.Server.Implementations/ResourceFileManager.cs +++ /dev/null @@ -1,45 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.IO; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Net; -using MediaBrowser.Model.IO; -using Microsoft.Extensions.Logging; - -namespace Emby.Server.Implementations -{ - public class ResourceFileManager : IResourceFileManager - { - private readonly IFileSystem _fileSystem; - private readonly ILogger<ResourceFileManager> _logger; - - public ResourceFileManager(ILogger<ResourceFileManager> logger, IFileSystem fileSystem) - { - _logger = logger; - _fileSystem = fileSystem; - } - - public string GetResourcePath(string basePath, string virtualPath) - { - var fullPath = Path.Combine(basePath, virtualPath.Replace('/', Path.DirectorySeparatorChar)); - - try - { - fullPath = Path.GetFullPath(fullPath); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error retrieving full path"); - } - - // Don't allow file system access outside of the source folder - if (!_fileSystem.ContainsSubPath(basePath, fullPath)) - { - throw new SecurityException("Access denied"); - } - - return fullPath; - } - } -} diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 7a071c071..f2c096b8a 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -6,13 +6,15 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; -using System.Runtime.Serialization; +using System.Net.Http.Json; using System.Security.Cryptography; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Events; using MediaBrowser.Common; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Json; using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; @@ -21,8 +23,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Events.Updates; using MediaBrowser.Model.IO; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Updates; using Microsoft.Extensions.Logging; @@ -40,9 +40,9 @@ namespace Emby.Server.Implementations.Updates private readonly IApplicationPaths _appPaths; private readonly IEventManager _eventManager; private readonly IHttpClientFactory _httpClientFactory; - private readonly IJsonSerializer _jsonSerializer; private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; + private readonly JsonSerializerOptions _jsonSerializerOptions; /// <summary> /// Gets the application host. @@ -70,7 +70,6 @@ namespace Emby.Server.Implementations.Updates IApplicationPaths appPaths, IEventManager eventManager, IHttpClientFactory httpClientFactory, - IJsonSerializer jsonSerializer, IServerConfigurationManager config, IFileSystem fileSystem, IZipClient zipClient) @@ -83,10 +82,10 @@ namespace Emby.Server.Implementations.Updates _appPaths = appPaths; _eventManager = eventManager; _httpClientFactory = httpClientFactory; - _jsonSerializer = jsonSerializer; _config = config; _fileSystem = fileSystem; _zipClient = zipClient; + _jsonSerializerOptions = JsonDefaults.GetOptions(); } /// <inheritdoc /> @@ -97,31 +96,29 @@ namespace Emby.Server.Implementations.Updates { try { - using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .GetAsync(new Uri(manifest), cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - - try + var packages = await _httpClientFactory.CreateClient(NamedClient.Default) + .GetFromJsonAsync<List<PackageInfo>>(new Uri(manifest), _jsonSerializerOptions, cancellationToken).ConfigureAwait(false); + if (packages == null) { - var package = await _jsonSerializer.DeserializeFromStreamAsync<IList<PackageInfo>>(stream).ConfigureAwait(false); + return Array.Empty<PackageInfo>(); + } - // Store the repository and repository url with each version, as they may be spread apart. - foreach (var entry in package) + // Store the repository and repository url with each version, as they may be spread apart. + foreach (var entry in packages) + { + foreach (var ver in entry.versions) { - foreach (var ver in entry.versions) - { - ver.repositoryName = manifestName; - ver.repositoryUrl = manifest; - } + ver.repositoryName = manifestName; + ver.repositoryUrl = manifest; } - - return package; - } - catch (SerializationException ex) - { - _logger.LogError(ex, "Failed to deserialize the plugin manifest retrieved from {Manifest}", manifest); - return Array.Empty<PackageInfo>(); } + + return packages; + } + catch (JsonException ex) + { + _logger.LogError(ex, "Failed to deserialize the plugin manifest retrieved from {Manifest}", manifest); + return Array.Empty<PackageInfo>(); } catch (UriFormatException ex) { @@ -187,7 +184,13 @@ namespace Emby.Server.Implementations.Updates // Where repositories have the same content, the details of the first is taken. foreach (var package in await GetPackages(repository.Name, repository.Url, cancellationToken).ConfigureAwait(true)) { - var existing = FilterPackages(result, package.name, Guid.Parse(package.guid)).FirstOrDefault(); + if (!Guid.TryParse(package.guid, out var packageGuid)) + { + // Package doesn't have a valid GUID, skip. + continue; + } + + var existing = FilterPackages(result, package.name, packageGuid).FirstOrDefault(); if (existing != null) { // Assumption is both lists are ordered, so slot these into the correct place. diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index 515ae669a..1a5614b7b 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -84,7 +84,7 @@ namespace Jellyfin.Networking.Manager private Collection<IPObject> _internalInterfaces; /// <summary> - /// Flag set when no custom LAN has been defined in the config. + /// Flag set when no custom LAN has been defined in the configuration. /// </summary> private bool _usingPrivateAddresses; @@ -228,7 +228,7 @@ namespace Jellyfin.Networking.Manager } /// <inheritdoc/> - public Collection<IPObject> CreateIPCollection(string[] values, bool bracketed = false) + public Collection<IPObject> CreateIPCollection(string[] values, bool negated = false) { Collection<IPObject> col = new Collection<IPObject>(); if (values == null) @@ -242,21 +242,14 @@ namespace Jellyfin.Networking.Manager try { - if (v.StartsWith('[') && v.EndsWith(']')) + if (v.StartsWith('!')) { - if (bracketed) - { - AddToCollection(col, v[1..^1]); - } - } - else if (v.StartsWith('!')) - { - if (bracketed) + if (negated) { AddToCollection(col, v[1..]); } } - else if (!bracketed) + else if (!negated) { AddToCollection(col, v); } @@ -730,7 +723,7 @@ namespace Jellyfin.Networking.Manager } /// <summary> - /// Parses a string and adds it into the the collection, replacing any interface references. + /// Parses a string and adds it into the collection, replacing any interface references. /// </summary> /// <param name="col"><see cref="Collection{IPObject}"/>Collection.</param> /// <param name="token">String value to parse.</param> @@ -755,7 +748,19 @@ namespace Jellyfin.Networking.Manager } else if (TryParse(token, out IPObject obj)) { - if (!IsIP6Enabled) + // Expand if the ip address is "any". + if ((obj.Address.Equals(IPAddress.Any) && IsIP4Enabled) + || (obj.Address.Equals(IPAddress.IPv6Any) && IsIP6Enabled)) + { + foreach (IPNetAddress iface in _interfaceAddresses) + { + if (obj.AddressFamily == iface.AddressFamily) + { + col.AddItem(iface); + } + } + } + else if (!IsIP6Enabled) { // Remove IP6 addresses from multi-homed IPHosts. obj.Remove(AddressFamily.InterNetworkV6); @@ -872,7 +877,7 @@ namespace Jellyfin.Networking.Manager else { var replacement = parts[1].Trim(); - if (string.Equals(parts[0], "remaining", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(parts[0], "all", StringComparison.OrdinalIgnoreCase)) { _publishedServerUrls[new IPNetAddress(IPAddress.Broadcast)] = replacement; } @@ -956,7 +961,7 @@ namespace Jellyfin.Networking.Manager { _logger.LogDebug("Refreshing LAN information."); - // Get config options. + // Get configuration options. string[] subnets = config.LocalNetworkSubnets; // Create lists from user settings. diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStopLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStopLogger.cs index 51a882c14..a0bad29e9 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStopLogger.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStopLogger.cs @@ -59,6 +59,12 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Session var user = eventArgs.Users[0]; + var notificationType = GetPlaybackStoppedNotificationType(item.MediaType); + if (notificationType == null) + { + return; + } + await _activityManager.CreateAsync(new ActivityLog( string.Format( CultureInfo.InvariantCulture, @@ -66,7 +72,7 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Session user.Username, GetItemName(item), eventArgs.DeviceName), - GetPlaybackStoppedNotificationType(item.MediaType), + notificationType, user.Id)) .ConfigureAwait(false); } diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs index 43562afe3..b6c390d23 100644 --- a/MediaBrowser.Common/Net/INetworkManager.cs +++ b/MediaBrowser.Common/Net/INetworkManager.cs @@ -149,7 +149,7 @@ namespace MediaBrowser.Common.Net /// <summary> /// Returns true if the address is a private address. - /// The config option TrustIP6Interfaces overrides this functions behaviour. + /// The configuration option TrustIP6Interfaces overrides this functions behaviour. /// </summary> /// <param name="address">Address to check.</param> /// <returns>True or False.</returns> @@ -157,7 +157,7 @@ namespace MediaBrowser.Common.Net /// <summary> /// Returns true if the address is part of the user defined LAN. - /// The config option TrustIP6Interfaces overrides this functions behaviour. + /// The configuration option TrustIP6Interfaces overrides this functions behaviour. /// </summary> /// <param name="address">IP to check.</param> /// <returns>True if endpoint is within the LAN range.</returns> @@ -165,7 +165,7 @@ namespace MediaBrowser.Common.Net /// <summary> /// Returns true if the address is part of the user defined LAN. - /// The config option TrustIP6Interfaces overrides this functions behaviour. + /// The configuration option TrustIP6Interfaces overrides this functions behaviour. /// </summary> /// <param name="address">IP to check.</param> /// <returns>True if endpoint is within the LAN range.</returns> @@ -173,7 +173,7 @@ namespace MediaBrowser.Common.Net /// <summary> /// Returns true if the address is part of the user defined LAN. - /// The config option TrustIP6Interfaces overrides this functions behaviour. + /// The configuration option TrustIP6Interfaces overrides this functions behaviour. /// </summary> /// <param name="address">IP to check.</param> /// <returns>True if endpoint is within the LAN range.</returns> @@ -192,9 +192,9 @@ namespace MediaBrowser.Common.Net /// Parses an array of strings into a Collection{IPObject}. /// </summary> /// <param name="values">Values to parse.</param> - /// <param name="bracketed">When true, only include values in []. When false, ignore bracketed values.</param> + /// <param name="negated">When true, only include values beginning with !. When false, ignore ! values.</param> /// <returns>IPCollection object containing the value strings.</returns> - Collection<IPObject> CreateIPCollection(string[] values, bool bracketed = false); + Collection<IPObject> CreateIPCollection(string[] values, bool negated = false); /// <summary> /// Returns all the internal Bind interface addresses. diff --git a/MediaBrowser.Controller/IResourceFileManager.cs b/MediaBrowser.Controller/IResourceFileManager.cs deleted file mode 100644 index 26f0424b7..000000000 --- a/MediaBrowser.Controller/IResourceFileManager.cs +++ /dev/null @@ -1,9 +0,0 @@ -#pragma warning disable CS1591 - -namespace MediaBrowser.Controller -{ - public interface IResourceFileManager - { - string GetResourcePath(string basePath, string virtualPath); - } -} diff --git a/debian/bin/restart.sh b/debian/bin/restart.sh index 9b64b6d72..34fce0670 100755 --- a/debian/bin/restart.sh +++ b/debian/bin/restart.sh @@ -24,13 +24,13 @@ cmd="$( get_service_command )" echo "Detected service control platform '$cmd'; using it to restart Jellyfin..." case $cmd in 'systemctl') - echo "sleep 2; /usr/bin/sudo $( which systemctl ) restart jellyfin" | at now + echo "sleep 0.5; /usr/bin/sudo $( which systemctl ) start jellyfin" | at now ;; 'service') - echo "sleep 2; /usr/bin/sudo $( which service ) jellyfin restart" | at now + echo "sleep 0.5; /usr/bin/sudo $( which service ) jellyfin start" | at now ;; 'sysv') - echo "sleep 2; /usr/bin/sudo /etc/init.d/jellyfin restart" | at now + echo "sleep 0.5; /usr/bin/sudo /etc/init.d/jellyfin start" | at now ;; esac exit 0 diff --git a/fedora/jellyfin.spec b/fedora/jellyfin.spec index 13305488e..0ab1e410a 100644 --- a/fedora/jellyfin.spec +++ b/fedora/jellyfin.spec @@ -40,7 +40,7 @@ Jellyfin is a free software media system that puts you in control of managing an Summary: The Free Software Media System Server backend Requires(pre): shadow-utils Requires: ffmpeg -Requires: libcurl, fontconfig, freetype, openssl, glibc libicu +Requires: libcurl, fontconfig, freetype, openssl, glibc, libicu, at %description server The Jellyfin media server backend. @@ -127,6 +127,10 @@ if [ $1 -gt 1 ] ; then if [ "${service_state}" = "active" ]; then systemctl start jellyfin.service fi + if [ $1 -eq 1 ]; then + # On fresh install only, enable the jellyfin.service unit + systemctl enable --now jellyfin.service + fi fi %systemd_post jellyfin.service diff --git a/fedora/restart.sh b/fedora/restart.sh index 9e53efecd..34fce0670 100755 --- a/fedora/restart.sh +++ b/fedora/restart.sh @@ -24,13 +24,13 @@ cmd="$( get_service_command )" echo "Detected service control platform '$cmd'; using it to restart Jellyfin..." case $cmd in 'systemctl') - echo "sleep 2; /usr/bin/sudo $( which systemctl ) restart jellyfin" | at now + echo "sleep 0.5; /usr/bin/sudo $( which systemctl ) start jellyfin" | at now ;; 'service') - echo "sleep 2; /usr/bin/sudo $( which service ) jellyfin restart" | at now + echo "sleep 0.5; /usr/bin/sudo $( which service ) jellyfin start" | at now ;; 'sysv') - echo "sleep 2; /usr/bin/sudo /etc/init.d/jellyfin restart" | at now + echo "sleep 0.5; /usr/bin/sudo /etc/init.d/jellyfin start" | at now ;; esac exit 0 diff --git a/tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs index 56d11ef52..c350685af 100644 --- a/tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs +++ b/tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs @@ -135,6 +135,7 @@ namespace Jellyfin.Networking.Tests [InlineData("127.0.0.1#")] [InlineData("localhost!")] [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517:1231")] + [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517:1231]")] public void InvalidAddressString(string address) { Assert.False(TryParse(address, out _)); @@ -157,7 +158,7 @@ namespace Jellyfin.Networking.Tests "[]", "[]", "[]")] - [InlineData("[127.0.0.1]", + [InlineData("!127.0.0.1", "[]", "[]", "[127.0.0.1/32]", @@ -169,18 +170,19 @@ namespace Jellyfin.Networking.Tests "[]", "[]", "[]")] + [InlineData( + "192.158.1.2/16, localhost, fd23:184f:2029:0:3139:7386:67d7:d517, !10.10.10.10", + "[192.158.1.2/16,127.0.0.1/32,fd23:184f:2029:0:3139:7386:67d7:d517/128]", + "[192.158.1.2/16,127.0.0.1/32]", + "[10.10.10.10/32]", + "[10.10.10.10/32]", + "[192.158.0.0/16,127.0.0.1/32,fd23:184f:2029:0:3139:7386:67d7:d517/128]")] [InlineData("192.158.1.2/255.255.0.0,192.169.1.2/8", "[192.158.1.2/16,192.169.1.2/8]", "[192.158.1.2/16,192.169.1.2/8]", "[]", "[]", "[192.158.0.0/16,192.0.0.0/8]")] - [InlineData("192.158.1.2/16, localhost, fd23:184f:2029:0:3139:7386:67d7:d517, [10.10.10.10]", - "[192.158.1.2/16,127.0.0.1/32,fd23:184f:2029:0:3139:7386:67d7:d517/128]", - "[192.158.1.2/16,127.0.0.1/32]", - "[10.10.10.10/32]", - "[10.10.10.10/32]", - "[192.158.0.0/16,127.0.0.1/32,fd23:184f:2029:0:3139:7386:67d7:d517/128]")] public void TestCollections(string settings, string result1, string result2, string result3, string result4, string result5) { if (settings == null) |
