소스 검색

Merge pull request #6590 from jellyfin/dotnet6

Bond-009 3 년 전
부모
커밋
2ee3e9e00f
100개의 변경된 파일240개의 추가작업 그리고 219개의 파일을 삭제
  1. 2 1
      .ci/azure-pipelines-abi.yml
  2. 2 1
      .ci/azure-pipelines-main.yml
  3. 3 2
      .ci/azure-pipelines-package.yml
  4. 3 2
      .ci/azure-pipelines-test.yml
  5. 0 2
      .ci/azure-pipelines.yml
  6. 3 1
      .github/workflows/codeql-analysis.yml
  7. 1 1
      Dockerfile
  8. 1 1
      Dockerfile.arm
  9. 1 1
      Dockerfile.arm64
  10. 1 1
      DvdLib/DvdLib.csproj
  11. 2 1
      DvdLib/Ifo/Dvd.cs
  12. 8 4
      Emby.Dlna/DlnaManager.cs
  13. 1 1
      Emby.Dlna/Emby.Dlna.csproj
  14. 1 2
      Emby.Dlna/Server/DescriptionXmlBuilder.cs
  15. 4 4
      Emby.Dlna/Service/BaseService.cs
  16. 1 1
      Emby.Drawing/Emby.Drawing.csproj
  17. 1 1
      Emby.Naming/Emby.Naming.csproj
  18. 1 1
      Emby.Notifications/Emby.Notifications.csproj
  19. 1 1
      Emby.Photos/Emby.Photos.csproj
  20. 11 16
      Emby.Server.Implementations/Data/SqliteItemRepository.cs
  21. 1 1
      Emby.Server.Implementations/Emby.Server.Implementations.csproj
  22. 1 3
      Emby.Server.Implementations/Library/LibraryManager.cs
  23. 1 1
      Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
  24. 3 25
      Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs
  25. 3 3
      Jellyfin.Api/Auth/FirstTimeSetupOrDefaultPolicy/FirstTimeSetupOrDefaultHandler.cs
  26. 3 3
      Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs
  27. 5 5
      Jellyfin.Api/Controllers/ImageController.cs
  28. 2 1
      Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs
  29. 1 1
      Jellyfin.Api/Jellyfin.Api.csproj
  30. 3 2
      Jellyfin.Api/ModelBinders/NullableEnumModelBinder.cs
  31. 1 1
      Jellyfin.Data/Jellyfin.Data.csproj
  32. 1 6
      Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj
  33. 1 1
      Jellyfin.Networking/Jellyfin.Networking.csproj
  34. 1 1
      Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj
  35. 2 2
      Jellyfin.Server/Configuration/CorsPolicyProvider.cs
  36. 1 1
      Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs
  37. 1 1
      Jellyfin.Server/Jellyfin.Server.csproj
  38. 5 1
      Jellyfin.Server/Middleware/QueryStringDecodingMiddleware.cs
  39. 2 8
      Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs
  40. 1 1
      MediaBrowser.Common/MediaBrowser.Common.csproj
  41. 1 1
      MediaBrowser.Controller/Dlna/IDlnaManager.cs
  42. 1 1
      MediaBrowser.Controller/Drawing/IImageProcessor.cs
  43. 7 2
      MediaBrowser.Controller/Drawing/ImageStream.cs
  44. 1 1
      MediaBrowser.Controller/MediaBrowser.Controller.csproj
  45. 6 1
      MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
  46. 1 1
      MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
  47. 1 1
      MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
  48. 1 1
      MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs
  49. 1 1
      MediaBrowser.Model/MediaBrowser.Model.csproj
  50. 7 5
      MediaBrowser.Model/Net/MimeTypes.cs
  51. 1 1
      MediaBrowser.Providers/MediaBrowser.Providers.csproj
  52. 1 1
      MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs
  53. 1 1
      MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj
  54. 3 2
      RSSDP/DisposableManagedObjectBase.cs
  55. 1 1
      RSSDP/RSSDP.csproj
  56. 8 5
      RSSDP/SsdpDevice.cs
  57. 8 7
      RSSDP/SsdpDevicePublisher.cs
  58. 1 1
      debian/control
  59. 5 5
      deployment/Dockerfile.centos.amd64
  60. 1 1
      deployment/Dockerfile.debian.amd64
  61. 5 5
      deployment/Dockerfile.debian.arm64
  62. 5 5
      deployment/Dockerfile.debian.armhf
  63. 1 3
      deployment/Dockerfile.docker.amd64
  64. 1 3
      deployment/Dockerfile.docker.arm64
  65. 1 3
      deployment/Dockerfile.docker.armhf
  66. 6 3
      deployment/Dockerfile.fedora.amd64
  67. 1 1
      deployment/Dockerfile.linux.amd64
  68. 1 1
      deployment/Dockerfile.linux.amd64-musl
  69. 1 1
      deployment/Dockerfile.linux.arm64
  70. 1 1
      deployment/Dockerfile.linux.armhf
  71. 1 1
      deployment/Dockerfile.macos
  72. 1 1
      deployment/Dockerfile.portable
  73. 1 3
      deployment/Dockerfile.ubuntu.amd64
  74. 1 3
      deployment/Dockerfile.ubuntu.arm64
  75. 1 3
      deployment/Dockerfile.ubuntu.armhf
  76. 1 1
      deployment/Dockerfile.windows.amd64
  77. 19 0
      deployment/build.centos.amd64
  78. 2 2
      deployment/build.debian.amd64
  79. 2 2
      deployment/build.debian.arm64
  80. 2 2
      deployment/build.debian.armhf
  81. 19 0
      deployment/build.fedora.amd64
  82. 2 2
      deployment/build.ubuntu.amd64
  83. 2 2
      deployment/build.ubuntu.arm64
  84. 2 2
      deployment/build.ubuntu.armhf
  85. 1 1
      fedora/jellyfin.spec
  86. 2 2
      src/Jellyfin.Extensions/Jellyfin.Extensions.csproj
  87. 1 1
      src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs
  88. 1 1
      tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj
  89. 1 1
      tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj
  90. 1 1
      tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj
  91. 1 1
      tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj
  92. 1 1
      tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj
  93. 1 1
      tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj
  94. 1 1
      tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj
  95. 1 1
      tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj
  96. 1 1
      tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj
  97. 1 1
      tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj
  98. 1 1
      tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj
  99. 1 0
      tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs
  100. 1 1
      tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj

+ 2 - 1
.ci/azure-pipelines-abi.yml

@@ -7,7 +7,7 @@ parameters:
   default: "ubuntu-latest"
 - name: DotNetSdkVersion
   type: string
-  default: 5.0.302
+  default: 6.0.x
 
 jobs:
   - job: CompatibilityCheck
@@ -34,6 +34,7 @@ jobs:
         inputs:
           packageType: sdk
           version: ${{ parameters.DotNetSdkVersion }}
+          includePreviewVersions: true
 
       - task: DotNetCoreCLI@2
         displayName: 'Install ABI CompatibilityChecker Tool'

+ 2 - 1
.ci/azure-pipelines-main.yml

@@ -1,7 +1,7 @@
 parameters:
   LinuxImage: 'ubuntu-latest'
   RestoreBuildProjects: 'Jellyfin.Server/Jellyfin.Server.csproj'
-  DotNetSdkVersion: 5.0.302
+  DotNetSdkVersion: 6.0.x
 
 jobs:
   - job: Build
@@ -54,6 +54,7 @@ jobs:
         inputs:
           packageType: sdk
           version: ${{ parameters.DotNetSdkVersion }}
+          includePreviewVersions: true
 
       - task: DotNetCoreCLI@2
         displayName: 'Publish Server'

+ 3 - 2
.ci/azure-pipelines-package.yml

@@ -195,10 +195,11 @@ jobs:
 
   steps:
   - task: UseDotNet@2
-    displayName: 'Use .NET 5.0 sdk'
+    displayName: 'Use .NET 6.0 sdk'
     inputs:
       packageType: 'sdk'
