From eb022c49ccb310ee46d8d7b7f46678312b13abc6 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 23 Oct 2023 23:36:56 +0200 Subject: [PATCH 01/11] Update to .NET 8 --- .ci/azure-pipelines-test.yml | 2 +- .config/dotnet-tools.json | 2 +- .github/workflows/ci-openapi.yml | 4 +- .vscode/launch.json | 4 +- Directory.Packages.props | 52 +++++++++---------- Emby.Dlna/Emby.Dlna.csproj | 2 +- Emby.Naming/Emby.Naming.csproj | 2 +- Emby.Photos/Emby.Photos.csproj | 2 +- .../Emby.Server.Implementations.csproj | 2 +- Jellyfin.Api/Jellyfin.Api.csproj | 2 +- Jellyfin.Data/Jellyfin.Data.csproj | 2 +- .../Jellyfin.Networking.csproj | 2 +- .../Jellyfin.Server.Implementations.csproj | 2 +- Jellyfin.Server/Jellyfin.Server.csproj | 2 +- .../MediaBrowser.Common.csproj | 2 +- .../MediaBrowser.Controller.csproj | 2 +- .../MediaBrowser.LocalMetadata.csproj | 2 +- .../MediaBrowser.MediaEncoding.csproj | 2 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 2 +- .../MediaBrowser.Providers.csproj | 2 +- .../MediaBrowser.XbmcMetadata.csproj | 2 +- README.md | 2 +- RSSDP/RSSDP.csproj | 2 +- fedora/jellyfin.spec | 2 +- .../Emby.Server.Implementations.Fuzz.csproj | 2 +- fuzz/Emby.Server.Implementations.Fuzz/fuzz.sh | 2 +- .../Jellyfin.Api.Fuzz.csproj | 2 +- fuzz/Jellyfin.Api.Fuzz/fuzz.sh | 2 +- global.json | 2 +- .../Jellyfin.Drawing.Skia.csproj | 2 +- src/Jellyfin.Drawing/Jellyfin.Drawing.csproj | 2 +- .../Jellyfin.Extensions.csproj | 2 +- .../Jellyfin.MediaEncoding.Hls.csproj | 2 +- .../Jellyfin.MediaEncoding.Keyframes.csproj | 2 +- tests/Directory.Build.props | 2 +- 35 files changed, 62 insertions(+), 62 deletions(-) diff --git a/.ci/azure-pipelines-test.yml b/.ci/azure-pipelines-test.yml index 81362aab23..f15d6a6cda 100644 --- a/.ci/azure-pipelines-test.yml +++ b/.ci/azure-pipelines-test.yml @@ -94,5 +94,5 @@ jobs: displayName: 'Publish OpenAPI Artifact' condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) inputs: - targetPath: "tests/Jellyfin.Server.Integration.Tests/bin/Release/net7.0/openapi.json" + targetPath: "tests/Jellyfin.Server.Integration.Tests/bin/Release/net8.0/openapi.json" artifactName: 'OpenAPI Spec' diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index dbe78984a2..37aa7721e3 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -9,4 +9,4 @@ ] } } -} \ No newline at end of file +} diff --git a/.github/workflows/ci-openapi.yml b/.github/workflows/ci-openapi.yml index 8c463a8fcf..96b790c0c7 100644 --- a/.github/workflows/ci-openapi.yml +++ b/.github/workflows/ci-openapi.yml @@ -30,7 +30,7 @@ jobs: name: openapi-head retention-days: 14 if-no-files-found: error - path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net7.0/openapi.json + path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net8.0/openapi.json openapi-base: name: OpenAPI - BASE @@ -64,7 +64,7 @@ jobs: name: openapi-base retention-days: 14 if-no-files-found: error - path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net7.0/openapi.json + path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net8.0/openapi.json openapi-diff: permissions: diff --git a/.vscode/launch.json b/.vscode/launch.json index 55e6508a9a..be55764fd4 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,7 +6,7 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "build", - "program": "${workspaceFolder}/Jellyfin.Server/bin/Debug/net7.0/jellyfin.dll", + "program": "${workspaceFolder}/Jellyfin.Server/bin/Debug/net8.0/jellyfin.dll", "args": [], "cwd": "${workspaceFolder}/Jellyfin.Server", "console": "internalConsole", @@ -22,7 +22,7 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "build", - "program": "${workspaceFolder}/Jellyfin.Server/bin/Debug/net7.0/jellyfin.dll", + "program": "${workspaceFolder}/Jellyfin.Server/bin/Debug/net8.0/jellyfin.dll", "args": ["--nowebclient"], "cwd": "${workspaceFolder}/Jellyfin.Server", "console": "internalConsole", diff --git a/Directory.Packages.props b/Directory.Packages.props index 9109a5a18a..0d7dbf12ce 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -23,30 +23,30 @@ - + - + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + @@ -77,9 +77,9 @@ - - - + + + @@ -88,4 +88,4 @@ - \ No newline at end of file + diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index efbef05640..7336482e56 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -17,7 +17,7 @@ - net7.0 + net8.0 false true diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index bc7548189b..47f2605501 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -6,7 +6,7 @@ - net7.0 + net8.0 false true true diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index 5a04bbe49b..55dbe393c7 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -19,7 +19,7 @@ - net7.0 + net8.0 false true diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index b48e389ace..905f36e43e 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -40,7 +40,7 @@ - net7.0 + net8.0 false true diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 03dd97367f..2473fb288a 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -6,7 +6,7 @@ - net7.0 + net8.0 true diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 847853ca00..c26e6cf239 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 false true true diff --git a/Jellyfin.Networking/Jellyfin.Networking.csproj b/Jellyfin.Networking/Jellyfin.Networking.csproj index 43d08c37a1..30f41aeb22 100644 --- a/Jellyfin.Networking/Jellyfin.Networking.csproj +++ b/Jellyfin.Networking/Jellyfin.Networking.csproj @@ -1,6 +1,6 @@ - net7.0 + net8.0 false true diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index df1d5a3e18..0ed1578c70 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 false true diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 5479d22965..1d4d97551e 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -8,7 +8,7 @@ jellyfin Exe - net7.0 + net8.0 false false true diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 7d0d7a173b..9b3ea43683 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -29,7 +29,7 @@ - net7.0 + net8.0 false true true diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index f9468f6cdb..83faac3372 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -35,7 +35,7 @@ - net7.0 + net8.0 false true true diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index a39bc238a7..05177ac398 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -11,7 +11,7 @@ - net7.0 + net8.0 false true diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 1f39e88cde..a4e8194c15 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -6,7 +6,7 @@ - net7.0 + net8.0 false true diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 75c5bc6f00..89ec156a9f 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -14,7 +14,7 @@ - net7.0 + net8.0 false true true diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 8471f6fa10..7a50c6cf4b 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -27,7 +27,7 @@ - net7.0 + net8.0 false true ../jellyfin.ruleset diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index d7e34fd226..c20073eea1 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -15,7 +15,7 @@ - net7.0 + net8.0 false true diff --git a/README.md b/README.md index 2362741b47..911d9a094b 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ A second option is to build the project and then run the resulting executable fi ```bash dotnet build # Build the project -cd Jellyfin.Server/bin/Debug/net7.0 # Change into the build output directory +cd Jellyfin.Server/bin/Debug/net8.0 # Change into the build output directory ``` 2. Execute the build output. On Linux, Mac, etc. use `./jellyfin` and on Windows use `jellyfin.exe`. diff --git a/RSSDP/RSSDP.csproj b/RSSDP/RSSDP.csproj index df5d982f62..3f24de4e65 100644 --- a/RSSDP/RSSDP.csproj +++ b/RSSDP/RSSDP.csproj @@ -11,7 +11,7 @@ - net7.0 + net8.0 false AllDisabledByDefault disable diff --git a/fedora/jellyfin.spec b/fedora/jellyfin.spec index e783689069..c56a189ce9 100644 --- a/fedora/jellyfin.spec +++ b/fedora/jellyfin.spec @@ -73,7 +73,7 @@ dotnet publish --configuration Release --self-contained --runtime %{dotnet_runti %install # Jellyfin files %{__mkdir} -p %{buildroot}%{_libdir}/jellyfin %{buildroot}%{_bindir} -%{__cp} -r Jellyfin.Server/bin/Release/net7.0/%{dotnet_runtime}/publish/* %{buildroot}%{_libdir}/jellyfin +%{__cp} -r Jellyfin.Server/bin/Release/net8.0/%{dotnet_runtime}/publish/* %{buildroot}%{_libdir}/jellyfin %{__install} -D %{SOURCE10} %{buildroot}%{_bindir}/jellyfin sed -i -e 's|/usr/lib64|%{_libdir}|g' %{buildroot}%{_bindir}/jellyfin diff --git a/fuzz/Emby.Server.Implementations.Fuzz/Emby.Server.Implementations.Fuzz.csproj b/fuzz/Emby.Server.Implementations.Fuzz/Emby.Server.Implementations.Fuzz.csproj index 1e3f8a0482..73aae3f3df 100644 --- a/fuzz/Emby.Server.Implementations.Fuzz/Emby.Server.Implementations.Fuzz.csproj +++ b/fuzz/Emby.Server.Implementations.Fuzz/Emby.Server.Implementations.Fuzz.csproj @@ -2,7 +2,7 @@ Exe - net7.0 + net8.0 diff --git a/fuzz/Emby.Server.Implementations.Fuzz/fuzz.sh b/fuzz/Emby.Server.Implementations.Fuzz/fuzz.sh index aa2a34cdde..80a5cd7c1f 100755 --- a/fuzz/Emby.Server.Implementations.Fuzz/fuzz.sh +++ b/fuzz/Emby.Server.Implementations.Fuzz/fuzz.sh @@ -8,4 +8,4 @@ cp bin/Emby.Server.Implementations.dll . dotnet build mkdir -p Findings -AFL_SKIP_BIN_CHECK=1 afl-fuzz -i "Testcases/$1" -o "Findings/$1" -t 5000 ./bin/Debug/net7.0/Emby.Server.Implementations.Fuzz "$1" +AFL_SKIP_BIN_CHECK=1 afl-fuzz -i "Testcases/$1" -o "Findings/$1" -t 5000 ./bin/Debug/net8.0/Emby.Server.Implementations.Fuzz "$1" diff --git a/fuzz/Jellyfin.Api.Fuzz/Jellyfin.Api.Fuzz.csproj b/fuzz/Jellyfin.Api.Fuzz/Jellyfin.Api.Fuzz.csproj index da46e63a5e..faac7d976f 100644 --- a/fuzz/Jellyfin.Api.Fuzz/Jellyfin.Api.Fuzz.csproj +++ b/fuzz/Jellyfin.Api.Fuzz/Jellyfin.Api.Fuzz.csproj @@ -2,7 +2,7 @@ Exe - net7.0 + net8.0 diff --git a/fuzz/Jellyfin.Api.Fuzz/fuzz.sh b/fuzz/Jellyfin.Api.Fuzz/fuzz.sh index edf9655626..96b0192cf7 100755 --- a/fuzz/Jellyfin.Api.Fuzz/fuzz.sh +++ b/fuzz/Jellyfin.Api.Fuzz/fuzz.sh @@ -8,4 +8,4 @@ cp bin/Jellyfin.Api.dll . dotnet build mkdir -p Findings -AFL_SKIP_BIN_CHECK=1 afl-fuzz -i "Testcases/$1" -o "Findings/$1" -t 5000 ./bin/Debug/net7.0/Jellyfin.Api.Fuzz "$1" +AFL_SKIP_BIN_CHECK=1 afl-fuzz -i "Testcases/$1" -o "Findings/$1" -t 5000 ./bin/Debug/net8.0/Jellyfin.Api.Fuzz "$1" diff --git a/global.json b/global.json index 24335d7a0f..9db4b532ce 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "7.0.0", + "version": "8.0.0", "rollForward": "latestMinor" } } diff --git a/src/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/src/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index 3c417f8ff0..f0f8e7afcd 100644 --- a/src/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/src/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -6,7 +6,7 @@ - net7.0 + net8.0 false true diff --git a/src/Jellyfin.Drawing/Jellyfin.Drawing.csproj b/src/Jellyfin.Drawing/Jellyfin.Drawing.csproj index d7ef6f8e77..23c4c0a9a4 100644 --- a/src/Jellyfin.Drawing/Jellyfin.Drawing.csproj +++ b/src/Jellyfin.Drawing/Jellyfin.Drawing.csproj @@ -6,7 +6,7 @@ - net7.0 + net8.0 false true diff --git a/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj index 997df6dbed..c91f5d008e 100644 --- a/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj +++ b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 false true true diff --git a/src/Jellyfin.MediaEncoding.Hls/Jellyfin.MediaEncoding.Hls.csproj b/src/Jellyfin.MediaEncoding.Hls/Jellyfin.MediaEncoding.Hls.csproj index 76dde1cf6a..ee79802a1e 100644 --- a/src/Jellyfin.MediaEncoding.Hls/Jellyfin.MediaEncoding.Hls.csproj +++ b/src/Jellyfin.MediaEncoding.Hls/Jellyfin.MediaEncoding.Hls.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 true diff --git a/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj b/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj index 0d91a447bc..c79dcee3c4 100644 --- a/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj +++ b/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 true diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props index de8fc1bb8b..bec3481cb7 100644 --- a/tests/Directory.Build.props +++ b/tests/Directory.Build.props @@ -4,7 +4,7 @@ - net7.0 + net8.0 false $(MSBuildThisFileDirectory)/jellyfin-tests.ruleset From 99e0d46ad93c1f2e62aed67c26b92f256610f1a6 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 23 Oct 2023 23:45:01 +0200 Subject: [PATCH 02/11] Use System.Net.IPNetwork --- Emby.Dlna/Main/DlnaEntryPoint.cs | 363 ++++++++++++++++++ Jellyfin.Networking/Manager/NetworkManager.cs | 17 +- .../ApiServiceCollectionExtensions.cs | 3 +- MediaBrowser.Common/Net/NetworkConstants.cs | 1 - MediaBrowser.Common/Net/NetworkUtils.cs | 3 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 1 - MediaBrowser.Model/Net/IPData.cs | 5 +- .../Jellyfin.Drawing.Skia.csproj | 2 + .../ParseNetworkTests.cs | 3 +- 9 files changed, 379 insertions(+), 19 deletions(-) create mode 100644 Emby.Dlna/Main/DlnaEntryPoint.cs diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs new file mode 100644 index 0000000000..dbc47d9816 --- /dev/null +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -0,0 +1,363 @@ +#nullable disable + +#pragma warning disable CS1591 + +using System; +using System.Globalization; +using System.Linq; +using System.Net.Http; +using System.Net.Sockets; +using System.Threading.Tasks; +using Emby.Dlna.PlayTo; +using Emby.Dlna.Ssdp; +using Jellyfin.Networking.Configuration; +using Jellyfin.Networking.Extensions; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dlna; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Globalization; +using Microsoft.Extensions.Logging; +using Rssdp; +using Rssdp.Infrastructure; + +namespace Emby.Dlna.Main +{ + public sealed class DlnaEntryPoint : IServerEntryPoint, IRunBeforeStartup + { + private readonly IServerConfigurationManager _config; + private readonly ILogger _logger; + private readonly IServerApplicationHost _appHost; + private readonly ISessionManager _sessionManager; + private readonly IHttpClientFactory _httpClientFactory; + private readonly ILibraryManager _libraryManager; + private readonly IUserManager _userManager; + private readonly IDlnaManager _dlnaManager; + private readonly IImageProcessor _imageProcessor; + private readonly IUserDataManager _userDataManager; + private readonly ILocalizationManager _localization; + private readonly IMediaSourceManager _mediaSourceManager; + private readonly IMediaEncoder _mediaEncoder; + private readonly IDeviceDiscovery _deviceDiscovery; + private readonly ISsdpCommunicationsServer _communicationsServer; + private readonly INetworkManager _networkManager; + private readonly object _syncLock = new(); + private readonly bool _disabled; + + private PlayToManager _manager; + private SsdpDevicePublisher _publisher; + + private bool _disposed; + + public DlnaEntryPoint( + IServerConfigurationManager config, + ILoggerFactory loggerFactory, + IServerApplicationHost appHost, + ISessionManager sessionManager, + IHttpClientFactory httpClientFactory, + ILibraryManager libraryManager, + IUserManager userManager, + IDlnaManager dlnaManager, + IImageProcessor imageProcessor, + IUserDataManager userDataManager, + ILocalizationManager localizationManager, + IMediaSourceManager mediaSourceManager, + IDeviceDiscovery deviceDiscovery, + IMediaEncoder mediaEncoder, + ISsdpCommunicationsServer communicationsServer, + INetworkManager networkManager) + { + _config = config; + _appHost = appHost; + _sessionManager = sessionManager; + _httpClientFactory = httpClientFactory; + _libraryManager = libraryManager; + _userManager = userManager; + _dlnaManager = dlnaManager; + _imageProcessor = imageProcessor; + _userDataManager = userDataManager; + _localization = localizationManager; + _mediaSourceManager = mediaSourceManager; + _deviceDiscovery = deviceDiscovery; + _mediaEncoder = mediaEncoder; + _communicationsServer = communicationsServer; + _networkManager = networkManager; + _logger = loggerFactory.CreateLogger(); + + var netConfig = config.GetConfiguration(NetworkConfigurationStore.StoreKey); + _disabled = appHost.ListenWithHttps && netConfig.RequireHttps; + + if (_disabled && _config.GetDlnaConfiguration().EnableServer) + { + _logger.LogError("The DLNA specification does not support HTTPS."); + } + } + + public async Task RunAsync() + { + await ((DlnaManager)_dlnaManager).InitProfilesAsync().ConfigureAwait(false); + + if (_disabled) + { + // No use starting as dlna won't work, as we're running purely on HTTPS. + return; + } + + ReloadComponents(); + + _config.NamedConfigurationUpdated += OnNamedConfigurationUpdated; + } + + private void OnNamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) + { + if (string.Equals(e.Key, "dlna", StringComparison.OrdinalIgnoreCase)) + { + ReloadComponents(); + } + } + + private void ReloadComponents() + { + var options = _config.GetDlnaConfiguration(); + StartDeviceDiscovery(); + + if (options.EnableServer) + { + StartDevicePublisher(options); + } + else + { + DisposeDevicePublisher(); + } + + if (options.EnablePlayTo) + { + StartPlayToManager(); + } + else + { + DisposePlayToManager(); + } + } + + private void StartDeviceDiscovery() + { + try + { + ((DeviceDiscovery)_deviceDiscovery).Start(_communicationsServer); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error starting device discovery"); + } + } + + public void StartDevicePublisher(Configuration.DlnaOptions options) + { + if (_publisher is not null) + { + return; + } + + try + { + _publisher = new SsdpDevicePublisher( + _communicationsServer, + Environment.OSVersion.Platform.ToString(), + // Can not use VersionString here since that includes OS and version + Environment.OSVersion.Version.ToString(), + _config.GetDlnaConfiguration().SendOnlyMatchedHost) + { + LogFunction = (msg) => _logger.LogDebug("{Msg}", msg), + SupportPnpRootDevice = false + }; + + RegisterServerEndpoints(); + + if (options.BlastAliveMessages) + { + _publisher.StartSendingAliveNotifications(TimeSpan.FromSeconds(options.BlastAliveMessageIntervalSeconds)); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Error registering endpoint"); + } + } + + private void RegisterServerEndpoints() + { + var udn = CreateUuid(_appHost.SystemId); + var descriptorUri = "/dlna/" + udn + "/description.xml"; + + // Only get bind addresses in LAN + // IPv6 is currently unsupported + var validInterfaces = _networkManager.GetInternalBindAddresses() + .Where(x => x.Address is not null) + .Where(x => x.AddressFamily != AddressFamily.InterNetworkV6) + .ToList(); + + if (validInterfaces.Count == 0) + { + // No interfaces returned, fall back to loopback + validInterfaces = _networkManager.GetLoopbacks().ToList(); + } + + foreach (var intf in validInterfaces) + { + var fullService = "urn:schemas-upnp-org:device:MediaServer:1"; + + _logger.LogInformation("Registering publisher for {ResourceName} on {DeviceAddress}", fullService, intf.Address); + + var uri = new UriBuilder(_appHost.GetApiUrlForLocalAccess(intf.Address, false) + descriptorUri); + + var device = new SsdpRootDevice + { + CacheLifetime = TimeSpan.FromSeconds(1800), // How long SSDP clients can cache this info. + Location = uri.Uri, // Must point to the URL that serves your devices UPnP description document. + Address = intf.Address, + PrefixLength = NetworkExtensions.MaskToCidr(intf.Subnet.BaseAddress), + FriendlyName = "Jellyfin", + Manufacturer = "Jellyfin", + ModelName = "Jellyfin Server", + Uuid = udn + // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc. + }; + + SetProperties(device, fullService); + _publisher.AddDevice(device); + + var embeddedDevices = new[] + { + "urn:schemas-upnp-org:service:ContentDirectory:1", + "urn:schemas-upnp-org:service:ConnectionManager:1", + // "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1" + }; + + foreach (var subDevice in embeddedDevices) + { + var embeddedDevice = new SsdpEmbeddedDevice + { + FriendlyName = device.FriendlyName, + Manufacturer = device.Manufacturer, + ModelName = device.ModelName, + Uuid = udn + // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc. + }; + + SetProperties(embeddedDevice, subDevice); + device.AddDevice(embeddedDevice); + } + } + } + + private static string CreateUuid(string text) + { + if (!Guid.TryParse(text, out var guid)) + { + guid = text.GetMD5(); + } + + return guid.ToString("D", CultureInfo.InvariantCulture); + } + + private static void SetProperties(SsdpDevice device, string fullDeviceType) + { + var serviceParts = fullDeviceType + .Replace("urn:", string.Empty, StringComparison.OrdinalIgnoreCase) + .Replace(":1", string.Empty, StringComparison.OrdinalIgnoreCase) + .Split(':'); + + device.DeviceTypeNamespace = serviceParts[0].Replace('.', '-'); + device.DeviceClass = serviceParts[1]; + device.DeviceType = serviceParts[2]; + } + + private void StartPlayToManager() + { + lock (_syncLock) + { + if (_manager is not null) + { + return; + } + + try + { + _manager = new PlayToManager( + _logger, + _sessionManager, + _libraryManager, + _userManager, + _dlnaManager, + _appHost, + _imageProcessor, + _deviceDiscovery, + _httpClientFactory, + _userDataManager, + _localization, + _mediaSourceManager, + _mediaEncoder); + + _manager.Start(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error starting PlayTo manager"); + } + } + } + + private void DisposePlayToManager() + { + lock (_syncLock) + { + if (_manager is not null) + { + try + { + _logger.LogInformation("Disposing PlayToManager"); + _manager.Dispose(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error disposing PlayTo manager"); + } + + _manager = null; + } + } + } + + public void DisposeDevicePublisher() + { + if (_publisher is not null) + { + _logger.LogInformation("Disposing SsdpDevicePublisher"); + _publisher.Dispose(); + _publisher = null; + } + } + + /// + public void Dispose() + { + if (_disposed) + { + return; + } + + DisposeDevicePublisher(); + DisposePlayToManager(); + _disposed = true; + } + } +} diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index b0fe4aba65..3c03d137be 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -11,7 +11,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Net; using MediaBrowser.Model.Net; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.HttpOverrides; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using static MediaBrowser.Controller.Extensions.ConfigurationExtensions; @@ -530,7 +529,7 @@ namespace Jellyfin.Networking.Manager { foreach (var lan in _lanSubnets) { - var lanPrefix = lan.Prefix; + var lanPrefix = lan.BaseAddress; publishedServerUrls.Add( new PublishedServerUriOverride( new IPData(lanPrefix, new IPNetwork(lanPrefix, lan.PrefixLength)), @@ -541,7 +540,7 @@ namespace Jellyfin.Networking.Manager } else if (NetworkUtils.TryParseToSubnet(identifier, out var result) && result is not null) { - var data = new IPData(result.Prefix, result); + var data = new IPData(result.BaseAddress, result); publishedServerUrls.Add( new PublishedServerUriOverride( data, @@ -607,7 +606,7 @@ namespace Jellyfin.Networking.Manager var parts = details.Split(','); if (NetworkUtils.TryParseToSubnet(parts[0], out var subnet)) { - var address = subnet.Prefix; + var address = subnet.BaseAddress; var index = int.Parse(parts[1], CultureInfo.InvariantCulture); if (address.AddressFamily == AddressFamily.InterNetwork || address.AddressFamily == AddressFamily.InterNetworkV6) { @@ -881,7 +880,7 @@ namespace Jellyfin.Networking.Manager { if (NetworkUtils.TryParseToSubnet(address, out var subnet)) { - return IPAddress.IsLoopback(subnet.Prefix) || (_lanSubnets.Any(x => x.Contains(subnet.Prefix)) && !_excludedSubnets.Any(x => x.Contains(subnet.Prefix))); + return IPAddress.IsLoopback(subnet.BaseAddress) || (_lanSubnets.Any(x => x.Contains(subnet.BaseAddress)) && !_excludedSubnets.Any(x => x.Contains(subnet.BaseAddress))); } if (NetworkUtils.TryParseHost(address, out var addresses, IsIPv4Enabled, IsIPv6Enabled)) @@ -1112,12 +1111,12 @@ namespace Jellyfin.Networking.Manager var logLevel = debug ? LogLevel.Debug : LogLevel.Information; if (_logger.IsEnabled(logLevel)) { - _logger.Log(logLevel, "Defined LAN addresses: {0}", _lanSubnets.Select(s => s.Prefix + "/" + s.PrefixLength)); - _logger.Log(logLevel, "Defined LAN exclusions: {0}", _excludedSubnets.Select(s => s.Prefix + "/" + s.PrefixLength)); - _logger.Log(logLevel, "Using LAN addresses: {0}", _lanSubnets.Where(s => !_excludedSubnets.Contains(s)).Select(s => s.Prefix + "/" + s.PrefixLength)); + _logger.Log(logLevel, "Defined LAN addresses: {0}", _lanSubnets.Select(s => s.BaseAddress + "/" + s.PrefixLength)); + _logger.Log(logLevel, "Defined LAN exclusions: {0}", _excludedSubnets.Select(s => s.BaseAddress + "/" + s.PrefixLength)); + _logger.Log(logLevel, "Using LAN addresses: {0}", _lanSubnets.Where(s => !_excludedSubnets.Contains(s)).Select(s => s.BaseAddress + "/" + s.PrefixLength)); _logger.Log(logLevel, "Using bind addresses: {0}", _interfaces.OrderByDescending(x => x.AddressFamily == AddressFamily.InterNetwork).Select(x => x.Address)); _logger.Log(logLevel, "Remote IP filter is {0}", config.IsRemoteIPFilterBlacklist ? "Blocklist" : "Allowlist"); - _logger.Log(logLevel, "Filter list: {0}", _remoteAddressFilter.Select(s => s.Prefix + "/" + s.PrefixLength)); + _logger.Log(logLevel, "Filter list: {0}", _remoteAddressFilter.Select(s => s.BaseAddress + "/" + s.PrefixLength)); } } } diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 89f9c08e7e..753029f2cd 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -30,7 +30,6 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Cors.Infrastructure; -using Microsoft.AspNetCore.HttpOverrides; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; @@ -280,7 +279,7 @@ namespace Jellyfin.Server.Extensions { if (subnet is not null) { - AddIPAddress(config, options, subnet.Prefix, subnet.PrefixLength); + AddIPAddress(config, options, subnet.BaseAddress, subnet.PrefixLength); } } else if (NetworkUtils.TryParseHost(allowedProxies[i], out var addresses, config.EnableIPv4, config.EnableIPv6)) diff --git a/MediaBrowser.Common/Net/NetworkConstants.cs b/MediaBrowser.Common/Net/NetworkConstants.cs index 396bc8fb50..fe7ab89632 100644 --- a/MediaBrowser.Common/Net/NetworkConstants.cs +++ b/MediaBrowser.Common/Net/NetworkConstants.cs @@ -1,5 +1,4 @@ using System.Net; -using Microsoft.AspNetCore.HttpOverrides; namespace MediaBrowser.Common.Net; diff --git a/MediaBrowser.Common/Net/NetworkUtils.cs b/MediaBrowser.Common/Net/NetworkUtils.cs index f3bff7fa95..452cb694ed 100644 --- a/MediaBrowser.Common/Net/NetworkUtils.cs +++ b/MediaBrowser.Common/Net/NetworkUtils.cs @@ -5,6 +5,7 @@ using System.Net; using System.Net.Sockets; using System.Text.RegularExpressions; using Jellyfin.Extensions; +using Jellyfin.Networking.Constants; using Microsoft.AspNetCore.HttpOverrides; namespace MediaBrowser.Common.Net; @@ -335,7 +336,7 @@ public static partial class NetworkUtils /// The broadcast address. public static IPAddress GetBroadcastAddress(IPNetwork network) { - var addressBytes = network.Prefix.GetAddressBytes(); + var addressBytes = network.BaseAddress.GetAddressBytes(); uint ipAddress = BitConverter.ToUInt32(addressBytes, 0); uint ipMaskV4 = BitConverter.ToUInt32(CidrToMask(network.PrefixLength, AddressFamily.InterNetwork).GetAddressBytes(), 0); uint broadCastIPAddress = ipAddress | ~ipMaskV4; diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 89ec156a9f..1ca5e4327c 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -33,7 +33,6 @@ - diff --git a/MediaBrowser.Model/Net/IPData.cs b/MediaBrowser.Model/Net/IPData.cs index e9fcd67975..e016ffea10 100644 --- a/MediaBrowser.Model/Net/IPData.cs +++ b/MediaBrowser.Model/Net/IPData.cs @@ -1,6 +1,5 @@ using System.Net; using System.Net.Sockets; -using Microsoft.AspNetCore.HttpOverrides; namespace MediaBrowser.Model.Net; @@ -66,9 +65,9 @@ public class IPData { if (Address.Equals(IPAddress.None)) { - return Subnet.Prefix.AddressFamily.Equals(IPAddress.None) + return Subnet.BaseAddress.AddressFamily.Equals(IPAddress.None) ? AddressFamily.Unspecified - : Subnet.Prefix.AddressFamily; + : Subnet.BaseAddress.AddressFamily; } else { diff --git a/src/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/src/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index f0f8e7afcd..0590ded32a 100644 --- a/src/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/src/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -9,6 +9,8 @@ net8.0 false true + + NU1903 diff --git a/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs b/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs index e0b65cbc44..8d464d4e75 100644 --- a/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs +++ b/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs @@ -6,7 +6,6 @@ using Jellyfin.Server.Extensions; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Net; using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.HttpOverrides; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging.Abstractions; using Moq; @@ -99,7 +98,7 @@ namespace Jellyfin.Server.Tests Assert.Equal(knownNetworks.Length, options.KnownNetworks.Count); foreach (var item in knownNetworks) { - Assert.NotNull(options.KnownNetworks.FirstOrDefault(x => x.Prefix.Equals(item.Prefix) && x.PrefixLength == item.PrefixLength)); + Assert.NotNull(options.KnownNetworks.FirstOrDefault(x => x.BaseAddress.Equals(item.BaseAddress) && x.PrefixLength == item.PrefixLength)); } } From b62b0ec2b581369de42c69305773f0edb9d701b4 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 24 Oct 2023 00:10:31 +0200 Subject: [PATCH 03/11] Fix warnings --- Emby.Server.Implementations/ApplicationHost.cs | 1 + .../EntryPoints/UdpServerEntryPoint.cs | 1 + .../LiveTv/TunerHosts/LiveStream.cs | 6 ++---- Jellyfin.Api/Auth/CustomAuthenticationHandler.cs | 5 ++--- Jellyfin.Api/Controllers/ImageController.cs | 16 ++++++++-------- Jellyfin.Api/Helpers/DynamicHlsHelper.cs | 4 ++-- Jellyfin.Api/Helpers/StreamingHelpers.cs | 14 +++++++------- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 2 +- .../HappyEyeballs/HttpClientExtension.cs | 6 +++--- Jellyfin.Networking/Manager/NetworkManager.cs | 11 ++++++----- .../Security/AuthorizationContext.cs | 2 +- .../Users/UserManager.cs | 2 +- .../Extensions/ApiServiceCollectionExtensions.cs | 8 +++++--- .../Migrations/Routines/MigrateRatingLevels.cs | 6 +----- MediaBrowser.Common/Net/NetworkUtils.cs | 2 +- .../MediaEncoding/EncodingHelper.cs | 1 + .../Probing/ProbeResultNormalizer.cs | 4 ++-- MediaBrowser.Model/Dlna/StreamBuilder.cs | 11 +++-------- MediaBrowser.Providers/Lyric/LrcLyricParser.cs | 2 +- .../Manager/ItemImageProvider.cs | 4 ++-- .../MediaInfo/AudioImageProvider.cs | 4 ++-- .../MediaInfo/MediaInfoResolver.cs | 2 +- .../Music/AlbumMetadataService.cs | 2 +- .../Plugins/AudioDb/AudioDbAlbumImageProvider.cs | 2 +- .../AudioDb/AudioDbArtistImageProvider.cs | 2 +- .../TV/SeriesMetadataService.cs | 2 +- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 4 ++-- jellyfin.ruleset | 3 +++ .../FfProbe/FfProbeKeyframeExtractor.cs | 7 ++++--- 29 files changed, 67 insertions(+), 69 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 40aee063eb..9affe235db 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -99,6 +99,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Prometheus.DotNetRuntime; using static MediaBrowser.Controller.Extensions.ConfigurationExtensions; +using IConfigurationManager = MediaBrowser.Common.Configuration.IConfigurationManager; using WebSocketManager = Emby.Server.Implementations.HttpServer.WebSocketManager; namespace Emby.Server.Implementations diff --git a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs index 18e60b2101..56ccb21ee7 100644 --- a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs +++ b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs @@ -12,6 +12,7 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Plugins; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; +using IConfigurationManager = MediaBrowser.Common.Configuration.IConfigurationManager; namespace Emby.Server.Implementations.EntryPoints { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 3ae9e256b2..767b941366 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -84,15 +84,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts return Task.CompletedTask; } - public Task Close() + public async Task Close() { EnableStreamSharing = false; Logger.LogInformation("Closing {Type}", GetType().Name); - LiveStreamCancellationTokenSource.Cancel(); - - return Task.CompletedTask; + await LiveStreamCancellationTokenSource.CancelAsync().ConfigureAwait(false); } public Stream GetStream() diff --git a/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs b/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs index bd3e7d9e3e..2853e69b01 100644 --- a/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs +++ b/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs @@ -27,13 +27,12 @@ namespace Jellyfin.Api.Auth /// Options monitor. /// The logger. /// The url encoder. - /// The system clock. public CustomAuthenticationHandler( IAuthService authService, IOptionsMonitor options, ILoggerFactory logger, - UrlEncoder encoder, - ISystemClock clock) : base(options, logger, encoder, clock) + UrlEncoder encoder) + : base(options, logger, encoder) { _authService = authService; _logger = logger.CreateLogger(); diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 1e6580ed15..7d1a54eced 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -2080,30 +2080,30 @@ public class ImageController : BaseJellyfinApiController foreach (var (key, value) in headers) { - Response.Headers.Add(key, value); + Response.Headers.Append(key, value); } Response.ContentType = imageContentType ?? MediaTypeNames.Text.Plain; - Response.Headers.Add(HeaderNames.Age, Convert.ToInt64((DateTime.UtcNow - dateImageModified).TotalSeconds).ToString(CultureInfo.InvariantCulture)); - Response.Headers.Add(HeaderNames.Vary, HeaderNames.Accept); + Response.Headers.Append(HeaderNames.Age, Convert.ToInt64((DateTime.UtcNow - dateImageModified).TotalSeconds).ToString(CultureInfo.InvariantCulture)); + Response.Headers.Append(HeaderNames.Vary, HeaderNames.Accept); if (disableCaching) { - Response.Headers.Add(HeaderNames.CacheControl, "no-cache, no-store, must-revalidate"); - Response.Headers.Add(HeaderNames.Pragma, "no-cache, no-store, must-revalidate"); + Response.Headers.Append(HeaderNames.CacheControl, "no-cache, no-store, must-revalidate"); + Response.Headers.Append(HeaderNames.Pragma, "no-cache, no-store, must-revalidate"); } else { if (cacheDuration.HasValue) { - Response.Headers.Add(HeaderNames.CacheControl, "public, max-age=" + cacheDuration.Value.TotalSeconds); + Response.Headers.Append(HeaderNames.CacheControl, "public, max-age=" + cacheDuration.Value.TotalSeconds); } else { - Response.Headers.Add(HeaderNames.CacheControl, "public"); + Response.Headers.Append(HeaderNames.CacheControl, "public"); } - Response.Headers.Add(HeaderNames.LastModified, dateImageModified.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss \"GMT\"", CultureInfo.InvariantCulture)); + Response.Headers.Append(HeaderNames.LastModified, dateImageModified.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss \"GMT\"", CultureInfo.InvariantCulture)); // if the image was not modified since "ifModifiedSinceHeader"-header, return a HTTP status code 304 not modified if (!(dateImageModified > ifModifiedSinceHeader) && cacheDuration.HasValue) diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index 24082fcff1..a8df628f0d 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -147,7 +147,7 @@ public class DynamicHlsHelper cancellationTokenSource.Token) .ConfigureAwait(false); - _httpContextAccessor.HttpContext.Response.Headers.Add(HeaderNames.Expires, "0"); + _httpContextAccessor.HttpContext.Response.Headers.Append(HeaderNames.Expires, "0"); if (isHeadRequest) { return new FileContentResult(Array.Empty(), MimeTypes.GetMimeType("playlist.m3u8")); @@ -568,7 +568,7 @@ public class DynamicHlsHelper && state.VideoStream is not null && state.VideoStream.Level.HasValue) { - levelString = state.VideoStream.Level.ToString() ?? string.Empty; + levelString = state.VideoStream.Level.Value.ToString(CultureInfo.InvariantCulture) ?? string.Empty; } else { diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index 6fbbceeabb..7d9a389312 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -279,15 +279,15 @@ public static class StreamingHelpers var profile = state.DeviceProfile; StringValues transferMode = request.Headers["transferMode.dlna.org"]; - responseHeaders.Add("transferMode.dlna.org", string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode.ToString()); - responseHeaders.Add("realTimeInfo.dlna.org", "DLNA.ORG_TLAG=*"); + responseHeaders.Append("transferMode.dlna.org", string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode.ToString()); + responseHeaders.Append("realTimeInfo.dlna.org", "DLNA.ORG_TLAG=*"); if (state.RunTimeTicks.HasValue) { if (string.Equals(request.Headers["getMediaInfo.sec"], "1", StringComparison.OrdinalIgnoreCase)) { var ms = TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalMilliseconds; - responseHeaders.Add("MediaInfo.sec", string.Format( + responseHeaders.Append("MediaInfo.sec", string.Format( CultureInfo.InvariantCulture, "SEC_Duration={0};", Convert.ToInt32(ms))); @@ -305,7 +305,7 @@ public static class StreamingHelpers if (!state.IsVideoRequest) { - responseHeaders.Add("contentFeatures.dlna.org", ContentFeatureBuilder.BuildAudioHeader( + responseHeaders.Append("contentFeatures.dlna.org", ContentFeatureBuilder.BuildAudioHeader( profile, state.OutputContainer, audioCodec, @@ -321,7 +321,7 @@ public static class StreamingHelpers { var videoCodec = state.ActualOutputVideoCodec; - responseHeaders.Add( + responseHeaders.Append( "contentFeatures.dlna.org", ContentFeatureBuilder.BuildVideoHeader(profile, state.OutputContainer, videoCodec, audioCodec, state.OutputWidth, state.OutputHeight, state.TargetVideoBitDepth, state.OutputVideoBitrate, state.TargetTimestamp, isStaticallyStreamed, state.RunTimeTicks, state.TargetVideoProfile, state.TargetVideoRangeType, state.TargetVideoLevel, state.TargetFramerate, state.TargetPacketLength, state.TranscodeSeekInfo, state.IsTargetAnamorphic, state.IsTargetInterlaced, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, state.TargetVideoCodecTag, state.IsTargetAVC).FirstOrDefault() ?? string.Empty); } @@ -404,12 +404,12 @@ public static class StreamingHelpers var runtimeSeconds = TimeSpan.FromTicks(state.RunTimeTicks!.Value).TotalSeconds.ToString(CultureInfo.InvariantCulture); var startSeconds = TimeSpan.FromTicks(startTimeTicks ?? 0).TotalSeconds.ToString(CultureInfo.InvariantCulture); - responseHeaders.Add("TimeSeekRange.dlna.org", string.Format( + responseHeaders.Append("TimeSeekRange.dlna.org", string.Format( CultureInfo.InvariantCulture, "npt={0}-{1}/{1}", startSeconds, runtimeSeconds)); - responseHeaders.Add("X-AvailableSeekRange", string.Format( + responseHeaders.Append("X-AvailableSeekRange", string.Format( CultureInfo.InvariantCulture, "1 npt={0}-{1}", startSeconds, diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index c16a586d60..5b407e4a95 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -280,6 +280,7 @@ public class TranscodingJobHelper : IDisposable if (job.CancellationTokenSource?.IsCancellationRequested == false) { +#pragma warning disable CA1849 // Can't await in lock block job.CancellationTokenSource.Cancel(); } } @@ -291,7 +292,6 @@ public class TranscodingJobHelper : IDisposable lock (job.ProcessLock!) { -#pragma warning disable CA1849 // Can't await in lock block job.TranscodingThrottler?.Stop().GetAwaiter().GetResult(); var process = job.Process; diff --git a/Jellyfin.Networking/HappyEyeballs/HttpClientExtension.cs b/Jellyfin.Networking/HappyEyeballs/HttpClientExtension.cs index 59e6956c71..d59e4e5e38 100644 --- a/Jellyfin.Networking/HappyEyeballs/HttpClientExtension.cs +++ b/Jellyfin.Networking/HappyEyeballs/HttpClientExtension.cs @@ -65,7 +65,7 @@ namespace Jellyfin.Networking.HappyEyeballs // See https://github.com/dotnet/corefx/pull/29792/files#r189415885 for more details. if (await Task.WhenAny(tryConnectAsyncIPv6, Task.Delay(200, cancelIPv6.Token)).ConfigureAwait(false) == tryConnectAsyncIPv6 && tryConnectAsyncIPv6.IsCompletedSuccessfully) { - cancelIPv6.Cancel(); + await cancelIPv6.CancelAsync().ConfigureAwait(false); return tryConnectAsyncIPv6.GetAwaiter().GetResult(); } @@ -76,7 +76,7 @@ namespace Jellyfin.Networking.HappyEyeballs { if (tryConnectAsyncIPv6.IsCompletedSuccessfully) { - cancelIPv4.Cancel(); + await cancelIPv4.CancelAsync().ConfigureAwait(false); return tryConnectAsyncIPv6.GetAwaiter().GetResult(); } @@ -86,7 +86,7 @@ namespace Jellyfin.Networking.HappyEyeballs { if (tryConnectAsyncIPv4.IsCompletedSuccessfully) { - cancelIPv6.Cancel(); + await cancelIPv6.CancelAsync().ConfigureAwait(false); return tryConnectAsyncIPv4.GetAwaiter().GetResult(); } diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index 3c03d137be..dbf7127a68 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -14,6 +14,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using static MediaBrowser.Controller.Extensions.ConfigurationExtensions; +using IConfigurationManager = MediaBrowser.Common.Configuration.IConfigurationManager; namespace Jellyfin.Networking.Manager { @@ -422,7 +423,7 @@ namespace Jellyfin.Networking.Manager { // Parse config values into filter collection var remoteIPFilter = config.RemoteIPFilter; - if (remoteIPFilter.Any() && !string.IsNullOrWhiteSpace(remoteIPFilter.First())) + if (remoteIPFilter.Length != 0 && !string.IsNullOrWhiteSpace(remoteIPFilter[0])) { // Parse all IPs with netmask to a subnet var remoteAddressFilter = new List(); @@ -540,7 +541,7 @@ namespace Jellyfin.Networking.Manager } else if (NetworkUtils.TryParseToSubnet(identifier, out var result) && result is not null) { - var data = new IPData(result.BaseAddress, result); + var data = new IPData(result.Value.BaseAddress, result); publishedServerUrls.Add( new PublishedServerUriOverride( data, @@ -606,11 +607,11 @@ namespace Jellyfin.Networking.Manager var parts = details.Split(','); if (NetworkUtils.TryParseToSubnet(parts[0], out var subnet)) { - var address = subnet.BaseAddress; + var address = subnet.Value.BaseAddress; var index = int.Parse(parts[1], CultureInfo.InvariantCulture); if (address.AddressFamily == AddressFamily.InterNetwork || address.AddressFamily == AddressFamily.InterNetworkV6) { - var data = new IPData(address, subnet, parts[2]) + var data = new IPData(address, subnet.Value, parts[2]) { Index = index }; @@ -880,7 +881,7 @@ namespace Jellyfin.Networking.Manager { if (NetworkUtils.TryParseToSubnet(address, out var subnet)) { - return IPAddress.IsLoopback(subnet.BaseAddress) || (_lanSubnets.Any(x => x.Contains(subnet.BaseAddress)) && !_excludedSubnets.Any(x => x.Contains(subnet.BaseAddress))); + return IPAddress.IsLoopback(subnet.Value.BaseAddress) || (_lanSubnets.Any(x => x.Contains(subnet.Value.BaseAddress)) && !_excludedSubnets.Any(x => x.Contains(subnet.Value.BaseAddress))); } if (NetworkUtils.TryParseHost(address, out var addresses, IsIPv4Enabled, IsIPv6Enabled)) diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index 77f8f7071b..6bda12c5b4 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -60,7 +60,7 @@ namespace Jellyfin.Server.Implementations.Security } private async Task GetAuthorizationInfoFromDictionary( - IReadOnlyDictionary? auth, + Dictionary? auth, IHeaderDictionary headers, IQueryCollection queryString) { diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index edae4cfc5e..075f4cb3a1 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -775,7 +775,7 @@ namespace Jellyfin.Server.Implementations.Users return providers; } - private IList GetPasswordResetProviders(User user) + private IPasswordResetProvider[] GetPasswordResetProviders(User user) { var passwordResetProviderId = user.PasswordResetProviderId; var providers = _passwordResetProviders.Where(i => i.IsEnabled).ToArray(); diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 753029f2cd..92c483c0fe 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -30,12 +30,14 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Cors.Infrastructure; +using Microsoft.AspNetCore.HttpOverrides; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; using AuthenticationSchemes = Jellyfin.Api.Constants.AuthenticationSchemes; +using IPNetwork = System.Net.IPNetwork; namespace Jellyfin.Server.Extensions { @@ -277,9 +279,9 @@ namespace Jellyfin.Server.Extensions } else if (NetworkUtils.TryParseToSubnet(allowedProxies[i], out var subnet)) { - if (subnet is not null) + if (subnet.HasValue) { - AddIPAddress(config, options, subnet.BaseAddress, subnet.PrefixLength); + AddIPAddress(config, options, subnet.Value.BaseAddress, subnet.Value.PrefixLength); } } else if (NetworkUtils.TryParseHost(allowedProxies[i], out var addresses, config.EnableIPv4, config.EnableIPv6)) @@ -310,7 +312,7 @@ namespace Jellyfin.Server.Extensions } else { - options.KnownNetworks.Add(new IPNetwork(addr, prefixLength)); + options.KnownNetworks.Add(new Microsoft.AspNetCore.HttpOverrides.IPNetwork(addr, prefixLength)); } } diff --git a/Jellyfin.Server/Migrations/Routines/MigrateRatingLevels.cs b/Jellyfin.Server/Migrations/Routines/MigrateRatingLevels.cs index ac50474010..247e1d8450 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateRatingLevels.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateRatingLevels.cs @@ -78,11 +78,7 @@ namespace Jellyfin.Server.Migrations.Routines } else { - var ratingValue = _localizationManager.GetRatingLevel(ratingString).ToString(); - if (string.IsNullOrEmpty(ratingValue)) - { - ratingValue = "NULL"; - } + var ratingValue = _localizationManager.GetRatingLevel(ratingString)?.ToString(CultureInfo.InvariantCulture) ?? "NULL"; using var statement = connection.PrepareStatement("UPDATE TypedBaseItems SET InheritedParentalRatingValue = @Value WHERE OfficialRating = @Rating;"); statement.TryBind("@Value", ratingValue); diff --git a/MediaBrowser.Common/Net/NetworkUtils.cs b/MediaBrowser.Common/Net/NetworkUtils.cs index 452cb694ed..7ae99336f1 100644 --- a/MediaBrowser.Common/Net/NetworkUtils.cs +++ b/MediaBrowser.Common/Net/NetworkUtils.cs @@ -180,7 +180,7 @@ public static partial class NetworkUtils { if (TryParseToSubnet(values[a], out var innerResult, negated)) { - tmpResult.Add(innerResult); + tmpResult.Add(innerResult.Value); } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 6621ae2842..46fd1ae478 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -20,6 +20,7 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.MediaInfo; using Microsoft.Extensions.Configuration; +using IConfigurationManager = MediaBrowser.Common.Configuration.IConfigurationManager; namespace MediaBrowser.Controller.MediaEncoding { diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index be1e8a1726..020e69eced 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -516,7 +516,7 @@ namespace MediaBrowser.MediaEncoding.Probing private void ProcessPairs(string key, List pairs, MediaInfo info) { - IList peoples = new List(); + List peoples = new List(); if (string.Equals(key, "studio", StringComparison.OrdinalIgnoreCase)) { info.Studios = pairs.Select(p => p.Value) @@ -1182,7 +1182,7 @@ namespace MediaBrowser.MediaEncoding.Probing info.Size = string.IsNullOrEmpty(data.Format.Size) ? null : long.Parse(data.Format.Size, CultureInfo.InvariantCulture); } - private void SetAudioInfoFromTags(MediaInfo audio, IReadOnlyDictionary tags) + private void SetAudioInfoFromTags(MediaInfo audio, Dictionary tags) { var people = new List(); if (tags.TryGetValue("composer", out var composer) && !string.IsNullOrWhiteSpace(composer)) diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 666e787951..252ac1303f 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -835,11 +835,6 @@ namespace MediaBrowser.Model.Dlna playlistItem.SetOption(qualifier, "profile", videoStream.Profile.ToLowerInvariant()); } - if (videoStream is not null && videoStream.Level != 0) - { - playlistItem.SetOption(qualifier, "level", videoStream.Level.ToString() ?? string.Empty); - } - // Prefer matching audio codecs, could do better here var audioCodecs = ContainerProfile.SplitValue(audioCodec); @@ -866,16 +861,16 @@ namespace MediaBrowser.Model.Dlna // Copy matching audio codec options playlistItem.AudioSampleRate = audioStream.SampleRate; - playlistItem.SetOption(qualifier, "audiochannels", audioStream.Channels.ToString() ?? string.Empty); + playlistItem.SetOption(qualifier, "audiochannels", audioStream.Channels?.ToString(CultureInfo.InvariantCulture) ?? string.Empty); if (!string.IsNullOrEmpty(audioStream.Profile)) { playlistItem.SetOption(audioStream.Codec, "profile", audioStream.Profile.ToLowerInvariant()); } - if (audioStream.Level != 0) + if (audioStream.Level.HasValue) { - playlistItem.SetOption(audioStream.Codec, "level", audioStream.Level.ToString() ?? string.Empty); + playlistItem.SetOption(audioStream.Codec, "level", audioStream.Level.Value.ToString(CultureInfo.InvariantCulture)); } } diff --git a/MediaBrowser.Providers/Lyric/LrcLyricParser.cs b/MediaBrowser.Providers/Lyric/LrcLyricParser.cs index 7f1ecd7435..a10ff198b4 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricParser.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricParser.cs @@ -125,7 +125,7 @@ public class LrcLyricParser : ILyricParser /// /// The metadata from the LRC file. /// A lyricMetadata object with mapped property data. - private static LyricMetadata MapMetadataValues(IDictionary metaData) + private static LyricMetadata MapMetadataValues(Dictionary metaData) { LyricMetadata lyricMetadata = new(); diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index dab36625e5..1a5dbd7a55 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -175,7 +175,7 @@ namespace MediaBrowser.Providers.Manager IDynamicImageProvider provider, ImageRefreshOptions refreshOptions, TypeOptions savedOptions, - ICollection downloadedImages, + List downloadedImages, RefreshResult result, CancellationToken cancellationToken) { @@ -263,7 +263,7 @@ namespace MediaBrowser.Providers.Manager ImageRefreshOptions refreshOptions, TypeOptions savedOptions, int backdropLimit, - ICollection downloadedImages, + List downloadedImages, RefreshResult result, CancellationToken cancellationToken) { diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index b4b1895f51..d1c0ddb375 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -82,8 +82,8 @@ namespace MediaBrowser.Providers.MediaInfo { Directory.CreateDirectory(Path.GetDirectoryName(path)); - var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("front", StringComparison.OrdinalIgnoreCase) != -1) ?? - imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1) ?? + var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).Contains("front", StringComparison.OrdinalIgnoreCase)) ?? + imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).Contains("cover", StringComparison.OrdinalIgnoreCase)) ?? imageStreams.FirstOrDefault(); var imageStreamIndex = imageStream?.Index; diff --git a/MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs b/MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs index 909cbb9b9c..f846aa5dec 100644 --- a/MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs +++ b/MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs @@ -183,7 +183,7 @@ namespace MediaBrowser.Providers.MediaInfo files.AddRange(directoryService.GetFilePaths(internalMetadataPath, clearCache, true)); } - if (!files.Any()) + if (files.Count == 0) { return Array.Empty(); } diff --git a/MediaBrowser.Providers/Music/AlbumMetadataService.cs b/MediaBrowser.Providers/Music/AlbumMetadataService.cs index 0ddb2ad67b..e4f34776b9 100644 --- a/MediaBrowser.Providers/Music/AlbumMetadataService.cs +++ b/MediaBrowser.Providers/Music/AlbumMetadataService.cs @@ -148,7 +148,7 @@ namespace MediaBrowser.Providers.Music .ToArray(); var id = item.GetProviderId(provider); - if (ids.Any()) + if (ids.Length != 0) { var firstId = ids[0]; if (!string.IsNullOrEmpty(firstId) diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs index 7f73afc53a..8a516e1ce7 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs @@ -73,7 +73,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb return Enumerable.Empty(); } - private IEnumerable GetImages(AudioDbAlbumProvider.Album item) + private List GetImages(AudioDbAlbumProvider.Album item) { var list = new List(); diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs index 2232dfa0d7..4e7757cd26 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs @@ -78,7 +78,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb return Enumerable.Empty(); } - private IEnumerable GetImages(AudioDbArtistProvider.Artist item) + private List GetImages(AudioDbArtistProvider.Artist item) { var list = new List(); diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs index e01c0f4830..01c07d6332 100644 --- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs +++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs @@ -121,7 +121,7 @@ namespace MediaBrowser.Providers.TV var seasonNumber = virtualSeason.IndexNumber; // If there's a physical season with the same number or no episodes in the season, delete it if ((seasonNumber.HasValue && physicalSeasonNumbers.Contains(seasonNumber.Value)) - || !virtualSeason.GetEpisodes().Any()) + || virtualSeason.GetEpisodes().Count == 0) { Logger.LogInformation("Removing virtual season {SeasonNumber} in series {SeriesName}", virtualSeason.IndexNumber, series.Name); diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index bf66a31458..1399ac307a 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -314,11 +314,11 @@ namespace MediaBrowser.XbmcMetadata.Savers { var codec = stream.Codec; - if ((stream.CodecTag ?? string.Empty).IndexOf("xvid", StringComparison.OrdinalIgnoreCase) != -1) + if ((stream.CodecTag ?? string.Empty).Contains("xvid", StringComparison.OrdinalIgnoreCase)) { codec = "xvid"; } - else if ((stream.CodecTag ?? string.Empty).IndexOf("divx", StringComparison.OrdinalIgnoreCase) != -1) + else if ((stream.CodecTag ?? string.Empty).Contains("divx", StringComparison.OrdinalIgnoreCase)) { codec = "divx"; } diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 870cf253f2..10225e3af8 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -140,6 +140,9 @@ + + + diff --git a/src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs b/src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs index 479e6ffdc8..720d987f13 100644 --- a/src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs +++ b/src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs @@ -11,8 +11,6 @@ namespace Jellyfin.MediaEncoding.Keyframes.FfProbe; /// public static class FfProbeKeyframeExtractor { - private const string DefaultArguments = "-fflags +genpts -v error -skip_frame nokey -show_entries format=duration -show_entries stream=duration -show_entries packet=pts_time,flags -select_streams v -of csv \"{0}\""; - /// /// Extracts the keyframes using the ffprobe executable at the specified path. /// @@ -26,7 +24,10 @@ public static class FfProbeKeyframeExtractor StartInfo = new ProcessStartInfo { FileName = ffProbePath, - Arguments = string.Format(CultureInfo.InvariantCulture, DefaultArguments, filePath), + Arguments = string.Format( + CultureInfo.InvariantCulture, + "-fflags +genpts -v error -skip_frame nokey -show_entries format=duration -show_entries stream=duration -show_entries packet=pts_time,flags -select_streams v -of csv \"{0}\"", + filePath), CreateNoWindow = true, UseShellExecute = false, From 0fd36a5bf1fc87ebbfd5b74585f0c080995c1688 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 14 Nov 2023 19:12:17 +0100 Subject: [PATCH 04/11] Fix warnings in test projects --- .../Controllers/UserControllerTests.cs | 2 +- .../JsonCommaDelimitedArrayTests.cs | 65 +++++++++---------- .../JsonCommaDelimitedIReadOnlyListTests.cs | 43 ++++++------ .../NetworkParseTests.cs | 1 + .../Manager/ItemImageProviderTests.cs | 14 ++-- .../Sorting/AiredEpisodeOrderComparerTests.cs | 11 ++-- .../Sorting/IndexNumberComparerTests.cs | 2 +- .../Sorting/ParentIndexNumberComparerTests.cs | 2 +- .../ParseNetworkTests.cs | 3 +- 9 files changed, 68 insertions(+), 75 deletions(-) diff --git a/tests/Jellyfin.Api.Tests/Controllers/UserControllerTests.cs b/tests/Jellyfin.Api.Tests/Controllers/UserControllerTests.cs index 3f965d0ff0..c7331c7181 100644 --- a/tests/Jellyfin.Api.Tests/Controllers/UserControllerTests.cs +++ b/tests/Jellyfin.Api.Tests/Controllers/UserControllerTests.cs @@ -109,7 +109,7 @@ public class UserControllerTests v.ErrorMessage.Contains("required", StringComparison.CurrentCultureIgnoreCase)); } - private IList Validate(object model) + private List Validate(object model) { var result = new List(); var context = new ValidationContext(model, null, null); diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs index f2ca2ff081..61105b42b2 100644 --- a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs @@ -7,135 +7,128 @@ using Xunit; namespace Jellyfin.Extensions.Tests.Json.Converters { - public static class JsonCommaDelimitedArrayTests + public class JsonCommaDelimitedArrayTests { + private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions() + { + Converters = + { + new JsonStringEnumConverter() + } + }; + [Fact] - public static void Deserialize_String_Null_Success() + public void Deserialize_String_Null_Success() { - var options = new JsonSerializerOptions(); - var value = JsonSerializer.Deserialize>(@"{ ""Value"": null }", options); + var value = JsonSerializer.Deserialize>(@"{ ""Value"": null }", _jsonOptions); Assert.Null(value?.Value); } [Fact] - public static void Deserialize_Empty_Success() + public void Deserialize_Empty_Success() { var desiredValue = new GenericBodyArrayModel { Value = Array.Empty() }; - var options = new JsonSerializerOptions(); - var value = JsonSerializer.Deserialize>(@"{ ""Value"": """" }", options); + var value = JsonSerializer.Deserialize>(@"{ ""Value"": """" }", _jsonOptions); Assert.Equal(desiredValue.Value, value?.Value); } [Fact] - public static void Deserialize_String_Valid_Success() + public void Deserialize_String_Valid_Success() { var desiredValue = new GenericBodyArrayModel { Value = new[] { "a", "b", "c" } }; - var options = new JsonSerializerOptions(); - var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""a,b,c"" }", options); + var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""a,b,c"" }", _jsonOptions); Assert.Equal(desiredValue.Value, value?.Value); } [Fact] - public static void Deserialize_String_Space_Valid_Success() + public void Deserialize_String_Space_Valid_Success() { var desiredValue = new GenericBodyArrayModel { Value = new[] { "a", "b", "c" } }; - var options = new JsonSerializerOptions(); - var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""a, b, c"" }", options); + var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""a, b, c"" }", _jsonOptions); Assert.Equal(desiredValue.Value, value?.Value); } [Fact] - public static void Deserialize_GenericCommandType_Valid_Success() + public void Deserialize_GenericCommandType_Valid_Success() { var desiredValue = new GenericBodyArrayModel { Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } }; - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); - var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""MoveUp,MoveDown"" }", options); + var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""MoveUp,MoveDown"" }", _jsonOptions); Assert.Equal(desiredValue.Value, value?.Value); } [Fact] - public static void Deserialize_GenericCommandType_EmptyEntry_Success() + public void Deserialize_GenericCommandType_EmptyEntry_Success() { var desiredValue = new GenericBodyArrayModel { Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } }; - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); - var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""MoveUp,,MoveDown"" }", options); + var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""MoveUp,,MoveDown"" }", _jsonOptions); Assert.Equal(desiredValue.Value, value?.Value); } [Fact] - public static void Deserialize_GenericCommandType_Invalid_Success() + public void Deserialize_GenericCommandType_Invalid_Success() { var desiredValue = new GenericBodyArrayModel { Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } }; - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); - var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""MoveUp,TotallyNotAVallidCommand,MoveDown"" }", options); + var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""MoveUp,TotallyNotAVallidCommand,MoveDown"" }", _jsonOptions); Assert.Equal(desiredValue.Value, value?.Value); } [Fact] - public static void Deserialize_GenericCommandType_Space_Valid_Success() + public void Deserialize_GenericCommandType_Space_Valid_Success() { var desiredValue = new GenericBodyArrayModel { Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } }; - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); - var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""MoveUp, MoveDown"" }", options); + var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""MoveUp, MoveDown"" }", _jsonOptions); Assert.Equal(desiredValue.Value, value?.Value); } [Fact] - public static void Deserialize_String_Array_Valid_Success() + public void Deserialize_String_Array_Valid_Success() { var desiredValue = new GenericBodyArrayModel { Value = new[] { "a", "b", "c" } }; - var options = new JsonSerializerOptions(); - var value = JsonSerializer.Deserialize>(@"{ ""Value"": [""a"",""b"",""c""] }", options); + var value = JsonSerializer.Deserialize>(@"{ ""Value"": [""a"",""b"",""c""] }", _jsonOptions); Assert.Equal(desiredValue.Value, value?.Value); } [Fact] - public static void Deserialize_GenericCommandType_Array_Valid_Success() + public void Deserialize_GenericCommandType_Array_Valid_Success() { var desiredValue = new GenericBodyArrayModel { Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } }; - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); - var value = JsonSerializer.Deserialize>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", options); + var value = JsonSerializer.Deserialize>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", _jsonOptions); Assert.Equal(desiredValue.Value, value?.Value); } } diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedIReadOnlyListTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedIReadOnlyListTests.cs index 92886dcd28..9b977b9a5d 100644 --- a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedIReadOnlyListTests.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedIReadOnlyListTests.cs @@ -6,86 +6,85 @@ using Xunit; namespace Jellyfin.Extensions.Tests.Json.Converters { - public static class JsonCommaDelimitedIReadOnlyListTests + public class JsonCommaDelimitedIReadOnlyListTests { + private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions() + { + Converters = + { + new JsonStringEnumConverter() + } + }; + [Fact] - public static void Deserialize_String_Valid_Success() + public void Deserialize_String_Valid_Success() { var desiredValue = new GenericBodyIReadOnlyListModel { Value = new[] { "a", "b", "c" } }; - var options = new JsonSerializerOptions(); - var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""a,b,c"" }", options); + var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""a,b,c"" }", _jsonOptions); Assert.Equal(desiredValue.Value, value?.Value); } [Fact] - public static void Deserialize_String_Space_Valid_Success() + public void Deserialize_String_Space_Valid_Success() { var desiredValue = new GenericBodyIReadOnlyListModel { Value = new[] { "a", "b", "c" } }; - var options = new JsonSerializerOptions(); - var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""a, b, c"" }", options); + var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""a, b, c"" }", _jsonOptions); Assert.Equal(desiredValue.Value, value?.Value); } [Fact] - public static void Deserialize_GenericCommandType_Valid_Success() + public void Deserialize_GenericCommandType_Valid_Success() { var desiredValue = new GenericBodyIReadOnlyListModel { Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } }; - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); - var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""MoveUp,MoveDown"" }", options); + var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""MoveUp,MoveDown"" }", _jsonOptions); Assert.Equal(desiredValue.Value, value?.Value); } [Fact] - public static void Deserialize_GenericCommandType_Space_Valid_Success() + public void Deserialize_GenericCommandType_Space_Valid_Success() { var desiredValue = new GenericBodyIReadOnlyListModel { Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } }; - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); - var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""MoveUp, MoveDown"" }", options); + var value = JsonSerializer.Deserialize>(@"{ ""Value"": ""MoveUp, MoveDown"" }", _jsonOptions); Assert.Equal(desiredValue.Value, value?.Value); } [Fact] - public static void Deserialize_String_Array_Valid_Success() + public void Deserialize_String_Array_Valid_Success() { var desiredValue = new GenericBodyIReadOnlyListModel { Value = new[] { "a", "b", "c" } }; - var options = new JsonSerializerOptions(); - var value = JsonSerializer.Deserialize>(@"{ ""Value"": [""a"",""b"",""c""] }", options); + var value = JsonSerializer.Deserialize>(@"{ ""Value"": [""a"",""b"",""c""] }", _jsonOptions); Assert.Equal(desiredValue.Value, value?.Value); } [Fact] - public static void Deserialize_GenericCommandType_Array_Valid_Success() + public void Deserialize_GenericCommandType_Array_Valid_Success() { var desiredValue = new GenericBodyIReadOnlyListModel { Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } }; - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); - var value = JsonSerializer.Deserialize>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", options); + var value = JsonSerializer.Deserialize>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", _jsonOptions); Assert.Equal(desiredValue.Value, value?.Value); } } diff --git a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs index 93514a5017..19aaa5ef8f 100644 --- a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs +++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; +using IConfigurationManager = MediaBrowser.Common.Configuration.IConfigurationManager; namespace Jellyfin.Networking.Tests { diff --git a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs index d5ab6ab4be..be5a401b1a 100644 --- a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs @@ -27,7 +27,7 @@ namespace Jellyfin.Providers.Tests.Manager { public partial class ItemImageProviderTests { - private const string TestDataImagePath = "Test Data/Images/blank{0}.jpg"; + private static readonly CompositeFormat _testDataImagePath = CompositeFormat.Parse("Test Data/Images/blank{0}.jpg"); [GeneratedRegex("[0-9]+")] private static partial Regex NumbersRegex(); @@ -275,7 +275,7 @@ namespace Jellyfin.Providers.Tests.Manager { HasImage = true, Format = ImageFormat.Jpg, - Path = responseHasPath ? string.Format(CultureInfo.InvariantCulture, TestDataImagePath, 0) : null, + Path = responseHasPath ? string.Format(CultureInfo.InvariantCulture, _testDataImagePath, 0) : null, Protocol = protocol }; @@ -563,21 +563,21 @@ namespace Jellyfin.Providers.Tests.Manager mockFileSystem.Setup(fs => fs.GetFilePaths(It.IsAny(), It.IsAny())) .Returns(new[] { - string.Format(CultureInfo.InvariantCulture, TestDataImagePath, 0), - string.Format(CultureInfo.InvariantCulture, TestDataImagePath, 1) + string.Format(CultureInfo.InvariantCulture, _testDataImagePath, 0), + string.Format(CultureInfo.InvariantCulture, _testDataImagePath, 1) }); return new ItemImageProvider(new NullLogger(), providerManager, mockFileSystem.Object); } - private static BaseItem GetItemWithImages(ImageType type, int count, bool validPaths) + private static Video GetItemWithImages(ImageType type, int count, bool validPaths) { // Has to exist for querying DateModified time on file, results stored but not checked so not populating BaseItem.FileSystem ??= Mock.Of(); var item = new Video(); - var path = validPaths ? TestDataImagePath : "invalid path {0}"; + var path = validPaths ? _testDataImagePath.Format : "invalid path {0}"; for (int i = 0; i < count; i++) { item.SetImagePath(type, i, new FileSystemMetadata @@ -604,7 +604,7 @@ namespace Jellyfin.Providers.Tests.Manager /// private static LocalImageInfo[] GetImages(ImageType type, int count, bool validPaths) { - var path = validPaths ? TestDataImagePath : "invalid path {0}"; + var path = validPaths ? _testDataImagePath.Format : "invalid path {0}"; var images = new LocalImageInfo[count]; for (int i = 0; i < count; i++) { diff --git a/tests/Jellyfin.Server.Implementations.Tests/Sorting/AiredEpisodeOrderComparerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Sorting/AiredEpisodeOrderComparerTests.cs index 1dd49b2cfa..ad85bdb6e1 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Sorting/AiredEpisodeOrderComparerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Sorting/AiredEpisodeOrderComparerTests.cs @@ -9,22 +9,21 @@ namespace Jellyfin.Server.Implementations.Tests.Sorting { public class AiredEpisodeOrderComparerTests { + private readonly AiredEpisodeOrderComparer _cmp = new AiredEpisodeOrderComparer(); + [Theory] [ClassData(typeof(EpisodeBadData))] public void Compare_GivenNull_ThrowsArgumentNullException(BaseItem? x, BaseItem? y) { - var cmp = new AiredEpisodeOrderComparer(); - Assert.Throws(() => cmp.Compare(x, y)); + Assert.Throws(() => _cmp.Compare(x, y)); } [Theory] [ClassData(typeof(EpisodeTestData))] public void AiredEpisodeOrderCompareTest(BaseItem x, BaseItem y, int expected) { - var cmp = new AiredEpisodeOrderComparer(); - - Assert.Equal(expected, cmp.Compare(x, y)); - Assert.Equal(-expected, cmp.Compare(y, x)); + Assert.Equal(expected, _cmp.Compare(x, y)); + Assert.Equal(-expected, _cmp.Compare(y, x)); } private sealed class EpisodeBadData : TheoryData diff --git a/tests/Jellyfin.Server.Implementations.Tests/Sorting/IndexNumberComparerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Sorting/IndexNumberComparerTests.cs index 18588bd67a..52f71ef4a3 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Sorting/IndexNumberComparerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Sorting/IndexNumberComparerTests.cs @@ -9,7 +9,7 @@ namespace Jellyfin.Server.Implementations.Tests.Sorting; public class IndexNumberComparerTests { - private readonly IBaseItemComparer _cmp = new IndexNumberComparer(); + private readonly IndexNumberComparer _cmp = new IndexNumberComparer(); public static TheoryData Compare_GivenNull_ThrowsArgumentNullException_TestData() => new() diff --git a/tests/Jellyfin.Server.Implementations.Tests/Sorting/ParentIndexNumberComparerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Sorting/ParentIndexNumberComparerTests.cs index 261092e019..bedd187ebb 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Sorting/ParentIndexNumberComparerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Sorting/ParentIndexNumberComparerTests.cs @@ -9,7 +9,7 @@ namespace Jellyfin.Server.Implementations.Tests.Sorting; public class ParentIndexNumberComparerTests { - private readonly IBaseItemComparer _cmp = new ParentIndexNumberComparer(); + private readonly ParentIndexNumberComparer _cmp = new ParentIndexNumberComparer(); public static TheoryData Compare_GivenNull_ThrowsArgumentNullException_TestData() => new() diff --git a/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs b/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs index 8d464d4e75..44d9ce13c0 100644 --- a/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs +++ b/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; +using IConfigurationManager = MediaBrowser.Common.Configuration.IConfigurationManager; namespace Jellyfin.Server.Tests { @@ -98,7 +99,7 @@ namespace Jellyfin.Server.Tests Assert.Equal(knownNetworks.Length, options.KnownNetworks.Count); foreach (var item in knownNetworks) { - Assert.NotNull(options.KnownNetworks.FirstOrDefault(x => x.BaseAddress.Equals(item.BaseAddress) && x.PrefixLength == item.PrefixLength)); + Assert.NotNull(options.KnownNetworks.FirstOrDefault(x => x.Prefix.Equals(item.BaseAddress) && x.PrefixLength == item.PrefixLength)); } } From 635d67d458e02df53a1b08998ccd3cff16e76ac3 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 14 Nov 2023 20:21:34 +0100 Subject: [PATCH 05/11] Revert "Use System.Net.IPNetwork" This reverts commit 117d05d288da1d412159a29c0cb8d5c8259e48ae. --- Emby.Dlna/Main/DlnaEntryPoint.cs | 363 ------------------ .../Controllers/EnvironmentController.cs | 2 +- .../Controllers/HlsSegmentController.cs | 2 +- Jellyfin.Api/Controllers/ImageController.cs | 2 +- .../Controllers/MusicGenresController.cs | 2 +- Jellyfin.Api/Extensions/DtoExtensions.cs | 22 +- Jellyfin.Api/Helpers/HlsHelpers.cs | 2 +- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 2 +- .../Models/StreamingDtos/StreamState.cs | 10 +- Jellyfin.Networking/Manager/NetworkManager.cs | 20 +- .../Users/UserManager.cs | 2 +- .../ApiServiceCollectionExtensions.cs | 4 +- Jellyfin.Server/Program.cs | 2 +- Jellyfin.Server/Startup.cs | 2 +- MediaBrowser.Common/Net/NetworkConstants.cs | 1 + MediaBrowser.Common/Net/NetworkUtils.cs | 7 +- .../Encoder/EncoderValidator.cs | 12 +- .../Encoder/EncodingUtils.cs | 2 +- .../Probing/ProbeResultNormalizer.cs | 6 +- .../Subtitles/SubtitleEditParser.cs | 2 +- .../Subtitles/SubtitleEncoder.cs | 2 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 1 + MediaBrowser.Model/Net/IPData.cs | 5 +- .../ParseNetworkTests.cs | 3 +- 24 files changed, 60 insertions(+), 418 deletions(-) delete mode 100644 Emby.Dlna/Main/DlnaEntryPoint.cs diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs deleted file mode 100644 index dbc47d9816..0000000000 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ /dev/null @@ -1,363 +0,0 @@ -#nullable disable - -#pragma warning disable CS1591 - -using System; -using System.Globalization; -using System.Linq; -using System.Net.Http; -using System.Net.Sockets; -using System.Threading.Tasks; -using Emby.Dlna.PlayTo; -using Emby.Dlna.Ssdp; -using Jellyfin.Networking.Configuration; -using Jellyfin.Networking.Extensions; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Dlna; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Globalization; -using Microsoft.Extensions.Logging; -using Rssdp; -using Rssdp.Infrastructure; - -namespace Emby.Dlna.Main -{ - public sealed class DlnaEntryPoint : IServerEntryPoint, IRunBeforeStartup - { - private readonly IServerConfigurationManager _config; - private readonly ILogger _logger; - private readonly IServerApplicationHost _appHost; - private readonly ISessionManager _sessionManager; - private readonly IHttpClientFactory _httpClientFactory; - private readonly ILibraryManager _libraryManager; - private readonly IUserManager _userManager; - private readonly IDlnaManager _dlnaManager; - private readonly IImageProcessor _imageProcessor; - private readonly IUserDataManager _userDataManager; - private readonly ILocalizationManager _localization; - private readonly IMediaSourceManager _mediaSourceManager; - private readonly IMediaEncoder _mediaEncoder; - private readonly IDeviceDiscovery _deviceDiscovery; - private readonly ISsdpCommunicationsServer _communicationsServer; - private readonly INetworkManager _networkManager; - private readonly object _syncLock = new(); - private readonly bool _disabled; - - private PlayToManager _manager; - private SsdpDevicePublisher _publisher; - - private bool _disposed; - - public DlnaEntryPoint( - IServerConfigurationManager config, - ILoggerFactory loggerFactory, - IServerApplicationHost appHost, - ISessionManager sessionManager, - IHttpClientFactory httpClientFactory, - ILibraryManager libraryManager, - IUserManager userManager, - IDlnaManager dlnaManager, - IImageProcessor imageProcessor, - IUserDataManager userDataManager, - ILocalizationManager localizationManager, - IMediaSourceManager mediaSourceManager, - IDeviceDiscovery deviceDiscovery, - IMediaEncoder mediaEncoder, - ISsdpCommunicationsServer communicationsServer, - INetworkManager networkManager) - { - _config = config; - _appHost = appHost; - _sessionManager = sessionManager; - _httpClientFactory = httpClientFactory; - _libraryManager = libraryManager; - _userManager = userManager; - _dlnaManager = dlnaManager; - _imageProcessor = imageProcessor; - _userDataManager = userDataManager; - _localization = localizationManager; - _mediaSourceManager = mediaSourceManager; - _deviceDiscovery = deviceDiscovery; - _mediaEncoder = mediaEncoder; - _communicationsServer = communicationsServer; - _networkManager = networkManager; - _logger = loggerFactory.CreateLogger(); - - var netConfig = config.GetConfiguration(NetworkConfigurationStore.StoreKey); - _disabled = appHost.ListenWithHttps && netConfig.RequireHttps; - - if (_disabled && _config.GetDlnaConfiguration().EnableServer) - { - _logger.LogError("The DLNA specification does not support HTTPS."); - } - } - - public async Task RunAsync() - { - await ((DlnaManager)_dlnaManager).InitProfilesAsync().ConfigureAwait(false); - - if (_disabled) - { - // No use starting as dlna won't work, as we're running purely on HTTPS. - return; - } - - ReloadComponents(); - - _config.NamedConfigurationUpdated += OnNamedConfigurationUpdated; - } - - private void OnNamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) - { - if (string.Equals(e.Key, "dlna", StringComparison.OrdinalIgnoreCase)) - { - ReloadComponents(); - } - } - - private void ReloadComponents() - { - var options = _config.GetDlnaConfiguration(); - StartDeviceDiscovery(); - - if (options.EnableServer) - { - StartDevicePublisher(options); - } - else - { - DisposeDevicePublisher(); - } - - if (options.EnablePlayTo) - { - StartPlayToManager(); - } - else - { - DisposePlayToManager(); - } - } - - private void StartDeviceDiscovery() - { - try - { - ((DeviceDiscovery)_deviceDiscovery).Start(_communicationsServer); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error starting device discovery"); - } - } - - public void StartDevicePublisher(Configuration.DlnaOptions options) - { - if (_publisher is not null) - { - return; - } - - try - { - _publisher = new SsdpDevicePublisher( - _communicationsServer, - Environment.OSVersion.Platform.ToString(), - // Can not use VersionString here since that includes OS and version - Environment.OSVersion.Version.ToString(), - _config.GetDlnaConfiguration().SendOnlyMatchedHost) - { - LogFunction = (msg) => _logger.LogDebug("{Msg}", msg), - SupportPnpRootDevice = false - }; - - RegisterServerEndpoints(); - - if (options.BlastAliveMessages) - { - _publisher.StartSendingAliveNotifications(TimeSpan.FromSeconds(options.BlastAliveMessageIntervalSeconds)); - } - } - catch (Exception ex) - { - _logger.LogError(ex, "Error registering endpoint"); - } - } - - private void RegisterServerEndpoints() - { - var udn = CreateUuid(_appHost.SystemId); - var descriptorUri = "/dlna/" + udn + "/description.xml"; - - // Only get bind addresses in LAN - // IPv6 is currently unsupported - var validInterfaces = _networkManager.GetInternalBindAddresses() - .Where(x => x.Address is not null) - .Where(x => x.AddressFamily != AddressFamily.InterNetworkV6) - .ToList(); - - if (validInterfaces.Count == 0) - { - // No interfaces returned, fall back to loopback - validInterfaces = _networkManager.GetLoopbacks().ToList(); - } - - foreach (var intf in validInterfaces) - { - var fullService = "urn:schemas-upnp-org:device:MediaServer:1"; - - _logger.LogInformation("Registering publisher for {ResourceName} on {DeviceAddress}", fullService, intf.Address); - - var uri = new UriBuilder(_appHost.GetApiUrlForLocalAccess(intf.Address, false) + descriptorUri); - - var device = new SsdpRootDevice - { - CacheLifetime = TimeSpan.FromSeconds(1800), // How long SSDP clients can cache this info. - Location = uri.Uri, // Must point to the URL that serves your devices UPnP description document. - Address = intf.Address, - PrefixLength = NetworkExtensions.MaskToCidr(intf.Subnet.BaseAddress), - FriendlyName = "Jellyfin", - Manufacturer = "Jellyfin", - ModelName = "Jellyfin Server", - Uuid = udn - // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc. - }; - - SetProperties(device, fullService); - _publisher.AddDevice(device); - - var embeddedDevices = new[] - { - "urn:schemas-upnp-org:service:ContentDirectory:1", - "urn:schemas-upnp-org:service:ConnectionManager:1", - // "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1" - }; - - foreach (var subDevice in embeddedDevices) - { - var embeddedDevice = new SsdpEmbeddedDevice - { - FriendlyName = device.FriendlyName, - Manufacturer = device.Manufacturer, - ModelName = device.ModelName, - Uuid = udn - // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc. - }; - - SetProperties(embeddedDevice, subDevice); - device.AddDevice(embeddedDevice); - } - } - } - - private static string CreateUuid(string text) - { - if (!Guid.TryParse(text, out var guid)) - { - guid = text.GetMD5(); - } - - return guid.ToString("D", CultureInfo.InvariantCulture); - } - - private static void SetProperties(SsdpDevice device, string fullDeviceType) - { - var serviceParts = fullDeviceType - .Replace("urn:", string.Empty, StringComparison.OrdinalIgnoreCase) - .Replace(":1", string.Empty, StringComparison.OrdinalIgnoreCase) - .Split(':'); - - device.DeviceTypeNamespace = serviceParts[0].Replace('.', '-'); - device.DeviceClass = serviceParts[1]; - device.DeviceType = serviceParts[2]; - } - - private void StartPlayToManager() - { - lock (_syncLock) - { - if (_manager is not null) - { - return; - } - - try - { - _manager = new PlayToManager( - _logger, - _sessionManager, - _libraryManager, - _userManager, - _dlnaManager, - _appHost, - _imageProcessor, - _deviceDiscovery, - _httpClientFactory, - _userDataManager, - _localization, - _mediaSourceManager, - _mediaEncoder); - - _manager.Start(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error starting PlayTo manager"); - } - } - } - - private void DisposePlayToManager() - { - lock (_syncLock) - { - if (_manager is not null) - { - try - { - _logger.LogInformation("Disposing PlayToManager"); - _manager.Dispose(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error disposing PlayTo manager"); - } - - _manager = null; - } - } - } - - public void DisposeDevicePublisher() - { - if (_publisher is not null) - { - _logger.LogInformation("Disposing SsdpDevicePublisher"); - _publisher.Dispose(); - _publisher = null; - } - } - - /// - public void Dispose() - { - if (_disposed) - { - return; - } - - DisposeDevicePublisher(); - DisposePlayToManager(); - _disposed = true; - } - } -} diff --git a/Jellyfin.Api/Controllers/EnvironmentController.cs b/Jellyfin.Api/Controllers/EnvironmentController.cs index e0713cf054..284a97621d 100644 --- a/Jellyfin.Api/Controllers/EnvironmentController.cs +++ b/Jellyfin.Api/Controllers/EnvironmentController.cs @@ -169,7 +169,7 @@ public class EnvironmentController : BaseJellyfinApiController // Check if unc share var index = path.LastIndexOf(UncSeparator); - if (index != -1 && path.IndexOf(UncSeparator, StringComparison.OrdinalIgnoreCase) == 0) + if (index != -1 && path[0] == UncSeparator) { parent = path.Substring(0, index); diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index 6eedfd8c7f..392d9955fb 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -160,7 +160,7 @@ public class HlsSegmentController : BaseJellyfinApiController var pathExtension = Path.GetExtension(path); if ((string.Equals(pathExtension, segmentContainer, StringComparison.OrdinalIgnoreCase) || string.Equals(pathExtension, ".m3u8", StringComparison.OrdinalIgnoreCase)) - && path.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1) + && path.Contains(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase)) { playlistPath = path; break; diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 7d1a54eced..c031ce338d 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -80,7 +80,7 @@ public class ImageController : BaseJellyfinApiController _appPaths = appPaths; } - private static Stream GetFromBase64Stream(Stream inputStream) + private static CryptoStream GetFromBase64Stream(Stream inputStream) => new CryptoStream(inputStream, new FromBase64Transform(), CryptoStreamMode.Read); /// diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs index 94c8993575..69b9042646 100644 --- a/Jellyfin.Api/Controllers/MusicGenresController.cs +++ b/Jellyfin.Api/Controllers/MusicGenresController.cs @@ -150,7 +150,7 @@ public class MusicGenresController : BaseJellyfinApiController MusicGenre? item; - if (genreName.IndexOf(BaseItem.SlugChar, StringComparison.OrdinalIgnoreCase) != -1) + if (genreName.Contains(BaseItem.SlugChar, StringComparison.OrdinalIgnoreCase)) { item = GetItemFromSlugName(_libraryManager, genreName, dtoOptions, BaseItemKind.MusicGenre); } diff --git a/Jellyfin.Api/Extensions/DtoExtensions.cs b/Jellyfin.Api/Extensions/DtoExtensions.cs index 2d7a56d913..7d9823c25c 100644 --- a/Jellyfin.Api/Extensions/DtoExtensions.cs +++ b/Jellyfin.Api/Extensions/DtoExtensions.cs @@ -38,10 +38,10 @@ public static class DtoExtensions if (!dtoOptions.ContainsField(ItemFields.RecursiveItemCount)) { - if (client.IndexOf("kodi", StringComparison.OrdinalIgnoreCase) != -1 || - client.IndexOf("wmc", StringComparison.OrdinalIgnoreCase) != -1 || - client.IndexOf("media center", StringComparison.OrdinalIgnoreCase) != -1 || - client.IndexOf("classic", StringComparison.OrdinalIgnoreCase) != -1) + if (client.Contains("kodi", StringComparison.OrdinalIgnoreCase) || + client.Contains("wmc", StringComparison.OrdinalIgnoreCase) || + client.Contains("media center", StringComparison.OrdinalIgnoreCase) || + client.Contains("classic", StringComparison.OrdinalIgnoreCase)) { int oldLen = dtoOptions.Fields.Count; var arr = new ItemFields[oldLen + 1]; @@ -53,13 +53,13 @@ public static class DtoExtensions if (!dtoOptions.ContainsField(ItemFields.ChildCount)) { - if (client.IndexOf("kodi", StringComparison.OrdinalIgnoreCase) != -1 || - client.IndexOf("wmc", StringComparison.OrdinalIgnoreCase) != -1 || - client.IndexOf("media center", StringComparison.OrdinalIgnoreCase) != -1 || - client.IndexOf("classic", StringComparison.OrdinalIgnoreCase) != -1 || - client.IndexOf("roku", StringComparison.OrdinalIgnoreCase) != -1 || - client.IndexOf("samsung", StringComparison.OrdinalIgnoreCase) != -1 || - client.IndexOf("androidtv", StringComparison.OrdinalIgnoreCase) != -1) + if (client.Contains("kodi", StringComparison.OrdinalIgnoreCase) || + client.Contains("wmc", StringComparison.OrdinalIgnoreCase) || + client.Contains("media center", StringComparison.OrdinalIgnoreCase) || + client.Contains("classic", StringComparison.OrdinalIgnoreCase) || + client.Contains("roku", StringComparison.OrdinalIgnoreCase) || + client.Contains("samsung", StringComparison.OrdinalIgnoreCase) || + client.Contains("androidtv", StringComparison.OrdinalIgnoreCase)) { int oldLen = dtoOptions.Fields.Count; var arr = new ItemFields[oldLen + 1]; diff --git a/Jellyfin.Api/Helpers/HlsHelpers.cs b/Jellyfin.Api/Helpers/HlsHelpers.cs index 2155e305da..e2d3bfb193 100644 --- a/Jellyfin.Api/Helpers/HlsHelpers.cs +++ b/Jellyfin.Api/Helpers/HlsHelpers.cs @@ -53,7 +53,7 @@ public static class HlsHelpers break; } - if (line.IndexOf("#EXTINF:", StringComparison.OrdinalIgnoreCase) != -1) + if (line.Contains("#EXTINF:", StringComparison.OrdinalIgnoreCase)) { count++; if (count >= segmentCount) diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 5b407e4a95..77d3edbd65 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -405,7 +405,7 @@ public class TranscodingJobHelper : IDisposable var name = Path.GetFileNameWithoutExtension(outputFilePath); var filesToDelete = _fileSystem.GetFilePaths(directory) - .Where(f => f.IndexOf(name, StringComparison.OrdinalIgnoreCase) != -1); + .Where(f => f.Contains(name, StringComparison.OrdinalIgnoreCase)); List? exs = null; foreach (var file in filesToDelete) diff --git a/Jellyfin.Api/Models/StreamingDtos/StreamState.cs b/Jellyfin.Api/Models/StreamingDtos/StreamState.cs index b75272d3f6..f249f3bc6c 100644 --- a/Jellyfin.Api/Models/StreamingDtos/StreamState.cs +++ b/Jellyfin.Api/Models/StreamingDtos/StreamState.cs @@ -86,11 +86,11 @@ public class StreamState : EncodingJobInfo, IDisposable { var userAgent = UserAgent ?? string.Empty; - if (userAgent.IndexOf("AppleTV", StringComparison.OrdinalIgnoreCase) != -1 - || userAgent.IndexOf("cfnetwork", StringComparison.OrdinalIgnoreCase) != -1 - || userAgent.IndexOf("ipad", StringComparison.OrdinalIgnoreCase) != -1 - || userAgent.IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1 - || userAgent.IndexOf("ipod", StringComparison.OrdinalIgnoreCase) != -1) + if (userAgent.Contains("AppleTV", StringComparison.OrdinalIgnoreCase) + || userAgent.Contains("cfnetwork", StringComparison.OrdinalIgnoreCase) + || userAgent.Contains("ipad", StringComparison.OrdinalIgnoreCase) + || userAgent.Contains("iphone", StringComparison.OrdinalIgnoreCase) + || userAgent.Contains("ipod", StringComparison.OrdinalIgnoreCase)) { return 6; } diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index dbf7127a68..749e0abbbe 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -11,10 +11,12 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Net; using MediaBrowser.Model.Net; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.HttpOverrides; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using static MediaBrowser.Controller.Extensions.ConfigurationExtensions; using IConfigurationManager = MediaBrowser.Common.Configuration.IConfigurationManager; +using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork; namespace Jellyfin.Networking.Manager { @@ -530,7 +532,7 @@ namespace Jellyfin.Networking.Manager { foreach (var lan in _lanSubnets) { - var lanPrefix = lan.BaseAddress; + var lanPrefix = lan.Prefix; publishedServerUrls.Add( new PublishedServerUriOverride( new IPData(lanPrefix, new IPNetwork(lanPrefix, lan.PrefixLength)), @@ -541,7 +543,7 @@ namespace Jellyfin.Networking.Manager } else if (NetworkUtils.TryParseToSubnet(identifier, out var result) && result is not null) { - var data = new IPData(result.Value.BaseAddress, result); + var data = new IPData(result.Prefix, result); publishedServerUrls.Add( new PublishedServerUriOverride( data, @@ -607,11 +609,11 @@ namespace Jellyfin.Networking.Manager var parts = details.Split(','); if (NetworkUtils.TryParseToSubnet(parts[0], out var subnet)) { - var address = subnet.Value.BaseAddress; + var address = subnet.Prefix; var index = int.Parse(parts[1], CultureInfo.InvariantCulture); if (address.AddressFamily == AddressFamily.InterNetwork || address.AddressFamily == AddressFamily.InterNetworkV6) { - var data = new IPData(address, subnet.Value, parts[2]) + var data = new IPData(address, subnet, parts[2]) { Index = index }; @@ -881,7 +883,7 @@ namespace Jellyfin.Networking.Manager { if (NetworkUtils.TryParseToSubnet(address, out var subnet)) { - return IPAddress.IsLoopback(subnet.Value.BaseAddress) || (_lanSubnets.Any(x => x.Contains(subnet.Value.BaseAddress)) && !_excludedSubnets.Any(x => x.Contains(subnet.Value.BaseAddress))); + return IPAddress.IsLoopback(subnet.Prefix) || (_lanSubnets.Any(x => x.Contains(subnet.Prefix)) && !_excludedSubnets.Any(x => x.Contains(subnet.Prefix))); } if (NetworkUtils.TryParseHost(address, out var addresses, IsIPv4Enabled, IsIPv6Enabled)) @@ -1112,12 +1114,12 @@ namespace Jellyfin.Networking.Manager var logLevel = debug ? LogLevel.Debug : LogLevel.Information; if (_logger.IsEnabled(logLevel)) { - _logger.Log(logLevel, "Defined LAN addresses: {0}", _lanSubnets.Select(s => s.BaseAddress + "/" + s.PrefixLength)); - _logger.Log(logLevel, "Defined LAN exclusions: {0}", _excludedSubnets.Select(s => s.BaseAddress + "/" + s.PrefixLength)); - _logger.Log(logLevel, "Using LAN addresses: {0}", _lanSubnets.Where(s => !_excludedSubnets.Contains(s)).Select(s => s.BaseAddress + "/" + s.PrefixLength)); + _logger.Log(logLevel, "Defined LAN addresses: {0}", _lanSubnets.Select(s => s.Prefix + "/" + s.PrefixLength)); + _logger.Log(logLevel, "Defined LAN exclusions: {0}", _excludedSubnets.Select(s => s.Prefix + "/" + s.PrefixLength)); + _logger.Log(logLevel, "Using LAN addresses: {0}", _lanSubnets.Where(s => !_excludedSubnets.Contains(s)).Select(s => s.Prefix + "/" + s.PrefixLength)); _logger.Log(logLevel, "Using bind addresses: {0}", _interfaces.OrderByDescending(x => x.AddressFamily == AddressFamily.InterNetwork).Select(x => x.Address)); _logger.Log(logLevel, "Remote IP filter is {0}", config.IsRemoteIPFilterBlacklist ? "Blocklist" : "Allowlist"); - _logger.Log(logLevel, "Filter list: {0}", _remoteAddressFilter.Select(s => s.BaseAddress + "/" + s.PrefixLength)); + _logger.Log(logLevel, "Filter list: {0}", _remoteAddressFilter.Select(s => s.Prefix + "/" + s.PrefixLength)); } } } diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 075f4cb3a1..990b9a5bd4 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -748,7 +748,7 @@ namespace Jellyfin.Server.Implementations.Users return GetPasswordResetProviders(user)[0]; } - private IList GetAuthenticationProviders(User? user) + private List GetAuthenticationProviders(User? user) { var authenticationProviderId = user?.AuthenticationProviderId; diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 92c483c0fe..46df173bfb 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -279,9 +279,9 @@ namespace Jellyfin.Server.Extensions } else if (NetworkUtils.TryParseToSubnet(allowedProxies[i], out var subnet)) { - if (subnet.HasValue) + if (subnet is not null) { - AddIPAddress(config, options, subnet.Value.BaseAddress, subnet.Value.PrefixLength); + AddIPAddress(config, options, subnet.Prefix, subnet.PrefixLength); } } else if (NetworkUtils.TryParseHost(allowedProxies[i], out var addresses, config.EnableIPv4, config.EnableIPv6)) diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index f9259d0d92..c70ef17197 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -40,7 +40,7 @@ namespace Jellyfin.Server /// public const string LoggingConfigFileSystem = "logging.json"; - private static readonly ILoggerFactory _loggerFactory = new SerilogLoggerFactory(); + private static readonly SerilogLoggerFactory _loggerFactory = new SerilogLoggerFactory(); private static long _startTimestamp; private static ILogger _logger = NullLogger.Instance; private static bool _restartOnShutdown; diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs index 18d13c0563..49f5bf232c 100644 --- a/Jellyfin.Server/Startup.cs +++ b/Jellyfin.Server/Startup.cs @@ -35,7 +35,7 @@ namespace Jellyfin.Server /// public class Startup { - private readonly IServerApplicationHost _serverApplicationHost; + private readonly CoreAppHost _serverApplicationHost; private readonly IServerConfigurationManager _serverConfigurationManager; /// diff --git a/MediaBrowser.Common/Net/NetworkConstants.cs b/MediaBrowser.Common/Net/NetworkConstants.cs index fe7ab89632..b18058fa96 100644 --- a/MediaBrowser.Common/Net/NetworkConstants.cs +++ b/MediaBrowser.Common/Net/NetworkConstants.cs @@ -1,4 +1,5 @@ using System.Net; +using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork; namespace MediaBrowser.Common.Net; diff --git a/MediaBrowser.Common/Net/NetworkUtils.cs b/MediaBrowser.Common/Net/NetworkUtils.cs index 7ae99336f1..4110b000e5 100644 --- a/MediaBrowser.Common/Net/NetworkUtils.cs +++ b/MediaBrowser.Common/Net/NetworkUtils.cs @@ -5,8 +5,7 @@ using System.Net; using System.Net.Sockets; using System.Text.RegularExpressions; using Jellyfin.Extensions; -using Jellyfin.Networking.Constants; -using Microsoft.AspNetCore.HttpOverrides; +using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork; namespace MediaBrowser.Common.Net; @@ -180,7 +179,7 @@ public static partial class NetworkUtils { if (TryParseToSubnet(values[a], out var innerResult, negated)) { - tmpResult.Add(innerResult.Value); + tmpResult.Add(innerResult); } } @@ -336,7 +335,7 @@ public static partial class NetworkUtils /// The broadcast address. public static IPAddress GetBroadcastAddress(IPNetwork network) { - var addressBytes = network.BaseAddress.GetAddressBytes(); + var addressBytes = network.Prefix.GetAddressBytes(); uint ipAddress = BitConverter.ToUInt32(addressBytes, 0); uint ipMaskV4 = BitConverter.ToUInt32(CidrToMask(network.PrefixLength, AddressFamily.InterNetwork).GetAddressBytes(), 0); uint broadCastIPAddress = ipAddress | ~ipMaskV4; diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index f12ef7e634..0d1d27ae8b 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -121,7 +121,7 @@ namespace MediaBrowser.MediaEncoding.Encoder "yadif_videotoolbox" }; - private static readonly IReadOnlyDictionary _filterOptionsDict = new Dictionary + private static readonly Dictionary _filterOptionsDict = new Dictionary { { 0, new string[] { "scale_cuda", "Output format (default \"same\")" } }, { 1, new string[] { "tonemap_cuda", "GPU accelerated HDR to SDR tonemapping" } }, @@ -132,7 +132,7 @@ namespace MediaBrowser.MediaEncoding.Encoder }; // These are the library versions that corresponds to our minimum ffmpeg version 4.x according to the version table below - private static readonly IReadOnlyDictionary _ffmpegMinimumLibraryVersions = new Dictionary + private static readonly Dictionary _ffmpegMinimumLibraryVersions = new Dictionary { { "libavutil", new Version(56, 14) }, { "libavcodec", new Version(58, 18) }, @@ -197,7 +197,7 @@ namespace MediaBrowser.MediaEncoding.Encoder internal bool ValidateVersionInternal(string versionOutput) { - if (versionOutput.IndexOf("Libav developers", StringComparison.OrdinalIgnoreCase) != -1) + if (versionOutput.Contains("Libav developers", StringComparison.OrdinalIgnoreCase)) { _logger.LogError("FFmpeg validation: avconv instead of ffmpeg is not supported"); return false; @@ -333,7 +333,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// The 'ffmpeg -version' output. /// The library names and major.minor version numbers. - private static IReadOnlyDictionary GetFFmpegLibraryVersions(string output) + private static Dictionary GetFFmpegLibraryVersions(string output) { var map = new Dictionary(); @@ -537,9 +537,9 @@ namespace MediaBrowser.MediaEncoding.Encoder return found; } - private IDictionary GetFFmpegFiltersWithOption() + private Dictionary GetFFmpegFiltersWithOption() { - IDictionary dict = new Dictionary(); + Dictionary dict = new Dictionary(); for (int i = 0; i < _filterOptionsDict.Count; i++) { if (_filterOptionsDict.TryGetValue(i, out var val) && val.Length == 2) diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs index 04128c9119..c5f500e76f 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs @@ -59,7 +59,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// System.String. private static string GetFileInputArgument(string path, string inputPrefix) { - if (path.IndexOf("://", StringComparison.Ordinal) != -1) + if (path.Contains("://", StringComparison.Ordinal)) { return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", path); } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 020e69eced..629c300603 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -612,11 +612,11 @@ namespace MediaBrowser.MediaEncoding.Probing { codec = "dvbsub"; } - else if ((codec ?? string.Empty).IndexOf("PGS", StringComparison.OrdinalIgnoreCase) != -1) + else if ((codec ?? string.Empty).Contains("PGS", StringComparison.OrdinalIgnoreCase)) { codec = "PGSSUB"; } - else if ((codec ?? string.Empty).IndexOf("DVD", StringComparison.OrdinalIgnoreCase) != -1) + else if ((codec ?? string.Empty).Contains("DVD", StringComparison.OrdinalIgnoreCase)) { codec = "DVDSUB"; } @@ -1339,7 +1339,7 @@ namespace MediaBrowser.MediaEncoding.Probing { // Only use the comma as a delimiter if there are no slashes or pipes. // We want to be careful not to split names that have commas in them - var delimiter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.IndexOf(i, StringComparison.Ordinal) != -1) ? + var delimiter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.Contains(i, StringComparison.Ordinal)) ? _nameDelimiters : new[] { ',' }; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs index 0d4489517e..fd55db4ba4 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs @@ -88,7 +88,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles public bool SupportsFileExtension(string fileExtension) => _subtitleFormats.ContainsKey(fileExtension); - private IEnumerable GetSubtitleFormats() + private List GetSubtitleFormats() { var subtitleFormats = new List(); var assembly = typeof(SubtitleFormat).Assembly; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 8eea773d86..459d854bf1 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -63,7 +63,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles private string SubtitleCachePath => Path.Combine(_appPaths.DataPath, "subtitles"); - private Stream ConvertSubtitles( + private MemoryStream ConvertSubtitles( Stream stream, string inputFormat, string outputFormat, diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 1ca5e4327c..89ec156a9f 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -33,6 +33,7 @@ + diff --git a/MediaBrowser.Model/Net/IPData.cs b/MediaBrowser.Model/Net/IPData.cs index e016ffea10..c116d883ed 100644 --- a/MediaBrowser.Model/Net/IPData.cs +++ b/MediaBrowser.Model/Net/IPData.cs @@ -1,5 +1,6 @@ using System.Net; using System.Net.Sockets; +using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork; namespace MediaBrowser.Model.Net; @@ -65,9 +66,9 @@ public class IPData { if (Address.Equals(IPAddress.None)) { - return Subnet.BaseAddress.AddressFamily.Equals(IPAddress.None) + return Subnet.Prefix.AddressFamily.Equals(IPAddress.None) ? AddressFamily.Unspecified - : Subnet.BaseAddress.AddressFamily; + : Subnet.Prefix.AddressFamily; } else { diff --git a/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs b/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs index 44d9ce13c0..123266d298 100644 --- a/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs +++ b/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs @@ -11,6 +11,7 @@ using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; using IConfigurationManager = MediaBrowser.Common.Configuration.IConfigurationManager; +using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork; namespace Jellyfin.Server.Tests { @@ -99,7 +100,7 @@ namespace Jellyfin.Server.Tests Assert.Equal(knownNetworks.Length, options.KnownNetworks.Count); foreach (var item in knownNetworks) { - Assert.NotNull(options.KnownNetworks.FirstOrDefault(x => x.Prefix.Equals(item.BaseAddress) && x.PrefixLength == item.PrefixLength)); + Assert.NotNull(options.KnownNetworks.FirstOrDefault(x => x.Prefix.Equals(item.Prefix) && x.PrefixLength == item.PrefixLength)); } } From 8ee15258944deb83b880cb5263fae2843a7af248 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 14 Nov 2023 22:01:10 +0100 Subject: [PATCH 06/11] Fix runtime errors --- Emby.Server.Implementations/ApplicationHost.cs | 4 +++- src/Jellyfin.Extensions/Json/JsonDefaults.cs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 9affe235db..4540ab205a 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -310,7 +310,9 @@ namespace Emby.Server.Implementations { _creatingInstances.Add(type); Logger.LogDebug("Creating instance of {Type}", type); - return ActivatorUtilities.CreateInstance(ServiceProvider, type); + return ServiceProvider is null + ? Activator.CreateInstance(type) + : ActivatorUtilities.CreateInstance(ServiceProvider, type); } catch (Exception ex) { diff --git a/src/Jellyfin.Extensions/Json/JsonDefaults.cs b/src/Jellyfin.Extensions/Json/JsonDefaults.cs index 4d56ca6151..9e6d4c3f87 100644 --- a/src/Jellyfin.Extensions/Json/JsonDefaults.cs +++ b/src/Jellyfin.Extensions/Json/JsonDefaults.cs @@ -1,5 +1,6 @@ using System.Text.Json; using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Metadata; using Jellyfin.Extensions.Json.Converters; namespace Jellyfin.Extensions.Json @@ -41,7 +42,8 @@ namespace Jellyfin.Extensions.Json new JsonNullableStructConverterFactory(), new JsonDateTimeConverter(), new JsonStringConverter() - } + }, + TypeInfoResolver = new DefaultJsonTypeInfoResolver() }; private static readonly JsonSerializerOptions _pascalCaseJsonSerializerOptions = new(_jsonSerializerOptions) From efec6e7a23fb0540559f7868640daf9624eecd7e Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 15 Nov 2023 15:22:51 +0100 Subject: [PATCH 07/11] Address review comment --- MediaBrowser.Model/Dlna/StreamBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 252ac1303f..bf18d46dcd 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -868,7 +868,7 @@ namespace MediaBrowser.Model.Dlna playlistItem.SetOption(audioStream.Codec, "profile", audioStream.Profile.ToLowerInvariant()); } - if (audioStream.Level.HasValue) + if (audioStream.Level.HasValue && audioStream.Level.Value != 0) { playlistItem.SetOption(audioStream.Codec, "level", audioStream.Level.Value.ToString(CultureInfo.InvariantCulture)); } From a1410ea899bcd6e84511e3304dd71cd33e53f156 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 15 Nov 2023 16:16:51 +0100 Subject: [PATCH 08/11] Update GitHub workflows --- .github/workflows/ci-codeql-analysis.yml | 2 +- .github/workflows/ci-openapi.yml | 4 ++-- .github/workflows/ci-tests.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-codeql-analysis.yml b/.github/workflows/ci-codeql-analysis.yml index f43d743f04..c3823610e5 100644 --- a/.github/workflows/ci-codeql-analysis.yml +++ b/.github/workflows/ci-codeql-analysis.yml @@ -24,7 +24,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0 with: - dotnet-version: '7.0.x' + dotnet-version: '8.0.x' - name: Initialize CodeQL uses: github/codeql-action/init@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5 diff --git a/.github/workflows/ci-openapi.yml b/.github/workflows/ci-openapi.yml index 96b790c0c7..62445a1ca3 100644 --- a/.github/workflows/ci-openapi.yml +++ b/.github/workflows/ci-openapi.yml @@ -21,7 +21,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0 with: - dotnet-version: '7.0.x' + dotnet-version: '8.0.x' - name: Generate openapi.json run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests" - name: Upload openapi.json @@ -55,7 +55,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0 with: - dotnet-version: '7.0.x' + dotnet-version: '8.0.x' - name: Generate openapi.json run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests" - name: Upload openapi.json diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 36686e64ba..a464609742 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -9,7 +9,7 @@ on: pull_request: env: - SDK_VERSION: "7.0.x" + SDK_VERSION: "8.0.x" jobs: run-tests: From 05b35dc41fa14290c2940ccd6de7ef63d303d7d2 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 15 Nov 2023 16:49:44 +0100 Subject: [PATCH 09/11] Update Azure pipelines --- .ci/azure-pipelines-abi.yml | 2 +- .ci/azure-pipelines-main.yml | 2 +- .ci/azure-pipelines-package.yml | 4 ++-- .ci/azure-pipelines-test.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.ci/azure-pipelines-abi.yml b/.ci/azure-pipelines-abi.yml index 4b82eedb45..547a514f86 100644 --- a/.ci/azure-pipelines-abi.yml +++ b/.ci/azure-pipelines-abi.yml @@ -7,7 +7,7 @@ parameters: default: "ubuntu-latest" - name: DotNetSdkVersion type: string - default: 7.0.x + default: 8.0.x jobs: - job: CompatibilityCheck diff --git a/.ci/azure-pipelines-main.yml b/.ci/azure-pipelines-main.yml index 020d7fff4a..0702aeb6b6 100644 --- a/.ci/azure-pipelines-main.yml +++ b/.ci/azure-pipelines-main.yml @@ -1,7 +1,7 @@ parameters: LinuxImage: 'ubuntu-latest' RestoreBuildProjects: 'Jellyfin.Server/Jellyfin.Server.csproj' - DotNetSdkVersion: 7.0.x + DotNetSdkVersion: 8.0.x jobs: - job: Build diff --git a/.ci/azure-pipelines-package.yml b/.ci/azure-pipelines-package.yml index c91a084e58..39f98e063e 100644 --- a/.ci/azure-pipelines-package.yml +++ b/.ci/azure-pipelines-package.yml @@ -208,10 +208,10 @@ jobs: steps: - task: UseDotNet@2 - displayName: 'Use .NET 7.0 sdk' + displayName: 'Use .NET 8.0 sdk' inputs: packageType: 'sdk' - version: '7.0.x' + version: '8.0.x' - task: DotNetCoreCLI@2 displayName: 'Build Stable Nuget packages' diff --git a/.ci/azure-pipelines-test.yml b/.ci/azure-pipelines-test.yml index f15d6a6cda..3549c691cb 100644 --- a/.ci/azure-pipelines-test.yml +++ b/.ci/azure-pipelines-test.yml @@ -10,7 +10,7 @@ parameters: default: "tests/**/*Tests.csproj" - name: DotNetSdkVersion type: string - default: 7.0.x + default: 8.0.x jobs: - job: Test From 5dad89cee331138dd2e4c24eecaea36aef2ee503 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 15 Nov 2023 22:06:09 +0100 Subject: [PATCH 10/11] Update Dockerfiles --- deployment/Dockerfile.centos.amd64 | 2 +- deployment/Dockerfile.fedora.amd64 | 2 +- deployment/Dockerfile.ubuntu.amd64 | 2 +- deployment/Dockerfile.ubuntu.arm64 | 2 +- deployment/Dockerfile.ubuntu.armhf | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/deployment/Dockerfile.centos.amd64 b/deployment/Dockerfile.centos.amd64 index e5cf638c1d..7c9bbf39e9 100644 --- a/deployment/Dockerfile.centos.amd64 +++ b/deployment/Dockerfile.centos.amd64 @@ -13,7 +13,7 @@ RUN yum update -yq \ && yum install -yq @buildsys-build rpmdevtools yum-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel git wget # Install DotNET SDK -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/ff8c660f-ffa9-4814-ac2d-4089e6ec4eb5/dc806d344844f1d58d8015d105e85c65/dotnet-sdk-7.0.403-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5226a5fa-8c0b-474f-b79a-8984ad7c5beb/3113ccbf789c9fd29972835f0f334b7a/dotnet-sdk-8.0.100-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.fedora.amd64 b/deployment/Dockerfile.fedora.amd64 index 777d92c116..66ead37d7d 100644 --- a/deployment/Dockerfile.fedora.amd64 +++ b/deployment/Dockerfile.fedora.amd64 @@ -12,7 +12,7 @@ RUN dnf update -yq \ && dnf install -yq @buildsys-build rpmdevtools git dnf-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel systemd wget make # Install DotNET SDK -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/ff8c660f-ffa9-4814-ac2d-4089e6ec4eb5/dc806d344844f1d58d8015d105e85c65/dotnet-sdk-7.0.403-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5226a5fa-8c0b-474f-b79a-8984ad7c5beb/3113ccbf789c9fd29972835f0f334b7a/dotnet-sdk-8.0.100-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.amd64 b/deployment/Dockerfile.ubuntu.amd64 index f34c0358d1..84fa2028e5 100644 --- a/deployment/Dockerfile.ubuntu.amd64 +++ b/deployment/Dockerfile.ubuntu.amd64 @@ -17,7 +17,7 @@ RUN apt-get update -yqq \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/ff8c660f-ffa9-4814-ac2d-4089e6ec4eb5/dc806d344844f1d58d8015d105e85c65/dotnet-sdk-7.0.403-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5226a5fa-8c0b-474f-b79a-8984ad7c5beb/3113ccbf789c9fd29972835f0f334b7a/dotnet-sdk-8.0.100-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.arm64 b/deployment/Dockerfile.ubuntu.arm64 index 87466d20ea..ca3aa35085 100644 --- a/deployment/Dockerfile.ubuntu.arm64 +++ b/deployment/Dockerfile.ubuntu.arm64 @@ -16,7 +16,7 @@ RUN apt-get update -yqq \ mmv build-essential lsb-release # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/ff8c660f-ffa9-4814-ac2d-4089e6ec4eb5/dc806d344844f1d58d8015d105e85c65/dotnet-sdk-7.0.403-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5226a5fa-8c0b-474f-b79a-8984ad7c5beb/3113ccbf789c9fd29972835f0f334b7a/dotnet-sdk-8.0.100-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.armhf b/deployment/Dockerfile.ubuntu.armhf index 261deb3e45..e52b7fba35 100644 --- a/deployment/Dockerfile.ubuntu.armhf +++ b/deployment/Dockerfile.ubuntu.armhf @@ -16,7 +16,7 @@ RUN apt-get update -yqq \ mmv build-essential lsb-release # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/ff8c660f-ffa9-4814-ac2d-4089e6ec4eb5/dc806d344844f1d58d8015d105e85c65/dotnet-sdk-7.0.403-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5226a5fa-8c0b-474f-b79a-8984ad7c5beb/3113ccbf789c9fd29972835f0f334b7a/dotnet-sdk-8.0.100-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet From 5fa1b8ac3a7e65f0972e4fc55e83172f66efd794 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 15 Nov 2023 22:21:20 +0100 Subject: [PATCH 11/11] Update more Dockerfiles --- Dockerfile | 2 +- Dockerfile.arm | 2 +- Dockerfile.arm64 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9be319311e..d3f10cd12e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ ##################################### # Requires binfm_misc registration # https://github.com/multiarch/qemu-user-static#binfmt_misc-register -ARG DOTNET_VERSION=7.0 +ARG DOTNET_VERSION=8.0 FROM node:20-alpine as web-builder ARG JELLYFIN_WEB_VERSION=master diff --git a/Dockerfile.arm b/Dockerfile.arm index e8ec6398e6..db1acc838a 100644 --- a/Dockerfile.arm +++ b/Dockerfile.arm @@ -2,7 +2,7 @@ ##################################### # Requires binfm_misc registration # https://github.com/multiarch/qemu-user-static#binfmt_misc-register -ARG DOTNET_VERSION=7.0 +ARG DOTNET_VERSION=8.0 FROM node:20-alpine as web-builder diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index 83137ee895..3eb5f45fc4 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -2,7 +2,7 @@ ##################################### # Requires binfm_misc registration # https://github.com/multiarch/qemu-user-static#binfmt_misc-register -ARG DOTNET_VERSION=7.0 +ARG DOTNET_VERSION=8.0 FROM node:20-alpine as web-builder