-      version: '5.0.x'
+      version: '6.0.x'
+      includePreviewVersions: true
 
   - task: DotNetCoreCLI@2
     displayName: 'Build Stable Nuget packages'

+ 3 - 2
.ci/azure-pipelines-test.yml

@@ -10,7 +10,7 @@ parameters:
   default: "tests/**/*Tests.csproj"
 - name: DotNetSdkVersion
   type: string
-  default: 5.0.302
+  default: 6.0.x
 
 jobs:
   - job: Test
@@ -41,6 +41,7 @@ jobs:
         inputs:
           packageType: sdk
           version: ${{ parameters.DotNetSdkVersion }}
+          includePreviewVersions: true
 
       - task: SonarCloudPrepare@1
         displayName: 'Prepare analysis on SonarCloud'
@@ -94,5 +95,5 @@ jobs:
         displayName: 'Publish OpenAPI Artifact'
         condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux'))
         inputs:
-          targetPath: "tests/Jellyfin.Server.Integration.Tests/bin/Release/net5.0/openapi.json"
+          targetPath: "tests/Jellyfin.Server.Integration.Tests/bin/Release/net6.0/openapi.json"
           artifactName: 'OpenAPI Spec'

+ 0 - 2
.ci/azure-pipelines.yml

@@ -5,8 +5,6 @@ variables:
   value: 'tests/**/*Tests.csproj'
 - name: RestoreBuildProjects
   value: 'Jellyfin.Server/Jellyfin.Server.csproj'
-- name: DotNetSdkVersion
-  value: 5.0.302
 
 pr:
   autoCancel: true

+ 3 - 1
.github/workflows/codeql-analysis.yml

@@ -24,7 +24,9 @@ jobs:
     - name: Setup .NET Core
       uses: actions/setup-dotnet@v1
       with:
-        dotnet-version: '5.0.x'
+        dotnet-version: '6.0.x'
+        include-prerelease: true
+        
     - name: Initialize CodeQL
       uses: github/codeql-action/init@v1
       with:

+ 1 - 1
Dockerfile

@@ -2,7 +2,7 @@
 #####################################
 # Requires binfm_misc registration
 # https://github.com/multiarch/qemu-user-static#binfmt_misc-register
-ARG DOTNET_VERSION=5.0
+ARG DOTNET_VERSION=6.0
 
 FROM node:lts-alpine as web-builder
 ARG JELLYFIN_WEB_VERSION=master

+ 1 - 1
Dockerfile.arm

@@ -2,7 +2,7 @@
 #####################################
 # Requires binfm_misc registration
 # https://github.com/multiarch/qemu-user-static#binfmt_misc-register
-ARG DOTNET_VERSION=5.0
+ARG DOTNET_VERSION=6.0
 
 
 FROM node:lts-alpine as web-builder

+ 1 - 1
Dockerfile.arm64

@@ -2,7 +2,7 @@
 #####################################
 # Requires binfm_misc registration
 # https://github.com/multiarch/qemu-user-static#binfmt_misc-register
-ARG DOTNET_VERSION=5.0
+ARG DOTNET_VERSION=6.0
 
 
 FROM node:lts-alpine as web-builder

+ 1 - 1
DvdLib/DvdLib.csproj

@@ -10,7 +10,7 @@
   </ItemGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <AnalysisMode>AllDisabledByDefault</AnalysisMode>

+ 2 - 1
DvdLib/Ifo/Dvd.cs

@@ -2,6 +2,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.Globalization;
 using System.IO;
 using System.Linq;
 
@@ -76,7 +77,7 @@ namespace DvdLib.Ifo
 
         private void ReadVTS(ushort vtsNum, IReadOnlyList<FileInfo> allFiles)
         {
-            var filename = string.Format("VTS_{0:00}_0.IFO", vtsNum);
+            var filename = string.Format(CultureInfo.InvariantCulture, "VTS_{0:00}_0.IFO", vtsNum);
 
             var vtsPath = allFiles.FirstOrDefault(i => string.Equals(i.Name, filename, StringComparison.OrdinalIgnoreCase)) ??
                 allFiles.FirstOrDefault(i => string.Equals(i.Name, Path.ChangeExtension(filename, ".bup"), StringComparison.OrdinalIgnoreCase));

+ 8 - 4
Emby.Dlna/DlnaManager.cs

@@ -486,18 +486,22 @@ namespace Emby.Dlna
         }
 
         /// <inheritdoc />
-        public ImageStream GetIcon(string filename)
+        public ImageStream? GetIcon(string filename)
         {
             var format = filename.EndsWith(".png", StringComparison.OrdinalIgnoreCase)
                 ? ImageFormat.Png
                 : ImageFormat.Jpg;
 
             var resource = GetType().Namespace + ".Images." + filename.ToLowerInvariant();
+            var stream = _assembly.GetManifestResourceStream(resource);
+            if (stream == null)
+            {
+                return null;
+            }
 
-            return new ImageStream
+            return new ImageStream(stream)
             {
-                Format = format,
-                Stream = _assembly.GetManifestResourceStream(resource)
+                Format = format
             };
         }
 

+ 1 - 1
Emby.Dlna/Emby.Dlna.csproj

@@ -17,7 +17,7 @@
   </ItemGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <AnalysisMode>AllDisabledByDefault</AnalysisMode>

+ 1 - 2
Emby.Dlna/Server/DescriptionXmlBuilder.cs

@@ -250,8 +250,7 @@ namespace Emby.Dlna.Server
 
             url = _serverAddress.TrimEnd('/') + "/dlna/" + _serverUdn + "/" + url.TrimStart('/');
 
-            // TODO: @bond remove null-coalescing operator when https://github.com/dotnet/runtime/pull/52442 is merged/released
-            return SecurityElement.Escape(url) ?? string.Empty;
+            return SecurityElement.Escape(url);
         }
 
         private IEnumerable<DeviceIcon> GetIcons()

+ 4 - 4
Emby.Dlna/Service/BaseService.cs

@@ -23,14 +23,14 @@ namespace Emby.Dlna.Service
             return EventManager.CancelEventSubscription(subscriptionId);
         }
 
-        public EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string timeoutString, string callbackUrl)
+        public EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string requestedTimeoutString, string callbackUrl)
         {
-            return EventManager.RenewEventSubscription(subscriptionId, notificationType, timeoutString, callbackUrl);
+            return EventManager.RenewEventSubscription(subscriptionId, notificationType, requestedTimeoutString, callbackUrl);
         }
 
-        public EventSubscriptionResponse CreateEventSubscription(string notificationType, string timeoutString, string callbackUrl)
+        public EventSubscriptionResponse CreateEventSubscription(string notificationType, string requestedTimeoutString, string callbackUrl)
         {
-            return EventManager.CreateEventSubscription(notificationType, timeoutString, callbackUrl);
+            return EventManager.CreateEventSubscription(notificationType, requestedTimeoutString, callbackUrl);
         }
     }
 }

+ 1 - 1
Emby.Drawing/Emby.Drawing.csproj

@@ -6,7 +6,7 @@
   </PropertyGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <AnalysisMode>AllDisabledByDefault</AnalysisMode>

+ 1 - 1
Emby.Naming/Emby.Naming.csproj

@@ -6,7 +6,7 @@
   </PropertyGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <PublishRepositoryUrl>true</PublishRepositoryUrl>

+ 1 - 1
Emby.Notifications/Emby.Notifications.csproj

@@ -6,7 +6,7 @@
   </PropertyGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
   </PropertyGroup>

+ 1 - 1
Emby.Photos/Emby.Photos.csproj

@@ -19,7 +19,7 @@
   </ItemGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
   </PropertyGroup>

+ 11 - 16
Emby.Server.Implementations/Data/SqliteItemRepository.cs

@@ -1150,7 +1150,7 @@ namespace Emby.Server.Implementations.Data
                 return null;
             }
 
-            if (Enum.TryParse(imageType.ToString(), true, out ImageType type))
+            if (Enum.TryParse(imageType, true, out ImageType type))
             {
                 image.Type = type;
             }
@@ -1571,7 +1571,6 @@ namespace Emby.Server.Implementations.Data
 
             if (reader.TryGetString(index++, out var audioString))
             {
-                // TODO Span overload coming in the future https://github.com/dotnet/runtime/issues/1916
                 if (Enum.TryParse(audioString, true, out ProgramAudio audio))
                 {
                     item.Audio = audio;
@@ -1610,18 +1609,16 @@ namespace Emby.Server.Implementations.Data
             {
                 if (reader.TryGetString(index++, out var lockedFields))
                 {
-                    IEnumerable<MetadataField> GetLockedFields(string s)
+                    List<MetadataField> fields = null;
+                    foreach (var i in lockedFields.AsSpan().Split('|'))
                     {
-                        foreach (var i in s.Split('|', StringSplitOptions.RemoveEmptyEntries))
+                        if (Enum.TryParse(i, true, out MetadataField parsedValue))
                         {
-                            if (Enum.TryParse(i, true, out MetadataField parsedValue))
-                            {
-                                yield return parsedValue;
-                            }
+                            (fields ??= new List<MetadataField>()).Add(parsedValue);
                         }
                     }
 
-                    item.LockedFields = GetLockedFields(lockedFields).ToArray();
+                    item.LockedFields = fields?.ToArray() ?? Array.Empty<MetadataField>();
                 }
             }
 
@@ -1647,18 +1644,16 @@ namespace Emby.Server.Implementations.Data
                 {
                     if (reader.TryGetString(index, out var trailerTypes))
                     {
-                        IEnumerable<TrailerType> GetTrailerTypes(string s)
+                        List<TrailerType> types = null;
+                        foreach (var i in trailerTypes.AsSpan().Split('|'))
                         {
-                            foreach (var i in s.Split('|', StringSplitOptions.RemoveEmptyEntries))
+                            if (Enum.TryParse(i, true, out TrailerType parsedValue))
                             {
-                                if (Enum.TryParse(i, true, out TrailerType parsedValue))
-                                {
-                                    yield return parsedValue;
-                                }
+                                (types ??= new List<TrailerType>()).Add(parsedValue);
                             }
                         }
 
-                        trailer.TrailerTypes = GetTrailerTypes(trailerTypes).ToArray();
+                        trailer.TrailerTypes = types?.ToArray() ?? Array.Empty<TrailerType>();
                     }
                 }
 

+ 1 - 1
Emby.Server.Implementations/Emby.Server.Implementations.csproj

@@ -42,7 +42,7 @@
   </ItemGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <!-- https://github.com/microsoft/ApplicationInsights-dotnet/issues/2047 -->

+ 1 - 3
Emby.Server.Implementations/Library/LibraryManager.cs

@@ -1250,10 +1250,8 @@ namespace Emby.Server.Implementations.Library
         private CollectionTypeOptions? GetCollectionType(string path)
         {
             var files = _fileSystem.GetFilePaths(path, new[] { ".collection" }, true, false);
-            foreach (var file in files)
+            foreach (ReadOnlySpan<char> file in files)
             {
-                // TODO: @bond use a ReadOnlySpan<char> here when Enum.TryParse supports it
-                // https://github.com/dotnet/runtime/issues/20008
                 if (Enum.TryParse<CollectionTypeOptions>(Path.GetFileNameWithoutExtension(file), true, out var res))
                 {
                     return res;

+ 1 - 1
Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs

@@ -196,7 +196,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
                         cancellationToken,
                         timeOutSource.Token))
                     {
-                        var resTask = udpClient.ReceiveAsync();
+                        var resTask = udpClient.ReceiveAsync(linkedSource.Token).AsTask();
                         if (await Task.WhenAny(resTask, Task.Delay(30000, linkedSource.Token)).ConfigureAwait(false) != resTask)
                         {
                             resTask.Dispose();

+ 3 - 25
Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs

@@ -18,7 +18,7 @@ namespace Emby.Server.Implementations.QuickConnect
     /// <summary>
     /// Quick connect implementation.
     /// </summary>
-    public class QuickConnectManager : IQuickConnect, IDisposable
+    public class QuickConnectManager : IQuickConnect
     {
         /// <summary>
         /// The length of user facing codes.
@@ -30,7 +30,6 @@ namespace Emby.Server.Implementations.QuickConnect
         /// </summary>
         private const int Timeout = 10;
 
-        private readonly RNGCryptoServiceProvider _rng = new ();
         private readonly ConcurrentDictionary<string, QuickConnectResult> _currentRequests = new ();
         private readonly ConcurrentDictionary<string, (DateTime Timestamp, AuthenticationResult AuthenticationResult)> _authorizedSecrets = new ();
 
@@ -140,7 +139,7 @@ namespace Emby.Server.Implementations.QuickConnect
             uint scale = uint.MaxValue;
             while (scale == uint.MaxValue)
             {
-                _rng.GetBytes(raw);
+                RandomNumberGenerator.Fill(raw);
                 scale = BitConverter.ToUInt32(raw);
             }
 
@@ -199,31 +198,10 @@ namespace Emby.Server.Implementations.QuickConnect
             return result.AuthenticationResult;
         }
 
-        /// <summary>
-        /// Dispose.
-        /// </summary>
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        /// <summary>
-        /// Dispose.
-        /// </summary>
-        /// <param name="disposing">Dispose unmanaged resources.</param>
-        protected virtual void Dispose(bool disposing)
-        {
-            if (disposing)
-            {
-                _rng.Dispose();
-            }
-        }
-
         private string GenerateSecureRandom(int length = 32)
         {
             Span<byte> bytes = stackalloc byte[length];
-            _rng.GetBytes(bytes);
+            RandomNumberGenerator.Fill(bytes);
 
             return Convert.ToHexString(bytes);
         }

+ 3 - 3
Jellyfin.Api/Auth/FirstTimeSetupOrDefaultPolicy/FirstTimeSetupOrDefaultHandler.cs

@@ -32,18 +32,18 @@ namespace Jellyfin.Api.Auth.FirstTimeSetupOrDefaultPolicy
         }
 
         /// <inheritdoc />
-        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeSetupOrDefaultRequirement firstTimeSetupOrDefaultRequirement)
+        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeSetupOrDefaultRequirement requirement)
         {
             if (!_configurationManager.CommonConfiguration.IsStartupWizardCompleted)
             {
-                context.Succeed(firstTimeSetupOrDefaultRequirement);
+                context.Succeed(requirement);
                 return Task.CompletedTask;
             }
 
             var validated = ValidateClaims(context.User);
             if (validated)
             {
-                context.Succeed(firstTimeSetupOrDefaultRequirement);
+                context.Succeed(requirement);
             }
             else
             {

+ 3 - 3
Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs

@@ -33,18 +33,18 @@ namespace Jellyfin.Api.Auth.FirstTimeSetupOrElevatedPolicy
         }
 
         /// <inheritdoc />
-        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeSetupOrElevatedRequirement firstTimeSetupOrElevatedRequirement)
+        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeSetupOrElevatedRequirement requirement)
         {
             if (!_configurationManager.CommonConfiguration.IsStartupWizardCompleted)
             {
-                context.Succeed(firstTimeSetupOrElevatedRequirement);
+                context.Succeed(requirement);
                 return Task.CompletedTask;
             }
 
             var validated = ValidateClaims(context.User);
             if (validated && context.User.IsInRole(UserRoles.Administrator))
             {
-                context.Succeed(firstTimeSetupOrElevatedRequirement);
+                context.Succeed(requirement);
             }
             else
             {

+ 5 - 5
Jellyfin.Api/Controllers/ImageController.cs

@@ -106,7 +106,7 @@ namespace Jellyfin.Api.Controllers
             await using var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
 
             // Handle image/png; charset=utf-8
-            var mimeType = Request.ContentType.Split(';').FirstOrDefault();
+            var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
             var userDataPath = Path.Combine(_serverConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username);
             if (user.ProfileImage != null)
             {
@@ -153,7 +153,7 @@ namespace Jellyfin.Api.Controllers
             await using var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
 
             // Handle image/png; charset=utf-8
-            var mimeType = Request.ContentType.Split(';').FirstOrDefault();
+            var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
             var userDataPath = Path.Combine(_serverConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username);
             if (user.ProfileImage != null)
             {
@@ -341,7 +341,7 @@ namespace Jellyfin.Api.Controllers
             await using var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
 
             // Handle image/png; charset=utf-8
-            var mimeType = Request.ContentType.Split(';').FirstOrDefault();
+            var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
             await _providerManager.SaveImage(item, memoryStream, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false);
             await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
 
@@ -377,7 +377,7 @@ namespace Jellyfin.Api.Controllers
             await using var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
 
             // Handle image/png; charset=utf-8
-            var mimeType = Request.ContentType.Split(';').FirstOrDefault();
+            var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
             await _providerManager.SaveImage(item, memoryStream, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false);
             await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
 
@@ -2026,7 +2026,7 @@ namespace Jellyfin.Api.Controllers
                 return NoContent();
             }
 
-            return PhysicalFile(imagePath, imageContentType);
+            return PhysicalFile(imagePath, imageContentType ?? MediaTypeNames.Text.Plain);
         }
     }
 }

+ 2 - 1
Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs

@@ -1,6 +1,7 @@
 using System;
 using System.IO;
 using System.Net.Http;
+using System.Net.Mime;
 using System.Threading;
 using System.Threading.Tasks;
 using Jellyfin.Api.Models.PlaybackDtos;
@@ -40,7 +41,7 @@ namespace Jellyfin.Api.Helpers
 
             // Can't dispose the response as it's required up the call chain.
             var response = await httpClient.GetAsync(new Uri(state.MediaPath), cancellationToken).ConfigureAwait(false);
-            var contentType = response.Content.Headers.ContentType?.ToString();
+            var contentType = response.Content.Headers.ContentType?.ToString() ?? MediaTypeNames.Text.Plain;
 
             httpContext.Response.Headers[HeaderNames.AcceptRanges] = "none";
 

+ 1 - 1
Jellyfin.Api/Jellyfin.Api.csproj

@@ -6,7 +6,7 @@
   </PropertyGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <!-- https://github.com/microsoft/ApplicationInsights-dotnet/issues/2047 -->
     <NoWarn>AD0001</NoWarn>

+ 3 - 2
Jellyfin.Api/ModelBinders/NullableEnumModelBinder.cs

@@ -32,7 +32,8 @@ namespace Jellyfin.Api.ModelBinders
             {
                 try
                 {
-                    var convertedValue = converter.ConvertFromString(valueProviderResult.FirstValue);
+                    // REVIEW: This shouldn't be null here
+                    var convertedValue = converter.ConvertFromString(valueProviderResult.FirstValue!);
                     bindingContext.Result = ModelBindingResult.Success(convertedValue);
                 }
                 catch (FormatException e)
@@ -44,4 +45,4 @@ namespace Jellyfin.Api.ModelBinders
             return Task.CompletedTask;
         }
     }
-}
+}

+ 1 - 1
Jellyfin.Data/Jellyfin.Data.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <PublishRepositoryUrl>true</PublishRepositoryUrl>

+ 1 - 6
Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj

@@ -6,7 +6,7 @@
   </PropertyGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
   </PropertyGroup>
@@ -28,11 +28,6 @@
     <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" />
   </ItemGroup>
 
-  <ItemGroup>
-    <!-- Needed for https://github.com/dotnet/roslyn-analyzers/issues/4382 which is in the SDK yet -->
-    <PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.0.3" PrivateAssets="All" />
-  </ItemGroup>
-
   <!-- Code analysers-->
   <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />

+ 1 - 1
Jellyfin.Networking/Jellyfin.Networking.csproj

@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
   </PropertyGroup>

+ 1 - 1
Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
   </PropertyGroup>

+ 2 - 2
Jellyfin.Server/Configuration/CorsPolicyProvider.cs

@@ -23,7 +23,7 @@ namespace Jellyfin.Server.Configuration
         }
 
         /// <inheritdoc />
-        public Task<CorsPolicy> GetPolicyAsync(HttpContext context, string policyName)
+        public Task<CorsPolicy?> GetPolicyAsync(HttpContext context, string? policyName)
         {
             var corsHosts = _serverConfigurationManager.Configuration.CorsHosts;
             var builder = new CorsPolicyBuilder()
@@ -43,7 +43,7 @@ namespace Jellyfin.Server.Configuration
                     .AllowCredentials();
             }
 
-            return Task.FromResult(builder.Build());
+            return Task.FromResult<CorsPolicy?>(builder.Build());
         }
     }
 }

+ 1 - 1
Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs

@@ -68,7 +68,7 @@ namespace Jellyfin.Server.Infrastructure
         }
 
         /// <inheritdoc />
-        protected override Task WriteFileAsync(ActionContext context, PhysicalFileResult result, RangeItemHeaderValue range, long rangeLength)
+        protected override Task WriteFileAsync(ActionContext context, PhysicalFileResult result, RangeItemHeaderValue? range, long rangeLength)
         {
             if (context == null)
             {

+ 1 - 1
Jellyfin.Server/Jellyfin.Server.csproj

@@ -8,7 +8,7 @@
   <PropertyGroup>
     <AssemblyName>jellyfin</AssemblyName>
     <OutputType>Exe</OutputType>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <ServerGarbageCollection>false</ServerGarbageCollection>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>

+ 5 - 1
Jellyfin.Server/Middleware/QueryStringDecodingMiddleware.cs

@@ -27,7 +27,11 @@ namespace Jellyfin.Server.Middleware
         /// <returns>The async task.</returns>
         public async Task Invoke(HttpContext httpContext)
         {
-            httpContext.Features.Set<IQueryFeature>(new UrlDecodeQueryFeature(httpContext.Features.Get<IQueryFeature>()));
+            var feature = httpContext.Features.Get<IQueryFeature>();
+            if (feature != null)
+            {
+                httpContext.Features.Set<IQueryFeature>(new UrlDecodeQueryFeature(feature));
+            }
 
             await _next(httpContext).ConfigureAwait(false);
         }

+ 2 - 8
Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs

@@ -52,20 +52,14 @@ namespace Jellyfin.Server.Middleware
                     return;
                 }
 
-                // Unencode and re-parse querystring.
-                var unencodedKey = HttpUtility.UrlDecode(key);
-
-                if (string.Equals(unencodedKey, key, StringComparison.Ordinal))
+                if (!key.Contains('='))
                 {
-                    // Don't do anything if it's not encoded.
                     _store = value;
                     return;
                 }
 
                 var pairs = new Dictionary<string, StringValues>();
-                var queryString = unencodedKey.SpanSplit('&');
-
-                foreach (var pair in queryString)
+                foreach (var pair in key.SpanSplit('&'))
                 {
                     var i = pair.IndexOf('=');
                     if (i == -1)

+ 1 - 1
MediaBrowser.Common/MediaBrowser.Common.csproj

@@ -29,7 +29,7 @@
   </ItemGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <PublishRepositoryUrl>true</PublishRepositoryUrl>

+ 1 - 1
MediaBrowser.Controller/Dlna/IDlnaManager.cs

@@ -74,6 +74,6 @@ namespace MediaBrowser.Controller.Dlna
         /// </summary>
         /// <param name="filename">The filename.</param>
         /// <returns>DlnaIconResponse.</returns>
-        ImageStream GetIcon(string filename);
+        ImageStream? GetIcon(string filename);
     }
 }

+ 1 - 1
MediaBrowser.Controller/Drawing/IImageProcessor.cs

@@ -58,7 +58,7 @@ namespace MediaBrowser.Controller.Drawing
         /// <returns>Guid.</returns>
         string GetImageCacheTag(BaseItem item, ItemImageInfo image);
 
-        string GetImageCacheTag(BaseItem item, ChapterInfo info);
+        string GetImageCacheTag(BaseItem item, ChapterInfo chapter);
 
         string? GetImageCacheTag(User user);
 

+ 7 - 2
MediaBrowser.Controller/Drawing/ImageStream.cs

@@ -8,11 +8,16 @@ namespace MediaBrowser.Controller.Drawing
 {
     public class ImageStream : IDisposable
     {
+        public ImageStream(Stream stream)
+        {
+            Stream = stream;
+        }
+
         /// <summary>
-        /// Gets or sets the stream.
+        /// Gets the stream.
         /// </summary>
         /// <value>The stream.</value>
-        public Stream? Stream { get; set; }
+        public Stream Stream { get; }
 
         /// <summary>
         /// Gets or sets the format.

+ 1 - 1
MediaBrowser.Controller/MediaBrowser.Controller.csproj

@@ -32,7 +32,7 @@
   </ItemGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <PublishRepositoryUrl>true</PublishRepositoryUrl>

+ 6 - 1
MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs

@@ -541,7 +541,12 @@ namespace MediaBrowser.Controller.MediaEncoding
                 return MimeType;
             }
 
-            return MimeTypes.GetMimeType(outputPath, enableStreamDefault);
+            if (enableStreamDefault)
+            {
+                return MimeTypes.GetMimeType(outputPath);
+            }
+
+            return MimeTypes.GetMimeType(outputPath, null);
         }
 
         public bool DeInterlace(string videoCodec, bool forceDeinterlaceIfSourceIsInterlaced)

+ 1 - 1
MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj

@@ -11,7 +11,7 @@
   </ItemGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
   </PropertyGroup>

+ 1 - 1
MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj

@@ -6,7 +6,7 @@
   </PropertyGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
   </PropertyGroup>

+ 1 - 1
MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs

@@ -38,7 +38,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
             subRip.LoadSubtitle(subtitle, lines, "untitled");
             if (subRip.ErrorCount > 0)
             {
-                _logger.LogError("{ErrorCount} errors encountered while parsing subtitle.");
+                _logger.LogError("{ErrorCount} errors encountered while parsing subtitle", subRip.ErrorCount);
             }
 
             var trackInfo = new SubtitleTrackInfo();

+ 1 - 1
MediaBrowser.Model/MediaBrowser.Model.csproj

@@ -14,7 +14,7 @@
   </PropertyGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <PublishRepositoryUrl>true</PublishRepositoryUrl>

+ 7 - 5
MediaBrowser.Model/Net/MimeTypes.cs

@@ -2,6 +2,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Linq;
 using Jellyfin.Extensions;
@@ -164,15 +165,16 @@ namespace MediaBrowser.Model.Net
             return dict;
         }
 
-        public static string? GetMimeType(string path) => GetMimeType(path, true);
+        public static string GetMimeType(string path) => GetMimeType(path, "application/octet-stream");
 
         /// <summary>
         /// Gets the type of the MIME.
         /// </summary>
         /// <param name="filename">The filename to find the MIME type of.</param>
-        /// <param name="enableStreamDefault">Whether of not to return a default value if no fitting MIME type is found.</param>
-        /// <returns>The worrect MIME type for the given filename, or `null` if it wasn't found and <paramref name="enableStreamDefault"/> is false.</returns>
-        public static string? GetMimeType(string filename, bool enableStreamDefault)
+        /// <param name="defaultValue">The default value to return if no fitting MIME type is found.</param>
+        /// <returns>The correct MIME type for the given filename, or <paramref name="defaultValue"/> if it wasn't found.</returns>
+        [return: NotNullIfNotNullAttribute("defaultValue")]
+        public static string? GetMimeType(string filename, string? defaultValue = null)
         {
             if (filename.Length == 0)
             {
@@ -211,7 +213,7 @@ namespace MediaBrowser.Model.Net
                 return "application/octet-stream";
             }
 
-            return enableStreamDefault ? "application/octet-stream" : null;
+            return defaultValue;
         }
 
         public static string? ToExtension(string mimeType)

+ 1 - 1
MediaBrowser.Providers/MediaBrowser.Providers.csproj

@@ -26,7 +26,7 @@
   </ItemGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>

+ 1 - 1
MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs

@@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             if (reader.TokenType == JsonTokenType.String)
             {
                 var str = reader.GetString();
-                if (str != null && str.Equals("N/A", StringComparison.OrdinalIgnoreCase))
+                if (str == null || str.Equals("N/A", StringComparison.OrdinalIgnoreCase))
                 {
                     return null;
                 }

+ 1 - 1
MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj

@@ -15,7 +15,7 @@
   </ItemGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
   </PropertyGroup>

+ 3 - 2
RSSDP/DisposableManagedObjectBase.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Globalization;
 using System.Text;
 
 namespace Rssdp.Infrastructure
@@ -45,11 +46,11 @@ namespace Rssdp.Infrastructure
 
             const string ArgFormat = "{0}: {1}\r\n";
 
-            builder.AppendFormat("{0}\r\n", header);
+            builder.AppendFormat(CultureInfo.InvariantCulture, "{0}\r\n", header);
 
             foreach (var pair in values)
             {
-                builder.AppendFormat(ArgFormat, pair.Key, pair.Value);
+                builder.AppendFormat(CultureInfo.InvariantCulture, ArgFormat, pair.Key, pair.Value);
             }
 
             builder.Append("\r\n");

+ 1 - 1
RSSDP/RSSDP.csproj

@@ -11,7 +11,7 @@
   </ItemGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <AnalysisMode>AllDisabledByDefault</AnalysisMode>
     <Nullable>disable</Nullable>

+ 8 - 5
RSSDP/SsdpDevice.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
+using System.Globalization;
 using Rssdp.Infrastructure;
 
 namespace Rssdp
@@ -134,11 +135,13 @@ namespace Rssdp
         {
             get
             {
-                return String.Format("urn:{0}:{3}:{1}:{2}",
-                this.DeviceTypeNamespace ?? String.Empty,
-                this.DeviceType ?? String.Empty,
-                this.DeviceVersion,
-                this.DeviceClass ?? "device");
+                return String.Format(
+                    CultureInfo.InvariantCulture,
+                    "urn:{0}:{3}:{1}:{2}",
+                    this.DeviceTypeNamespace ?? String.Empty,
+                    this.DeviceType ?? String.Empty,
+                    this.DeviceVersion,
+                    this.DeviceClass ?? "device");
             }
         }
 

+ 8 - 7
RSSDP/SsdpDevicePublisher.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
+using System.Globalization;
 using System.Linq;
 using System.Net;
 using System.Threading;
@@ -233,7 +234,7 @@ namespace Rssdp.Infrastructure
         {
             if (String.IsNullOrEmpty(searchTarget))
             {
-                WriteTrace(String.Format("Invalid search request received From {0}, Target is null/empty.", remoteEndPoint.ToString()));
+                WriteTrace(String.Format(CultureInfo.InvariantCulture, "Invalid search request received From {0}, Target is null/empty.", remoteEndPoint.ToString()));
                 return;
             }
 
@@ -340,7 +341,7 @@ namespace Rssdp.Infrastructure
 
         private string GetUsn(string udn, string fullDeviceType)
         {
-            return String.Format("{0}::{1}", udn, fullDeviceType);
+            return String.Format(CultureInfo.InvariantCulture, "{0}::{1}", udn, fullDeviceType);
         }
 
         private async void SendSearchResponse(
@@ -363,7 +364,7 @@ namespace Rssdp.Infrastructure
             values["DATE"] = DateTime.UtcNow.ToString("r");
             values["CACHE-CONTROL"] = "max-age = " + rootDevice.CacheLifetime.TotalSeconds;
             values["ST"] = searchTarget;
-            values["SERVER"] = string.Format("{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion);
+            values["SERVER"] = string.Format(CultureInfo.InvariantCulture, "{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion);
             values["USN"] = uniqueServiceName;
             values["LOCATION"] = rootDevice.Location.ToString();
 
@@ -497,7 +498,7 @@ namespace Rssdp.Infrastructure
             values["DATE"] = DateTime.UtcNow.ToString("r");
             values["CACHE-CONTROL"] = "max-age = " + rootDevice.CacheLifetime.TotalSeconds;
             values["LOCATION"] = rootDevice.Location.ToString();
-            values["SERVER"] = string.Format("{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion);
+            values["SERVER"] = string.Format(CultureInfo.InvariantCulture, "{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion);
             values["NTS"] = "ssdp:alive";
             values["NT"] = notificationType;
             values["USN"] = uniqueServiceName;
@@ -522,7 +523,7 @@ namespace Rssdp.Infrastructure
             }
 
             tasks.Add(SendByeByeNotification(device, device.Udn, device.Udn, cancellationToken));
-            tasks.Add(SendByeByeNotification(device, String.Format("urn:{0}", device.FullDeviceType), GetUsn(device.Udn, device.FullDeviceType), cancellationToken));
+            tasks.Add(SendByeByeNotification(device, String.Format(CultureInfo.InvariantCulture, "urn:{0}", device.FullDeviceType), GetUsn(device.Udn, device.FullDeviceType), cancellationToken));
 
             foreach (var childDevice in device.Devices)
             {
@@ -542,7 +543,7 @@ namespace Rssdp.Infrastructure
             // If needed later for non-server devices, these headers will need to be dynamic
             values["HOST"] = "239.255.255.250:1900";
             values["DATE"] = DateTime.UtcNow.ToString("r");
-            values["SERVER"] = string.Format("{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion);
+            values["SERVER"] = string.Format(CultureInfo.InvariantCulture, "{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion);
             values["NTS"] = "ssdp:byebye";
             values["NT"] = notificationType;
             values["USN"] = uniqueServiceName;
@@ -550,7 +551,7 @@ namespace Rssdp.Infrastructure
             var message = BuildMessage(header, values);
 
             var sendCount = IsDisposed ? 1 : 3;
-            WriteTrace(String.Format("Sent byebye notification"), device);
+            WriteTrace(String.Format(CultureInfo.InvariantCulture, "Sent byebye notification"), device);
             return _CommsServer.SendMulticastMessage(message, sendCount, _sendOnlyMatchedHost ? device.ToRootDevice().Address : null, cancellationToken);
         }
 

+ 1 - 1
debian/control

@@ -3,7 +3,7 @@ Section: misc
 Priority: optional
 Maintainer: Jellyfin Team <team@jellyfin.org>
 Build-Depends:  debhelper (>= 9),
-                dotnet-sdk-5.0,
+                dotnet-sdk-6.0,
                 libc6-dev,
                 libcurl4-openssl-dev,
                 libfontconfig1-dev,

+ 5 - 5
deployment/Dockerfile.centos.amd64

@@ -2,7 +2,6 @@ FROM centos:7
 # Docker build arguments
 ARG SOURCE_DIR=/jellyfin
 ARG ARTIFACT_DIR=/dist
-ARG SDK_VERSION=5.0
 # Docker run environment
 ENV SOURCE_DIR=/jellyfin
 ENV ARTIFACT_DIR=/dist
@@ -11,12 +10,13 @@ ENV IS_DOCKER=YES
 # Prepare CentOS environment
 RUN yum update -yq \
   && yum install -yq epel-release \
-  && yum install -yq @buildsys-build rpmdevtools yum-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel git
+  && 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 rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm \
-  && rpmdev-setuptree \
-  && yum install -yq dotnet-sdk-${SDK_VERSION}
+RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5fcb98bb-21e1-47a5-bb8e-bb25f41a3e52/04811d5d05b7e694f040d2a13c1aae4c/dotnet-sdk-6.0.100-rc.1.21463.6-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
 
 # Create symlinks and directories
 RUN ln -sf ${SOURCE_DIR}/deployment/build.centos.amd64 /build.sh \

+ 1 - 1
deployment/Dockerfile.debian.amd64

@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim
+FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim
 # Docker build arguments
 ARG SOURCE_DIR=/jellyfin
 ARG ARTIFACT_DIR=/dist

+ 5 - 5
deployment/Dockerfile.debian.arm64

@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim
+FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim
 # Docker build arguments
 ARG SOURCE_DIR=/jellyfin
 ARG ARTIFACT_DIR=/dist
@@ -18,16 +18,16 @@ RUN apt-get update -yqq \
 RUN dpkg --add-architecture arm64 \
   && apt-get update -yqq \
   && apt-get install -yqq --no-install-recommends cross-gcc-dev \
-  && TARGET_LIST="arm64" cross-gcc-gensource 8 \
-  && cd cross-gcc-packages-amd64/cross-gcc-8-arm64 \
+  && TARGET_LIST="arm64" cross-gcc-gensource 9 \
+  && cd cross-gcc-packages-amd64/cross-gcc-9-arm64 \
   && apt-get install -yqq --no-install-recommends \
-    gcc-8-source libstdc++-8-dev-arm64-cross \
+    gcc-9-source libstdc++-9-dev-arm64-cross \
     binutils-aarch64-linux-gnu bison flex libtool \
     gdb sharutils netbase libmpc-dev libmpfr-dev libgmp-dev \
     systemtap-sdt-dev autogen expect chrpath zlib1g-dev zip \
     libc6-dev:arm64 linux-libc-dev:arm64 libgcc1:arm64 \
     libcurl4-openssl-dev:arm64 libfontconfig1-dev:arm64 \
-    libfreetype6-dev:arm64 libssl-dev:arm64 liblttng-ust0:arm64 libstdc++-8-dev:arm64
+    libfreetype6-dev:arm64 libssl-dev:arm64 liblttng-ust0:arm64 libstdc++-9-dev:arm64
 
 # Link to build script
 RUN ln -sf ${SOURCE_DIR}/deployment/build.debian.arm64 /build.sh

+ 5 - 5
deployment/Dockerfile.debian.armhf

@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim
+FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim
 # Docker build arguments
 ARG SOURCE_DIR=/jellyfin
 ARG ARTIFACT_DIR=/dist
@@ -18,17 +18,17 @@ RUN apt-get update -yqq \
 RUN dpkg --add-architecture armhf \
   && apt-get update -yqq \
   && apt-get install -yqq --no-install-recommends cross-gcc-dev \
-  && TARGET_LIST="armhf" cross-gcc-gensource 8 \
-  && cd cross-gcc-packages-amd64/cross-gcc-8-armhf \
+  && TARGET_LIST="armhf" cross-gcc-gensource 9 \
+  && cd cross-gcc-packages-amd64/cross-gcc-9-armhf \
   && apt-get install -yqq --no-install-recommends\
-    gcc-8-source libstdc++-8-dev-armhf-cross \
+    gcc-9-source libstdc++-9-dev-armhf-cross \
     binutils-aarch64-linux-gnu bison flex libtool gdb \
     sharutils netbase libmpc-dev libmpfr-dev libgmp-dev \
     systemtap-sdt-dev autogen expect chrpath zlib1g-dev \
     zip binutils-arm-linux-gnueabihf libc6-dev:armhf \
     linux-libc-dev:armhf libgcc1:armhf libcurl4-openssl-dev:armhf \
     libfontconfig1-dev:armhf libfreetype6-dev:armhf libssl-dev:armhf \
-    liblttng-ust0:armhf libstdc++-8-dev:armhf
+    liblttng-ust0:armhf libstdc++-9-dev:armhf
 
 # Link to build script
 RUN ln -sf ${SOURCE_DIR}/deployment/build.debian.armhf /build.sh

+ 1 - 3
deployment/Dockerfile.docker.amd64

@@ -1,6 +1,4 @@
-ARG DOTNET_VERSION=5.0
-
-FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION}-buster-slim
+FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim
 
 ARG SOURCE_DIR=/src
 ARG ARTIFACT_DIR=/jellyfin

+ 1 - 3
deployment/Dockerfile.docker.arm64

@@ -1,6 +1,4 @@
-ARG DOTNET_VERSION=5.0
-
-FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION}-buster-slim
+FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim
 
 ARG SOURCE_DIR=/src
 ARG ARTIFACT_DIR=/jellyfin

+ 1 - 3
deployment/Dockerfile.docker.armhf

@@ -1,6 +1,4 @@
-ARG DOTNET_VERSION=5.0
-
-FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION}-buster-slim
+FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim
 
 ARG SOURCE_DIR=/src
 ARG ARTIFACT_DIR=/jellyfin

+ 6 - 3
deployment/Dockerfile.fedora.amd64

@@ -2,7 +2,6 @@ FROM fedora:33
 # Docker build arguments
 ARG SOURCE_DIR=/jellyfin
 ARG ARTIFACT_DIR=/dist
-ARG SDK_VERSION=5.0
 # Docker run environment
 ENV SOURCE_DIR=/jellyfin
 ENV ARTIFACT_DIR=/dist
@@ -10,10 +9,14 @@ ENV IS_DOCKER=YES
 
 # Prepare Fedora environment
 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
+  && dnf install -yq @buildsys-build rpmdevtools git dnf-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel systemd wget
 
 # Install DotNET SDK
-RUN dnf install -yq dotnet-sdk-${SDK_VERSION} dotnet-runtime-${SDK_VERSION}
+RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5fcb98bb-21e1-47a5-bb8e-bb25f41a3e52/04811d5d05b7e694f040d2a13c1aae4c/dotnet-sdk-6.0.100-rc.1.21463.6-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
+
 
 # Create symlinks and directories
 RUN ln -sf ${SOURCE_DIR}/deployment/build.fedora.amd64 /build.sh \

+ 1 - 1
deployment/Dockerfile.linux.amd64

@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim
+FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim
 # Docker build arguments
 ARG SOURCE_DIR=/jellyfin
 ARG ARTIFACT_DIR=/dist

+ 1 - 1
deployment/Dockerfile.linux.amd64-musl

@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim
+FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim
 # Docker build arguments
 ARG SOURCE_DIR=/jellyfin
 ARG ARTIFACT_DIR=/dist

+ 1 - 1
deployment/Dockerfile.linux.arm64

@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim
+FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim
 # Docker build arguments
 ARG SOURCE_DIR=/jellyfin
 ARG ARTIFACT_DIR=/dist

+ 1 - 1
deployment/Dockerfile.linux.armhf

@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim
+FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim
 # Docker build arguments
 ARG SOURCE_DIR=/jellyfin
 ARG ARTIFACT_DIR=/dist

+ 1 - 1
deployment/Dockerfile.macos

@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim
+FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim
 # Docker build arguments
 ARG SOURCE_DIR=/jellyfin
 ARG ARTIFACT_DIR=/dist

+ 1 - 1
deployment/Dockerfile.portable

@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim
+FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim
 # Docker build arguments
 ARG SOURCE_DIR=/jellyfin
 ARG ARTIFACT_DIR=/dist

+ 1 - 3
deployment/Dockerfile.ubuntu.amd64

@@ -2,7 +2,6 @@ FROM ubuntu:bionic
 # Docker build arguments
 ARG SOURCE_DIR=/jellyfin
 ARG ARTIFACT_DIR=/dist
-ARG SDK_VERSION=5.0
 # Docker run environment
 ENV SOURCE_DIR=/jellyfin
 ENV ARTIFACT_DIR=/dist
@@ -18,8 +17,7 @@ RUN apt-get update -yqq \
     libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0
 
 # Install dotnet repository
-# https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current
-RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5972698f-ba44-4664-9c50-bdc69ca70fb7/1cf7d94425d8dd4d5789dfa978d61475/dotnet-sdk-5.0.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \
+RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5fcb98bb-21e1-47a5-bb8e-bb25f41a3e52/04811d5d05b7e694f040d2a13c1aae4c/dotnet-sdk-6.0.100-rc.1.21463.6-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

+ 1 - 3
deployment/Dockerfile.ubuntu.arm64

@@ -2,7 +2,6 @@ FROM ubuntu:bionic
 # Docker build arguments
 ARG SOURCE_DIR=/jellyfin
 ARG ARTIFACT_DIR=/dist
-ARG SDK_VERSION=5.0
 # Docker run environment
 ENV SOURCE_DIR=/jellyfin
 ENV ARTIFACT_DIR=/dist
@@ -17,8 +16,7 @@ RUN apt-get update -yqq \
     mmv build-essential lsb-release
 
 # Install dotnet repository
-# https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current
-RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5972698f-ba44-4664-9c50-bdc69ca70fb7/1cf7d94425d8dd4d5789dfa978d61475/dotnet-sdk-5.0.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \
+RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5fcb98bb-21e1-47a5-bb8e-bb25f41a3e52/04811d5d05b7e694f040d2a13c1aae4c/dotnet-sdk-6.0.100-rc.1.21463.6-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

+ 1 - 3
deployment/Dockerfile.ubuntu.armhf

@@ -2,7 +2,6 @@ FROM ubuntu:bionic
 # Docker build arguments
 ARG SOURCE_DIR=/jellyfin
 ARG ARTIFACT_DIR=/dist
-ARG SDK_VERSION=5.0
 # Docker run environment
 ENV SOURCE_DIR=/jellyfin
 ENV ARTIFACT_DIR=/dist
@@ -17,8 +16,7 @@ RUN apt-get update -yqq \
     mmv build-essential lsb-release
 
 # Install dotnet repository
-# https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current
-RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5972698f-ba44-4664-9c50-bdc69ca70fb7/1cf7d94425d8dd4d5789dfa978d61475/dotnet-sdk-5.0.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \
+RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5fcb98bb-21e1-47a5-bb8e-bb25f41a3e52/04811d5d05b7e694f040d2a13c1aae4c/dotnet-sdk-6.0.100-rc.1.21463.6-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

+ 1 - 1
deployment/Dockerfile.windows.amd64

@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim
+FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim
 # Docker build arguments
 ARG SOURCE_DIR=/jellyfin
 ARG ARTIFACT_DIR=/dist

+ 19 - 0
deployment/build.centos.amd64

@@ -8,6 +8,16 @@ set -o xtrace
 # Move to source directory
 pushd ${SOURCE_DIR}
 
+if [[ ${IS_DOCKER} == YES ]]; then
+    # Remove BuildRequires for dotnet-sdk-6.0, since it's installed manually
+    pushd fedora
+
+    cp -a jellyfin.spec /tmp/spec.orig
+    sed -i 's/BuildRequires:  dotnet/# BuildRequires:  dotnet/' jellyfin.spec
+
+    popd
+fi
+
 # Modify changelog to unstable configuration if IS_UNSTABLE
 if [[ ${IS_UNSTABLE} == 'yes' ]]; then
     pushd fedora
@@ -37,4 +47,13 @@ fi
 
 rm -f fedora/jellyfin*.tar.gz
 
+if [[ ${IS_DOCKER} == YES ]]; then
+    pushd fedora
+
+    cp -a /tmp/spec.orig jellyfin.spec
+    chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+    
+    popd
+fi
+
 popd

+ 2 - 2
deployment/build.debian.amd64

@@ -9,9 +9,9 @@ set -o xtrace
 pushd ${SOURCE_DIR}
 
 if [[ ${IS_DOCKER} == YES ]]; then
-    # Remove build-dep for dotnet-sdk-5.0, since it's installed manually
+    # Remove build-dep for dotnet-sdk-6.0, since it's installed manually
     cp -a debian/control /tmp/control.orig
-    sed -i '/dotnet-sdk-5.0,/d' debian/control
+    sed -i '/dotnet-sdk-6.0,/d' debian/control
 fi
 
 # Modify changelog to unstable configuration if IS_UNSTABLE

+ 2 - 2
deployment/build.debian.arm64

@@ -9,9 +9,9 @@ set -o xtrace
 pushd ${SOURCE_DIR}
 
 if [[ ${IS_DOCKER} == YES ]]; then
-    # Remove build-dep for dotnet-sdk-5.0, since it's installed manually
+    # Remove build-dep for dotnet-sdk-6.0, since it's installed manually
     cp -a debian/control /tmp/control.orig
-    sed -i '/dotnet-sdk-5.0,/d' debian/control
+    sed -i '/dotnet-sdk-6.0,/d' debian/control
 fi
 
 # Modify changelog to unstable configuration if IS_UNSTABLE

+ 2 - 2
deployment/build.debian.armhf

@@ -9,9 +9,9 @@ set -o xtrace
 pushd ${SOURCE_DIR}
 
 if [[ ${IS_DOCKER} == YES ]]; then
-    # Remove build-dep for dotnet-sdk-5.0, since it's installed manually
+    # Remove build-dep for dotnet-sdk-6.0, since it's installed manually
     cp -a debian/control /tmp/control.orig
-    sed -i '/dotnet-sdk-5.0,/d' debian/control
+    sed -i '/dotnet-sdk-6.0,/d' debian/control
 fi
 
 # Modify changelog to unstable configuration if IS_UNSTABLE

+ 19 - 0
deployment/build.fedora.amd64

@@ -8,6 +8,16 @@ set -o xtrace
 # Move to source directory
 pushd ${SOURCE_DIR}
 
+if [[ ${IS_DOCKER} == YES ]]; then
+    # Remove BuildRequires for dotnet-sdk-6.0, since it's installed manually
+    pushd fedora
+
+    cp -a jellyfin.spec /tmp/spec.orig
+    sed -i 's/BuildRequires:  dotnet/# BuildRequires:  dotnet/' jellyfin.spec
+
+    popd
+fi
+
 # Modify changelog to unstable configuration if IS_UNSTABLE
 if [[ ${IS_UNSTABLE} == 'yes' ]]; then
     pushd fedora
@@ -37,4 +47,13 @@ fi
 
 rm -f fedora/jellyfin*.tar.gz
 
+if [[ ${IS_DOCKER} == YES ]]; then
+    pushd fedora
+
+    cp -a /tmp/spec.orig jellyfin.spec
+    chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+    
+    popd
+fi
+
 popd

+ 2 - 2
deployment/build.ubuntu.amd64

@@ -9,9 +9,9 @@ set -o xtrace
 pushd ${SOURCE_DIR}
 
 if [[ ${IS_DOCKER} == YES ]]; then
-    # Remove build-dep for dotnet-sdk-5.0, since it's installed manually
+    # Remove build-dep for dotnet-sdk-6.0, since it's installed manually
     cp -a debian/control /tmp/control.orig
-    sed -i '/dotnet-sdk-5.0,/d' debian/control
+    sed -i '/dotnet-sdk-6.0,/d' debian/control
 fi
 
 # Modify changelog to unstable configuration if IS_UNSTABLE

+ 2 - 2
deployment/build.ubuntu.arm64

@@ -9,9 +9,9 @@ set -o xtrace
 pushd ${SOURCE_DIR}
 
 if [[ ${IS_DOCKER} == YES ]]; then
-    # Remove build-dep for dotnet-sdk-5.0, since it's installed manually
+    # Remove build-dep for dotnet-sdk-6.0, since it's installed manually
     cp -a debian/control /tmp/control.orig
-    sed -i '/dotnet-sdk-5.0,/d' debian/control
+    sed -i '/dotnet-sdk-6.0,/d' debian/control
 fi
 
 # Modify changelog to unstable configuration if IS_UNSTABLE

+ 2 - 2
deployment/build.ubuntu.armhf

@@ -9,9 +9,9 @@ set -o xtrace
 pushd ${SOURCE_DIR}
 
 if [[ ${IS_DOCKER} == YES ]]; then
-    # Remove build-dep for dotnet-sdk-5.0, since it's installed manually
+    # Remove build-dep for dotnet-sdk-6.0, since it's installed manually
     cp -a debian/control /tmp/control.orig
-    sed -i '/dotnet-sdk-5.0,/d' debian/control
+    sed -i '/dotnet-sdk-6.0,/d' debian/control
 fi
 
 # Modify changelog to unstable configuration if IS_UNSTABLE

+ 1 - 1
fedora/jellyfin.spec

@@ -27,7 +27,7 @@ BuildRequires:  libcurl-devel, fontconfig-devel, freetype-devel, openssl-devel,
 # Requirements not packaged in main repos
 # COPR @dotnet-sig/dotnet or
 # https://packages.microsoft.com/rhel/7/prod/
-BuildRequires:  dotnet-runtime-5.0, dotnet-sdk-5.0
+BuildRequires:  dotnet-runtime-6.0, dotnet-sdk-6.0
 Requires: %{name}-server = %{version}-%{release}, %{name}-web = %{version}-%{release}
 # Disable Automatic Dependency Processing
 AutoReqProv:    no

+ 2 - 2
src/Jellyfin.Extensions/Jellyfin.Extensions.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <PublishRepositoryUrl>true</PublishRepositoryUrl>
@@ -22,7 +22,7 @@
     <!-- Include all symbols in the main nupkg until Azure Artifact Feed starts supporting ingesting NuGet symbol packages. -->
     <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
   </PropertyGroup>
-  
+
   <ItemGroup>
     <Compile Include="../../SharedVersion.cs" />
   </ItemGroup>

+ 1 - 1
src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs

@@ -44,7 +44,7 @@ namespace Jellyfin.Extensions.Json.Converters
                 {
                     try
                     {
-                        parsedValues[i] = _typeConverter.ConvertFrom(stringEntries[i].Trim());
+                        parsedValues[i] = _typeConverter.ConvertFrom(stringEntries[i].Trim()) ?? throw new FormatException();
                         convertedCount++;
                     }
                     catch (FormatException)

+ 1 - 1
tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj

@@ -6,7 +6,7 @@
   </PropertyGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <IsPackable>false</IsPackable>
     <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>

+ 1 - 1
tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj

@@ -6,7 +6,7 @@
   </PropertyGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <IsPackable>false</IsPackable>
     <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>

+ 1 - 1
tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj

@@ -6,7 +6,7 @@
   </PropertyGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <IsPackable>false</IsPackable>
     <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>

+ 1 - 1
tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <IsPackable>false</IsPackable>
     <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>

+ 1 - 1
tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <IsPackable>false</IsPackable>
     <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>

+ 1 - 1
tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj

@@ -6,7 +6,7 @@
   </PropertyGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <IsPackable>false</IsPackable>
     <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>

+ 1 - 1
tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <IsPackable>false</IsPackable>
     <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>

+ 1 - 1
tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj

@@ -6,7 +6,7 @@
   </PropertyGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <IsPackable>false</IsPackable>
     <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>

+ 1 - 1
tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj

@@ -6,7 +6,7 @@
   </PropertyGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <IsPackable>false</IsPackable>
     <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>

+ 1 - 1
tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <IsPackable>false</IsPackable>
     <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>

+ 1 - 1
tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj

@@ -6,7 +6,7 @@
   </PropertyGroup>
 
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <IsPackable>false</IsPackable>
     <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
     <RootNamespace>Jellyfin.Server.Implementations.Tests</RootNamespace>

+ 1 - 0
tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs

@@ -21,6 +21,7 @@ namespace Jellyfin.Server.Integration.Tests
         [InlineData("a=1", "a=1")] // won't be processed as it has a value
         [InlineData("a%3D1%26b%3D2%26c%3D3", "a=1&b=2&c=3")] // will be processed.
         [InlineData("a=b&a=c", "a=b")]
+        [InlineData("a%3D1", "a=1")]
         [InlineData("a%3Db%26a%3Dc", "a=b")]
         public async Task Ensure_Decoding_Of_Urls_Is_Working(string sourceUrl, string unencodedUrl)
         {

+ 1 - 1
tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj

@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
     <IsPackable>false</IsPackable>
     <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.