Explorar o código

Merge branch 'master' into comparisons

BaronGreenback %!s(int64=4) %!d(string=hai) anos
pai
achega
97c2c523a8
Modificáronse 100 ficheiros con 291 adicións e 230 borrados
  1. 0 2
      .github/workflows/automation.yml
  2. 2 0
      Emby.Dlna/Configuration/DlnaOptions.cs
  3. 0 1
      Emby.Dlna/ConfigurationExtension.cs
  4. 2 0
      Emby.Dlna/ContentDirectory/ContentDirectoryService.cs
  5. 2 0
      Emby.Dlna/ContentDirectory/ControlHandler.cs
  6. 2 0
      Emby.Dlna/ControlRequest.cs
  7. 2 0
      Emby.Dlna/ControlResponse.cs
  8. 2 0
      Emby.Dlna/Didl/DidlBuilder.cs
  9. 1 1
      Emby.Dlna/Didl/StringWriterWithEncoding.cs
  10. 0 1
      Emby.Dlna/DlnaConfigurationFactory.cs
  11. 2 0
      Emby.Dlna/DlnaManager.cs
  12. 1 0
      Emby.Dlna/Emby.Dlna.csproj
  13. 2 0
      Emby.Dlna/EventSubscriptionResponse.cs
  14. 2 0
      Emby.Dlna/Eventing/DlnaEventManager.cs
  15. 2 0
      Emby.Dlna/Eventing/EventSubscription.cs
  16. 2 0
      Emby.Dlna/Main/DlnaEntryPoint.cs
  17. 2 0
      Emby.Dlna/PlayTo/Device.cs
  18. 2 0
      Emby.Dlna/PlayTo/DeviceInfo.cs
  19. 2 0
      Emby.Dlna/PlayTo/MediaChangedEventArgs.cs
  20. 2 0
      Emby.Dlna/PlayTo/PlayToController.cs
  21. 2 0
      Emby.Dlna/PlayTo/PlayToManager.cs
  22. 2 0
      Emby.Dlna/PlayTo/PlaybackProgressEventArgs.cs
  23. 2 0
      Emby.Dlna/PlayTo/PlaybackStartEventArgs.cs
  24. 2 0
      Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs
  25. 2 0
      Emby.Dlna/PlayTo/PlaylistItem.cs
  26. 2 0
      Emby.Dlna/PlayTo/PlaylistItemFactory.cs
  27. 2 0
      Emby.Dlna/PlayTo/SsdpHttpClient.cs
  28. 7 7
      Emby.Dlna/PlayTo/TransportCommands.cs
  29. 2 0
      Emby.Dlna/PlayTo/uBaseObject.cs
  30. 2 1
      Emby.Dlna/Server/DescriptionXmlBuilder.cs
  31. 2 2
      Emby.Dlna/Service/BaseControlHandler.cs
  32. 2 0
      Emby.Dlna/Ssdp/DeviceDiscovery.cs
  33. 3 3
      Emby.Dlna/Ssdp/SsdpExtensions.cs
  34. 5 0
      Emby.Server.Implementations/Library/ResolverHelper.cs
  35. 3 4
      Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
  36. 7 7
      Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
  37. 12 22
      Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
  38. 4 6
      Emby.Server.Implementations/Localization/LocalizationManager.cs
  39. 3 2
      Jellyfin.Api/Auth/BaseAuthorizationHandler.cs
  40. 6 0
      Jellyfin.Api/Controllers/ConfigurationController.cs
  41. 1 1
      Jellyfin.Api/Controllers/LibraryController.cs
  42. 1 4
      Jellyfin.Api/Helpers/HlsHelpers.cs
  43. 2 0
      MediaBrowser.Common/Configuration/ConfigurationStore.cs
  44. 1 0
      MediaBrowser.Common/Configuration/ConfigurationUpdateEventArgs.cs
  45. 2 0
      MediaBrowser.Common/Configuration/IApplicationPaths.cs
  46. 0 1
      MediaBrowser.Common/Cryptography/PasswordHash.cs
  47. 2 2
      MediaBrowser.Common/Events/EventHelper.cs
  48. 0 2
      MediaBrowser.Common/Extensions/BaseExtensions.cs
  49. 0 2
      MediaBrowser.Common/Extensions/CopyToExtensions.cs
  50. 1 1
      MediaBrowser.Common/Extensions/HttpContextExtensions.cs
  51. 0 2
      MediaBrowser.Common/Extensions/MethodNotAllowedException.cs
  52. 0 2
      MediaBrowser.Common/Extensions/ProcessExtensions.cs
  53. 0 1
      MediaBrowser.Common/Extensions/RateLimitExceededException.cs
  54. 0 2
      MediaBrowser.Common/Extensions/ResourceNotFoundException.cs
  55. 0 2
      MediaBrowser.Common/Extensions/ShuffleExtensions.cs
  56. 1 1
      MediaBrowser.Common/Extensions/SplitStringExtensions.cs
  57. 17 5
      MediaBrowser.Common/Extensions/StreamExtensions.cs
  58. 2 0
      MediaBrowser.Common/IApplicationHost.cs
  59. 3 54
      MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverter.cs
  60. 2 2
      MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs
  61. 81 0
      MediaBrowser.Common/Json/Converters/JsonDelimitedArrayConverter.cs
  62. 3 3
      MediaBrowser.Common/Json/Converters/JsonNullableStructConverterFactory.cs
  63. 12 6
      MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStringConverter.cs
  64. 3 54
      MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverter.cs
  65. 2 2
      MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs
  66. 4 4
      MediaBrowser.Common/Json/Converters/JsonStringConverter.cs
  67. 1 1
      MediaBrowser.Common/Json/Converters/JsonVersionConverter.cs
  68. 1 0
      MediaBrowser.Common/MediaBrowser.Common.csproj
  69. 0 1
      MediaBrowser.Common/Net/INetworkManager.cs
  70. 0 1
      MediaBrowser.Common/Net/IPHost.cs
  71. 0 1
      MediaBrowser.Common/Net/IPNetAddress.cs
  72. 0 1
      MediaBrowser.Common/Net/IPObject.cs
  73. 2 0
      MediaBrowser.Common/Plugins/BasePlugin.cs
  74. 2 0
      MediaBrowser.Common/Plugins/BasePluginOfT.cs
  75. 2 0
      MediaBrowser.Common/Plugins/IPlugin.cs
  76. 0 2
      MediaBrowser.Common/Plugins/IPluginManager.cs
  77. 0 1
      MediaBrowser.Common/Plugins/LocalPlugin.cs
  78. 0 2
      MediaBrowser.Common/Plugins/PluginManifest.cs
  79. 2 2
      MediaBrowser.Common/Progress/ActionableProgress.cs
  80. 1 1
      MediaBrowser.Common/Progress/SimpleProgress.cs
  81. 1 3
      MediaBrowser.Common/Providers/ProviderIdParsers.cs
  82. 0 2
      MediaBrowser.Common/Updates/IInstallationManager.cs
  83. 2 0
      MediaBrowser.Common/Updates/InstallationEventArgs.cs
  84. 1 0
      MediaBrowser.Common/Updates/InstallationFailedEventArgs.cs
  85. 2 0
      MediaBrowser.Controller/Authentication/AuthenticationResult.cs
  86. 2 0
      MediaBrowser.Controller/Authentication/IAuthenticationProvider.cs
  87. 2 0
      MediaBrowser.Controller/Authentication/IPasswordResetProvider.cs
  88. 2 0
      MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs
  89. 2 0
      MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs
  90. 2 0
      MediaBrowser.Controller/Channels/Channel.cs
  91. 2 0
      MediaBrowser.Controller/Channels/ChannelItemInfo.cs
  92. 2 0
      MediaBrowser.Controller/Channels/ChannelItemResult.cs
  93. 2 0
      MediaBrowser.Controller/Channels/ChannelSearchInfo.cs
  94. 2 0
      MediaBrowser.Controller/Channels/IChannel.cs
  95. 2 0
      MediaBrowser.Controller/Channels/IChannelManager.cs
  96. 2 0
      MediaBrowser.Controller/Channels/IHasCacheKey.cs
  97. 2 0
      MediaBrowser.Controller/Channels/ISearchableChannel.cs
  98. 2 0
      MediaBrowser.Controller/Channels/InternalChannelFeatures.cs
  99. 2 0
      MediaBrowser.Controller/Channels/InternalChannelItemQuery.cs
  100. 2 0
      MediaBrowser.Controller/Collections/CollectionCreationOptions.cs

+ 0 - 2
.github/workflows/automation.yml

@@ -2,8 +2,6 @@ name: Automation
 
 
 on:
 on:
   pull_request:
   pull_request:
-  issues:
-  issue_comment:
 
 
 jobs:
 jobs:
   main:
   main:

+ 2 - 0
Emby.Dlna/Configuration/DlnaOptions.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 namespace Emby.Dlna.Configuration
 namespace Emby.Dlna.Configuration

+ 0 - 1
Emby.Dlna/ConfigurationExtension.cs

@@ -1,4 +1,3 @@
-#nullable enable
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using Emby.Dlna.Configuration;
 using Emby.Dlna.Configuration;

+ 2 - 0
Emby.Dlna/ContentDirectory/ContentDirectoryService.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
Emby.Dlna/ContentDirectory/ControlHandler.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Globalization;
 using System.Globalization;

+ 2 - 0
Emby.Dlna/ControlRequest.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System.IO;
 using System.IO;

+ 2 - 0
Emby.Dlna/ControlResponse.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System.Collections.Generic;
 using System.Collections.Generic;

+ 2 - 0
Emby.Dlna/Didl/DidlBuilder.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 1 - 1
Emby.Dlna/Didl/StringWriterWithEncoding.cs

@@ -9,7 +9,7 @@ namespace Emby.Dlna.Didl
 {
 {
     public class StringWriterWithEncoding : StringWriter
     public class StringWriterWithEncoding : StringWriter
     {
     {
-        private readonly Encoding _encoding;
+        private readonly Encoding? _encoding;
 
 
         public StringWriterWithEncoding()
         public StringWriterWithEncoding()
         {
         {

+ 0 - 1
Emby.Dlna/DlnaConfigurationFactory.cs

@@ -1,4 +1,3 @@
-#nullable enable
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System.Collections.Generic;
 using System.Collections.Generic;

+ 2 - 0
Emby.Dlna/DlnaManager.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

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

@@ -21,6 +21,7 @@
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
   </PropertyGroup>
 
 
   <!-- Code Analyzers-->
   <!-- Code Analyzers-->

+ 2 - 0
Emby.Dlna/EventSubscriptionResponse.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System.Collections.Generic;
 using System.Collections.Generic;

+ 2 - 0
Emby.Dlna/Eventing/DlnaEventManager.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
Emby.Dlna/Eventing/EventSubscription.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
Emby.Dlna/Main/DlnaEntryPoint.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
Emby.Dlna/PlayTo/Device.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
Emby.Dlna/PlayTo/DeviceInfo.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System.Collections.Generic;
 using System.Collections.Generic;

+ 2 - 0
Emby.Dlna/PlayTo/MediaChangedEventArgs.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
Emby.Dlna/PlayTo/PlayToController.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
Emby.Dlna/PlayTo/PlayToManager.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
Emby.Dlna/PlayTo/PlaybackProgressEventArgs.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
Emby.Dlna/PlayTo/PlaybackStartEventArgs.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
Emby.Dlna/PlayTo/PlaylistItem.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Dlna;

+ 2 - 0
Emby.Dlna/PlayTo/PlaylistItemFactory.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System.IO;
 using System.IO;

+ 2 - 0
Emby.Dlna/PlayTo/SsdpHttpClient.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 7 - 7
Emby.Dlna/PlayTo/TransportCommands.cs

@@ -46,7 +46,7 @@ namespace Emby.Dlna.PlayTo
         {
         {
             var serviceAction = new ServiceAction
             var serviceAction = new ServiceAction
             {
             {
-                Name = container.GetValue(UPnpNamespaces.Svc + "name"),
+                Name = container.GetValue(UPnpNamespaces.Svc + "name") ?? string.Empty,
             };
             };
 
 
             var argumentList = serviceAction.ArgumentList;
             var argumentList = serviceAction.ArgumentList;
@@ -68,9 +68,9 @@ namespace Emby.Dlna.PlayTo
 
 
             return new Argument
             return new Argument
             {
             {
-                Name = container.GetValue(UPnpNamespaces.Svc + "name"),
-                Direction = container.GetValue(UPnpNamespaces.Svc + "direction"),
-                RelatedStateVariable = container.GetValue(UPnpNamespaces.Svc + "relatedStateVariable")
+                Name = container.GetValue(UPnpNamespaces.Svc + "name") ?? string.Empty,
+                Direction = container.GetValue(UPnpNamespaces.Svc + "direction") ?? string.Empty,
+                RelatedStateVariable = container.GetValue(UPnpNamespaces.Svc + "relatedStateVariable") ?? string.Empty
             };
             };
         }
         }
 
 
@@ -89,8 +89,8 @@ namespace Emby.Dlna.PlayTo
 
 
             return new StateVariable
             return new StateVariable
             {
             {
-                Name = container.GetValue(UPnpNamespaces.Svc + "name"),
-                DataType = container.GetValue(UPnpNamespaces.Svc + "dataType"),
+                Name = container.GetValue(UPnpNamespaces.Svc + "name") ?? string.Empty,
+                DataType = container.GetValue(UPnpNamespaces.Svc + "dataType") ?? string.Empty,
                 AllowedValues = allowedValues
                 AllowedValues = allowedValues
             };
             };
         }
         }
@@ -166,7 +166,7 @@ namespace Emby.Dlna.PlayTo
             return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamesapce, stateString);
             return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamesapce, stateString);
         }
         }
 
 
-        private string BuildArgumentXml(Argument argument, string value, string commandParameter = "")
+        private string BuildArgumentXml(Argument argument, string? value, string commandParameter = "")
         {
         {
             var state = StateVariables.FirstOrDefault(a => string.Equals(a.Name, argument.RelatedStateVariable, StringComparison.OrdinalIgnoreCase));
             var state = StateVariables.FirstOrDefault(a => string.Equals(a.Name, argument.RelatedStateVariable, StringComparison.OrdinalIgnoreCase));
 
 

+ 2 - 0
Emby.Dlna/PlayTo/uBaseObject.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

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

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

+ 2 - 2
Emby.Dlna/Service/BaseControlHandler.cs

@@ -47,7 +47,7 @@ namespace Emby.Dlna.Service
 
 
         private async Task<ControlResponse> ProcessControlRequestInternalAsync(ControlRequest request)
         private async Task<ControlResponse> ProcessControlRequestInternalAsync(ControlRequest request)
         {
         {
-            ControlRequestInfo requestInfo;
+            ControlRequestInfo? requestInfo = null;
 
 
             using (var streamReader = new StreamReader(request.InputXml, Encoding.UTF8))
             using (var streamReader = new StreamReader(request.InputXml, Encoding.UTF8))
             {
             {
@@ -151,7 +151,7 @@ namespace Emby.Dlna.Service
 
 
         private async Task<ControlRequestInfo> ParseBodyTagAsync(XmlReader reader)
         private async Task<ControlRequestInfo> ParseBodyTagAsync(XmlReader reader)
         {
         {
-            string namespaceURI = null, localName = null;
+            string? namespaceURI = null, localName = null;
 
 
             await reader.MoveToContentAsync().ConfigureAwait(false);
             await reader.MoveToContentAsync().ConfigureAwait(false);
             await reader.ReadAsync().ConfigureAwait(false);
             await reader.ReadAsync().ConfigureAwait(false);

+ 2 - 0
Emby.Dlna/Ssdp/DeviceDiscovery.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 3 - 3
Emby.Dlna/Ssdp/SsdpExtensions.cs

@@ -7,21 +7,21 @@ namespace Emby.Dlna.Ssdp
 {
 {
     public static class SsdpExtensions
     public static class SsdpExtensions
     {
     {
-        public static string GetValue(this XElement container, XName name)
+        public static string? GetValue(this XElement container, XName name)
         {
         {
             var node = container.Element(name);
             var node = container.Element(name);
 
 
             return node?.Value;
             return node?.Value;
         }
         }
 
 
-        public static string GetAttributeValue(this XElement container, XName name)
+        public static string? GetAttributeValue(this XElement container, XName name)
         {
         {
             var node = container.Attribute(name);
             var node = container.Attribute(name);
 
 
             return node?.Value;
             return node?.Value;
         }
         }
 
 
-        public static string GetDescendantValue(this XElement container, XName name)
+        public static string? GetDescendantValue(this XElement container, XName name)
             => container.Descendants(name).FirstOrDefault()?.Value;
             => container.Descendants(name).FirstOrDefault()?.Value;
     }
     }
 }
 }

+ 5 - 0
Emby.Server.Implementations/Library/ResolverHelper.cs

@@ -44,6 +44,11 @@ namespace Emby.Server.Implementations.Library
 
 
             // Make sure DateCreated and DateModified have values
             // Make sure DateCreated and DateModified have values
             var fileInfo = directoryService.GetFile(item.Path);
             var fileInfo = directoryService.GetFile(item.Path);
+            if (fileInfo == null)
+            {
+                throw new FileNotFoundException("Can't find item path.", item.Path);
+            }
+
             SetDateCreated(item, fileInfo);
             SetDateCreated(item, fileInfo);
 
 
             EnsureName(item, fileInfo);
             EnsureName(item, fileInfo);

+ 3 - 4
Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs

@@ -10,6 +10,7 @@ using System.Text.Json;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Json;
 using MediaBrowser.Common.Json;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Configuration;
@@ -307,13 +308,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
             {
             {
                 using (var reader = new StreamReader(source))
                 using (var reader = new StreamReader(source))
                 {
                 {
-                    while (!reader.EndOfStream)
+                    await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false))
                     {
                     {
-                        var line = await reader.ReadLineAsync().ConfigureAwait(false);
-
                         var bytes = Encoding.UTF8.GetBytes(Environment.NewLine + line);
                         var bytes = Encoding.UTF8.GetBytes(Environment.NewLine + line);
 
 
-                        await target.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
+                        await target.WriteAsync(bytes.AsMemory()).ConfigureAwait(false);
                         await target.FlushAsync().ConfigureAwait(false);
                         await target.FlushAsync().ConfigureAwait(false);
                     }
                     }
                 }
                 }

+ 7 - 7
Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs

@@ -182,16 +182,16 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
             await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             using var sr = new StreamReader(stream, System.Text.Encoding.UTF8);
             using var sr = new StreamReader(stream, System.Text.Encoding.UTF8);
             var tuners = new List<LiveTvTunerInfo>();
             var tuners = new List<LiveTvTunerInfo>();
-            while (!sr.EndOfStream)
+            await foreach (var line in sr.ReadAllLinesAsync().ConfigureAwait(false))
             {
             {
-                string line = StripXML(sr.ReadLine());
-                if (line.Contains("Channel", StringComparison.Ordinal))
+                string stripedLine = StripXML(line);
+                if (stripedLine.Contains("Channel", StringComparison.Ordinal))
                 {
                 {
                     LiveTvTunerStatus status;
                     LiveTvTunerStatus status;
-                    var index = line.IndexOf("Channel", StringComparison.OrdinalIgnoreCase);
-                    var name = line.Substring(0, index - 1);
-                    var currentChannel = line.Substring(index + 7);
-                    if (currentChannel != "none")
+                    var index = stripedLine.IndexOf("Channel", StringComparison.OrdinalIgnoreCase);
+                    var name = stripedLine.Substring(0, index - 1);
+                    var currentChannel = stripedLine.Substring(index + 7);
+                    if (string.Equals(currentChannel, "none", StringComparison.Ordinal))
                     {
                     {
                         status = LiveTvTunerStatus.LiveTv;
                         status = LiveTvTunerStatus.LiveTv;
                     }
                     }

+ 12 - 22
Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs

@@ -35,16 +35,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
             // Read the file and display it line by line.
             // Read the file and display it line by line.
             using (var reader = new StreamReader(await GetListingsStream(info, cancellationToken).ConfigureAwait(false)))
             using (var reader = new StreamReader(await GetListingsStream(info, cancellationToken).ConfigureAwait(false)))
             {
             {
-                return GetChannels(reader, channelIdPrefix, info.Id);
-            }
-        }
-
-        public List<ChannelInfo> ParseString(string text, string channelIdPrefix, string tunerHostId)
-        {
-            // Read the file and display it line by line.
-            using (var reader = new StringReader(text))
-            {
-                return GetChannels(reader, channelIdPrefix, tunerHostId);
+                return await GetChannelsAsync(reader, channelIdPrefix, info.Id).ConfigureAwait(false);
             }
             }
         }
         }
 
 
@@ -70,43 +61,42 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
 
 
         private const string ExtInfPrefix = "#EXTINF:";
         private const string ExtInfPrefix = "#EXTINF:";
 
 
-        private List<ChannelInfo> GetChannels(TextReader reader, string channelIdPrefix, string tunerHostId)
+        private async Task<List<ChannelInfo>> GetChannelsAsync(TextReader reader, string channelIdPrefix, string tunerHostId)
         {
         {
             var channels = new List<ChannelInfo>();
             var channels = new List<ChannelInfo>();
-            string line;
             string extInf = string.Empty;
             string extInf = string.Empty;
 
 
-            while ((line = reader.ReadLine()) != null)
+            await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false))
             {
             {
-                line = line.Trim();
-                if (string.IsNullOrWhiteSpace(line))
+                var trimmedLine = line.Trim();
+                if (string.IsNullOrWhiteSpace(trimmedLine))
                 {
                 {
                     continue;
                     continue;
                 }
                 }
 
 
-                if (line.StartsWith("#EXTM3U", StringComparison.OrdinalIgnoreCase))
+                if (trimmedLine.StartsWith("#EXTM3U", StringComparison.OrdinalIgnoreCase))
                 {
                 {
                     continue;
                     continue;
                 }
                 }
 
 
-                if (line.StartsWith(ExtInfPrefix, StringComparison.OrdinalIgnoreCase))
+                if (trimmedLine.StartsWith(ExtInfPrefix, StringComparison.OrdinalIgnoreCase))
                 {
                 {
-                    extInf = line.Substring(ExtInfPrefix.Length).Trim();
+                    extInf = trimmedLine.Substring(ExtInfPrefix.Length).Trim();
                     _logger.LogInformation("Found m3u channel: {0}", extInf);
                     _logger.LogInformation("Found m3u channel: {0}", extInf);
                 }
                 }
-                else if (!string.IsNullOrWhiteSpace(extInf) && !line.StartsWith('#'))
+                else if (!string.IsNullOrWhiteSpace(extInf) && !trimmedLine.StartsWith('#'))
                 {
                 {
-                    var channel = GetChannelnfo(extInf, tunerHostId, line);
+                    var channel = GetChannelnfo(extInf, tunerHostId, trimmedLine);
                     if (string.IsNullOrWhiteSpace(channel.Id))
                     if (string.IsNullOrWhiteSpace(channel.Id))
                     {
                     {
-                        channel.Id = channelIdPrefix + line.GetMD5().ToString("N", CultureInfo.InvariantCulture);
+                        channel.Id = channelIdPrefix + trimmedLine.GetMD5().ToString("N", CultureInfo.InvariantCulture);
                     }
                     }
                     else
                     else
                     {
                     {
                         channel.Id = channelIdPrefix + channel.Id.GetMD5().ToString("N", CultureInfo.InvariantCulture);
                         channel.Id = channelIdPrefix + channel.Id.GetMD5().ToString("N", CultureInfo.InvariantCulture);
                     }
                     }
 
 
-                    channel.Path = line;
+                    channel.Path = trimmedLine;
                     channels.Add(channel);
                     channels.Add(channel);
                     extInf = string.Empty;
                     extInf = string.Empty;
                 }
                 }

+ 4 - 6
Emby.Server.Implementations/Localization/LocalizationManager.cs

@@ -7,6 +7,7 @@ using System.Linq;
 using System.Reflection;
 using System.Reflection;
 using System.Text.Json;
 using System.Text.Json;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Json;
 using MediaBrowser.Common.Json;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
@@ -72,8 +73,7 @@ namespace Emby.Server.Implementations.Localization
                 using (var str = _assembly.GetManifestResourceStream(resource))
                 using (var str = _assembly.GetManifestResourceStream(resource))
                 using (var reader = new StreamReader(str))
                 using (var reader = new StreamReader(str))
                 {
                 {
-                    string line;
-                    while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) != null)
+                    await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false))
                     {
                     {
                         if (string.IsNullOrWhiteSpace(line))
                         if (string.IsNullOrWhiteSpace(line))
                         {
                         {
@@ -118,10 +118,8 @@ namespace Emby.Server.Implementations.Localization
             using (var stream = _assembly.GetManifestResourceStream(ResourcePath))
             using (var stream = _assembly.GetManifestResourceStream(ResourcePath))
             using (var reader = new StreamReader(stream))
             using (var reader = new StreamReader(stream))
             {
             {
-                while (!reader.EndOfStream)
+                await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false))
                 {
                 {
-                    var line = await reader.ReadLineAsync().ConfigureAwait(false);
-
                     if (string.IsNullOrWhiteSpace(line))
                     if (string.IsNullOrWhiteSpace(line))
                     {
                     {
                         continue;
                         continue;
@@ -179,7 +177,7 @@ namespace Emby.Server.Implementations.Localization
         /// <inheritdoc />
         /// <inheritdoc />
         public IEnumerable<CountryInfo> GetCountries()
         public IEnumerable<CountryInfo> GetCountries()
         {
         {
-            StreamReader reader = new StreamReader(_assembly.GetManifestResourceStream("Emby.Server.Implementations.Localization.countries.json"));
+            using StreamReader reader = new StreamReader(_assembly.GetManifestResourceStream("Emby.Server.Implementations.Localization.countries.json"));
 
 
             return JsonSerializer.Deserialize<IEnumerable<CountryInfo>>(reader.ReadToEnd(), _jsonOptions);
             return JsonSerializer.Deserialize<IEnumerable<CountryInfo>>(reader.ReadToEnd(), _jsonOptions);
         }
         }

+ 3 - 2
Jellyfin.Api/Auth/BaseAuthorizationHandler.cs

@@ -77,8 +77,9 @@ namespace Jellyfin.Api.Auth
                 return false;
                 return false;
             }
             }
 
 
-            var ip = _httpContextAccessor.HttpContext.GetNormalizedRemoteIp();
-            var isInLocalNetwork = _networkManager.IsInLocalNetwork(ip);
+            var isInLocalNetwork = _httpContextAccessor.HttpContext != null
+                && _networkManager.IsInLocalNetwork(_httpContextAccessor.HttpContext.GetNormalizedRemoteIp());
+
             // User cannot access remotely and user is remote
             // User cannot access remotely and user is remote
             if (!user.HasPermission(PermissionKind.EnableRemoteAccess) && !isInLocalNetwork)
             if (!user.HasPermission(PermissionKind.EnableRemoteAccess) && !isInLocalNetwork)
             {
             {

+ 6 - 0
Jellyfin.Api/Controllers/ConfigurationController.cs

@@ -1,3 +1,4 @@
+using System;
 using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations;
 using System.Net.Mime;
 using System.Net.Mime;
 using System.Text.Json;
 using System.Text.Json;
@@ -94,6 +95,11 @@ namespace Jellyfin.Api.Controllers
         {
         {
             var configurationType = _configurationManager.GetConfigurationType(key);
             var configurationType = _configurationManager.GetConfigurationType(key);
             var configuration = await JsonSerializer.DeserializeAsync(Request.Body, configurationType, _serializerOptions).ConfigureAwait(false);
             var configuration = await JsonSerializer.DeserializeAsync(Request.Body, configurationType, _serializerOptions).ConfigureAwait(false);
+            if (configuration == null)
+            {
+                throw new ArgumentException("Body doesn't contain a valid configuration");
+            }
+
             _configurationManager.SaveConfiguration(key, configuration);
             _configurationManager.SaveConfiguration(key, configuration);
             return NoContent();
             return NoContent();
         }
         }

+ 1 - 1
Jellyfin.Api/Controllers/LibraryController.cs

@@ -600,7 +600,7 @@ namespace Jellyfin.Api.Controllers
         {
         {
             foreach (var item in dto.Updates)
             foreach (var item in dto.Updates)
             {
             {
-                _libraryMonitor.ReportFileSystemChanged(item.Path);
+                _libraryMonitor.ReportFileSystemChanged(item.Path ?? throw new ArgumentException("Item path can't be null."));
             }
             }
 
 
             return NoContent();
             return NoContent();

+ 1 - 4
Jellyfin.Api/Helpers/HlsHelpers.cs

@@ -118,10 +118,7 @@ namespace Jellyfin.Api.Helpers
         /// <returns>The playlist text as a string.</returns>
         /// <returns>The playlist text as a string.</returns>
         public static string GetLivePlaylistText(string path, StreamState state)
         public static string GetLivePlaylistText(string path, StreamState state)
         {
         {
-            using var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
-            using var reader = new StreamReader(stream);
-
-            var text = reader.ReadToEnd();
+            var text = File.ReadAllText(path);
 
 
             var segmentFormat = EncodingHelper.GetSegmentFileExtension(state.Request.SegmentContainer).TrimStart('.');
             var segmentFormat = EncodingHelper.GetSegmentFileExtension(state.Request.SegmentContainer).TrimStart('.');
             if (string.Equals(segmentFormat, "mp4", StringComparison.OrdinalIgnoreCase))
             if (string.Equals(segmentFormat, "mp4", StringComparison.OrdinalIgnoreCase))

+ 2 - 0
MediaBrowser.Common/Configuration/ConfigurationStore.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 using System;
 using System;
 
 
 namespace MediaBrowser.Common.Configuration
 namespace MediaBrowser.Common.Configuration

+ 1 - 0
MediaBrowser.Common/Configuration/ConfigurationUpdateEventArgs.cs

@@ -1,3 +1,4 @@
+#nullable disable
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
MediaBrowser.Common/Configuration/IApplicationPaths.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 namespace MediaBrowser.Common.Configuration
 namespace MediaBrowser.Common.Configuration
 {
 {
     /// <summary>
     /// <summary>

+ 0 - 1
MediaBrowser.Common/Cryptography/PasswordHash.cs

@@ -1,5 +1,4 @@
 #pragma warning disable CS1591
 #pragma warning disable CS1591
-#nullable enable
 
 
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;

+ 2 - 2
MediaBrowser.Common/Events/EventHelper.cs

@@ -17,7 +17,7 @@ namespace MediaBrowser.Common.Events
         /// <param name="sender">The sender.</param>
         /// <param name="sender">The sender.</param>
         /// <param name="args">The <see cref="EventArgs" /> instance containing the event data.</param>
         /// <param name="args">The <see cref="EventArgs" /> instance containing the event data.</param>
         /// <param name="logger">The logger.</param>
         /// <param name="logger">The logger.</param>
-        public static void QueueEventIfNotNull(EventHandler handler, object sender, EventArgs args, ILogger logger)
+        public static void QueueEventIfNotNull(EventHandler? handler, object sender, EventArgs args, ILogger logger)
         {
         {
             if (handler != null)
             if (handler != null)
             {
             {
@@ -43,7 +43,7 @@ namespace MediaBrowser.Common.Events
         /// <param name="sender">The sender.</param>
         /// <param name="sender">The sender.</param>
         /// <param name="args">The args.</param>
         /// <param name="args">The args.</param>
         /// <param name="logger">The logger.</param>
         /// <param name="logger">The logger.</param>
-        public static void QueueEventIfNotNull<T>(EventHandler<T> handler, object sender, T args, ILogger logger)
+        public static void QueueEventIfNotNull<T>(EventHandler<T>? handler, object sender, T args, ILogger logger)
         {
         {
             if (handler != null)
             if (handler != null)
             {
             {

+ 0 - 2
MediaBrowser.Common/Extensions/BaseExtensions.cs

@@ -1,5 +1,3 @@
-#nullable enable
-
 using System;
 using System;
 using System.Security.Cryptography;
 using System.Security.Cryptography;
 using System.Text;
 using System.Text;

+ 0 - 2
MediaBrowser.Common/Extensions/CopyToExtensions.cs

@@ -1,5 +1,3 @@
-#nullable enable
-
 using System.Collections.Generic;
 using System.Collections.Generic;
 
 
 namespace MediaBrowser.Common.Extensions
 namespace MediaBrowser.Common.Extensions

+ 1 - 1
MediaBrowser.Common/Extensions/HttpContextExtensions.cs

@@ -17,7 +17,7 @@ namespace MediaBrowser.Common.Extensions
         {
         {
             return (context.Connection.LocalIpAddress == null
             return (context.Connection.LocalIpAddress == null
                     && context.Connection.RemoteIpAddress == null)
                     && context.Connection.RemoteIpAddress == null)
-                   || context.Connection.LocalIpAddress.Equals(context.Connection.RemoteIpAddress);
+                   || Equals(context.Connection.LocalIpAddress, context.Connection.RemoteIpAddress);
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 0 - 2
MediaBrowser.Common/Extensions/MethodNotAllowedException.cs

@@ -1,5 +1,3 @@
-#nullable enable
-
 using System;
 using System;
 
 
 namespace MediaBrowser.Common.Extensions
 namespace MediaBrowser.Common.Extensions

+ 0 - 2
MediaBrowser.Common/Extensions/ProcessExtensions.cs

@@ -1,5 +1,3 @@
-#nullable enable
-
 using System;
 using System;
 using System.Diagnostics;
 using System.Diagnostics;
 using System.Threading;
 using System.Threading;

+ 0 - 1
MediaBrowser.Common/Extensions/RateLimitExceededException.cs

@@ -1,4 +1,3 @@
-#nullable enable
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 0 - 2
MediaBrowser.Common/Extensions/ResourceNotFoundException.cs

@@ -1,5 +1,3 @@
-#nullable enable
-
 using System;
 using System;
 
 
 namespace MediaBrowser.Common.Extensions
 namespace MediaBrowser.Common.Extensions

+ 0 - 2
MediaBrowser.Common/Extensions/ShuffleExtensions.cs

@@ -1,5 +1,3 @@
-#nullable enable
-
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 
 

+ 1 - 1
MediaBrowser.Common/Extensions/SplitStringExtensions.cs

@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 SOFTWARE.
  */
  */
-#nullable enable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 #pragma warning disable CA1034
 #pragma warning disable CA1034
 using System;
 using System;

+ 17 - 5
MediaBrowser.Common/Extensions/StreamExtensions.cs

@@ -1,5 +1,3 @@
-#nullable enable
-
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
@@ -35,11 +33,11 @@ namespace MediaBrowser.Common.Extensions
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Reads all lines in the <see cref="StreamReader" />.
+        /// Reads all lines in the <see cref="TextReader" />.
         /// </summary>
         /// </summary>
-        /// <param name="reader">The <see cref="StreamReader" /> to read from.</param>
+        /// <param name="reader">The <see cref="TextReader" /> to read from.</param>
         /// <returns>All lines in the stream.</returns>
         /// <returns>All lines in the stream.</returns>
-        public static IEnumerable<string> ReadAllLines(this StreamReader reader)
+        public static IEnumerable<string> ReadAllLines(this TextReader reader)
         {
         {
             string? line;
             string? line;
             while ((line = reader.ReadLine()) != null)
             while ((line = reader.ReadLine()) != null)
@@ -47,5 +45,19 @@ namespace MediaBrowser.Common.Extensions
                 yield return line;
                 yield return line;
             }
             }
         }
         }
+
+        /// <summary>
+        /// Reads all lines in the <see cref="TextReader" />.
+        /// </summary>
+        /// <param name="reader">The <see cref="TextReader" /> to read from.</param>
+        /// <returns>All lines in the stream.</returns>
+        public static async IAsyncEnumerable<string> ReadAllLinesAsync(this TextReader reader)
+        {
+            string? line;
+            while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) != null)
+            {
+                yield return line;
+            }
+        }
     }
     }
 }
 }

+ 2 - 0
MediaBrowser.Common/IApplicationHost.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Reflection;
 using System.Reflection;

+ 3 - 54
MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverter.cs

@@ -9,67 +9,16 @@ namespace MediaBrowser.Common.Json.Converters
     /// Convert comma delimited string to array of type.
     /// Convert comma delimited string to array of type.
     /// </summary>
     /// </summary>
     /// <typeparam name="T">Type to convert to.</typeparam>
     /// <typeparam name="T">Type to convert to.</typeparam>
-    public class JsonCommaDelimitedArrayConverter<T> : JsonConverter<T[]>
+    public sealed class JsonCommaDelimitedArrayConverter<T> : JsonDelimitedArrayConverter<T>
     {
     {
-        private readonly TypeConverter _typeConverter;
-
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="JsonCommaDelimitedArrayConverter{T}"/> class.
         /// Initializes a new instance of the <see cref="JsonCommaDelimitedArrayConverter{T}"/> class.
         /// </summary>
         /// </summary>
-        public JsonCommaDelimitedArrayConverter()
+        public JsonCommaDelimitedArrayConverter() : base()
         {
         {
-            _typeConverter = TypeDescriptor.GetConverter(typeof(T));
         }
         }
 
 
         /// <inheritdoc />
         /// <inheritdoc />
-        public override T[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
-        {
-            if (reader.TokenType == JsonTokenType.String)
-            {
-                var stringEntries = reader.GetString().Split(',', StringSplitOptions.RemoveEmptyEntries);
-                if (stringEntries.Length == 0)
-                {
-                    return Array.Empty<T>();
-                }
-
-                var parsedValues = new object[stringEntries.Length];
-                var convertedCount = 0;
-                for (var i = 0; i < stringEntries.Length; i++)
-                {
-                    try
-                    {
-                        parsedValues[i] = _typeConverter.ConvertFrom(stringEntries[i].Trim());
-                        convertedCount++;
-                    }
-                    catch (FormatException)
-                    {
-                        // TODO log when upgraded to .Net6
-                        // https://github.com/dotnet/runtime/issues/42975
-                        // _logger.LogDebug(e, "Error converting value.");
-                    }
-                }
-
-                var typedValues = new T[convertedCount];
-                var typedValueIndex = 0;
-                for (var i = 0; i < stringEntries.Length; i++)
-                {
-                    if (parsedValues[i] != null)
-                    {
-                        typedValues.SetValue(parsedValues[i], typedValueIndex);
-                        typedValueIndex++;
-                    }
-                }
-
-                return typedValues;
-            }
-
-            return JsonSerializer.Deserialize<T[]>(ref reader, options);
-        }
-
-        /// <inheritdoc />
-        public override void Write(Utf8JsonWriter writer, T[] value, JsonSerializerOptions options)
-        {
-            throw new NotImplementedException();
-        }
+        protected override char Delimiter => ',';
     }
     }
 }
 }

+ 2 - 2
MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs

@@ -19,10 +19,10 @@ namespace MediaBrowser.Common.Json.Converters
         }
         }
 
 
         /// <inheritdoc />
         /// <inheritdoc />
-        public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
+        public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options)
         {
         {
             var structType = typeToConvert.GetElementType() ?? typeToConvert.GenericTypeArguments[0];
             var structType = typeToConvert.GetElementType() ?? typeToConvert.GenericTypeArguments[0];
-            return (JsonConverter)Activator.CreateInstance(typeof(JsonCommaDelimitedArrayConverter<>).MakeGenericType(structType));
+            return (JsonConverter?)Activator.CreateInstance(typeof(JsonCommaDelimitedArrayConverter<>).MakeGenericType(structType));
         }
         }
     }
     }
 }
 }

+ 81 - 0
MediaBrowser.Common/Json/Converters/JsonDelimitedArrayConverter.cs

@@ -0,0 +1,81 @@
+using System;
+using System.ComponentModel;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace MediaBrowser.Common.Json.Converters
+{
+    /// <summary>
+    /// Convert delimited string to array of type.
+    /// </summary>
+    /// <typeparam name="T">Type to convert to.</typeparam>
+    public abstract class JsonDelimitedArrayConverter<T> : JsonConverter<T[]?>
+    {
+        private readonly TypeConverter _typeConverter;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonDelimitedArrayConverter{T}"/> class.
+        /// </summary>
+        protected JsonDelimitedArrayConverter()
+        {
+            _typeConverter = TypeDescriptor.GetConverter(typeof(T));
+        }
+
+        /// <summary>
+        /// Gets the array delimiter.
+        /// </summary>
+        protected virtual char Delimiter { get; }
+
+        /// <inheritdoc />
+        public override T[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+        {
+            if (reader.TokenType == JsonTokenType.String)
+            {
+                // GetString can't return null here because we already handled it above
+                var stringEntries = reader.GetString()?.Split(Delimiter, StringSplitOptions.RemoveEmptyEntries);
+                if (stringEntries == null || stringEntries.Length == 0)
+                {
+                    return Array.Empty<T>();
+                }
+
+                var parsedValues = new object[stringEntries.Length];
+                var convertedCount = 0;
+                for (var i = 0; i < stringEntries.Length; i++)
+                {
+                    try
+                    {
+                        parsedValues[i] = _typeConverter.ConvertFrom(stringEntries[i].Trim());
+                        convertedCount++;
+                    }
+                    catch (FormatException)
+                    {
+                        // TODO log when upgraded to .Net6
+                        // https://github.com/dotnet/runtime/issues/42975
+                        // _logger.LogDebug(e, "Error converting value.");
+                    }
+                }
+
+                var typedValues = new T[convertedCount];
+                var typedValueIndex = 0;
+                for (var i = 0; i < stringEntries.Length; i++)
+                {
+                    if (parsedValues[i] != null)
+                    {
+                        typedValues.SetValue(parsedValues[i], typedValueIndex);
+                        typedValueIndex++;
+                    }
+                }
+
+                return typedValues;
+            }
+
+            return JsonSerializer.Deserialize<T[]>(ref reader, options);
+        }
+
+        /// <inheritdoc />
+        public override void Write(Utf8JsonWriter writer, T[]? value, JsonSerializerOptions options)
+        {
+            throw new NotImplementedException();
+        }
+    }
+}

+ 3 - 3
MediaBrowser.Common/Json/Converters/JsonNullableStructConverterFactory.cs

@@ -18,10 +18,10 @@ namespace MediaBrowser.Common.Json.Converters
         }
         }
 
 
         /// <inheritdoc />
         /// <inheritdoc />
-        public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
+        public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options)
         {
         {
             var structType = typeToConvert.GenericTypeArguments[0];
             var structType = typeToConvert.GenericTypeArguments[0];
-            return (JsonConverter)Activator.CreateInstance(typeof(JsonNullableStructConverter<>).MakeGenericType(structType));
+            return (JsonConverter?)Activator.CreateInstance(typeof(JsonNullableStructConverter<>).MakeGenericType(structType));
         }
         }
     }
     }
-}
+}

+ 12 - 6
MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStringConverter.cs

@@ -7,15 +7,21 @@ namespace MediaBrowser.Common.Json.Converters
     /// <summary>
     /// <summary>
     /// Converts a string <c>N/A</c> to <c>string.Empty</c>.
     /// Converts a string <c>N/A</c> to <c>string.Empty</c>.
     /// </summary>
     /// </summary>
-    public class JsonOmdbNotAvailableStringConverter : JsonConverter<string>
+    public class JsonOmdbNotAvailableStringConverter : JsonConverter<string?>
     {
     {
         /// <inheritdoc />
         /// <inheritdoc />
-        public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+        public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
         {
         {
+            if (reader.TokenType == JsonTokenType.Null)
+            {
+                return null;
+            }
+
             if (reader.TokenType == JsonTokenType.String)
             if (reader.TokenType == JsonTokenType.String)
             {
             {
-                var str = reader.GetString();
-                if (str != null && str.Equals("N/A", StringComparison.OrdinalIgnoreCase))
+                // GetString can't return null here because we already handled it above
+                var str = reader.GetString()!;
+                if (str.Equals("N/A", StringComparison.OrdinalIgnoreCase))
                 {
                 {
                     return null;
                     return null;
                 }
                 }
@@ -23,11 +29,11 @@ namespace MediaBrowser.Common.Json.Converters
                 return str;
                 return str;
             }
             }
 
 
-            return JsonSerializer.Deserialize<string>(ref reader, options);
+            return JsonSerializer.Deserialize<string?>(ref reader, options);
         }
         }
 
 
         /// <inheritdoc />
         /// <inheritdoc />
-        public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
+        public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options)
         {
         {
             writer.WriteStringValue(value);
             writer.WriteStringValue(value);
         }
         }

+ 3 - 54
MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverter.cs

@@ -9,67 +9,16 @@ namespace MediaBrowser.Common.Json.Converters
     /// Convert Pipe delimited string to array of type.
     /// Convert Pipe delimited string to array of type.
     /// </summary>
     /// </summary>
     /// <typeparam name="T">Type to convert to.</typeparam>
     /// <typeparam name="T">Type to convert to.</typeparam>
-    public class JsonPipeDelimitedArrayConverter<T> : JsonConverter<T[]>
+    public sealed class JsonPipeDelimitedArrayConverter<T> : JsonDelimitedArrayConverter<T>
     {
     {
-        private readonly TypeConverter _typeConverter;
-
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="JsonPipeDelimitedArrayConverter{T}"/> class.
         /// Initializes a new instance of the <see cref="JsonPipeDelimitedArrayConverter{T}"/> class.
         /// </summary>
         /// </summary>
-        public JsonPipeDelimitedArrayConverter()
+        public JsonPipeDelimitedArrayConverter() : base()
         {
         {
-            _typeConverter = TypeDescriptor.GetConverter(typeof(T));
         }
         }
 
 
         /// <inheritdoc />
         /// <inheritdoc />
-        public override T[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
-        {
-            if (reader.TokenType == JsonTokenType.String)
-            {
-                var stringEntries = reader.GetString()?.Split('|', StringSplitOptions.RemoveEmptyEntries);
-                if (stringEntries == null || stringEntries.Length == 0)
-                {
-                    return Array.Empty<T>();
-                }
-
-                var parsedValues = new object[stringEntries.Length];
-                var convertedCount = 0;
-                for (var i = 0; i < stringEntries.Length; i++)
-                {
-                    try
-                    {
-                        parsedValues[i] = _typeConverter.ConvertFrom(stringEntries[i].Trim());
-                        convertedCount++;
-                    }
-                    catch (FormatException)
-                    {
-                        // TODO log when upgraded to .Net6
-                        // https://github.com/dotnet/runtime/issues/42975
-                        // _logger.LogDebug(e, "Error converting value.");
-                    }
-                }
-
-                var typedValues = new T[convertedCount];
-                var typedValueIndex = 0;
-                for (var i = 0; i < stringEntries.Length; i++)
-                {
-                    if (parsedValues[i] != null)
-                    {
-                        typedValues.SetValue(parsedValues[i], typedValueIndex);
-                        typedValueIndex++;
-                    }
-                }
-
-                return typedValues;
-            }
-
-            return JsonSerializer.Deserialize<T[]>(ref reader, options);
-        }
-
-        /// <inheritdoc />
-        public override void Write(Utf8JsonWriter writer, T[] value, JsonSerializerOptions options)
-        {
-            throw new NotImplementedException();
-        }
+        protected override char Delimiter => '|';
     }
     }
 }
 }

+ 2 - 2
MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs

@@ -19,10 +19,10 @@ namespace MediaBrowser.Common.Json.Converters
         }
         }
 
 
         /// <inheritdoc />
         /// <inheritdoc />
-        public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
+        public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options)
         {
         {
             var structType = typeToConvert.GetElementType() ?? typeToConvert.GenericTypeArguments[0];
             var structType = typeToConvert.GetElementType() ?? typeToConvert.GenericTypeArguments[0];
-            return (JsonConverter)Activator.CreateInstance(typeof(JsonPipeDelimitedArrayConverter<>).MakeGenericType(structType));
+            return (JsonConverter?)Activator.CreateInstance(typeof(JsonPipeDelimitedArrayConverter<>).MakeGenericType(structType));
         }
         }
     }
     }
 }
 }

+ 4 - 4
MediaBrowser.Common/Json/Converters/JsonStringConverter.cs

@@ -9,10 +9,10 @@ namespace MediaBrowser.Common.Json.Converters
     /// <summary>
     /// <summary>
     /// Converter to allow the serializer to read strings.
     /// Converter to allow the serializer to read strings.
     /// </summary>
     /// </summary>
-    public class JsonStringConverter : JsonConverter<string>
+    public class JsonStringConverter : JsonConverter<string?>
     {
     {
         /// <inheritdoc />
         /// <inheritdoc />
-        public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+        public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
         {
         {
             return reader.TokenType switch
             return reader.TokenType switch
             {
             {
@@ -23,7 +23,7 @@ namespace MediaBrowser.Common.Json.Converters
         }
         }
 
 
         /// <inheritdoc />
         /// <inheritdoc />
-        public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
+        public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options)
         {
         {
             writer.WriteStringValue(value);
             writer.WriteStringValue(value);
         }
         }
@@ -36,4 +36,4 @@ namespace MediaBrowser.Common.Json.Converters
             return Encoding.UTF8.GetString(utf8Bytes);
             return Encoding.UTF8.GetString(utf8Bytes);
         }
         }
     }
     }
-}
+}

+ 1 - 1
MediaBrowser.Common/Json/Converters/JsonVersionConverter.cs

@@ -14,7 +14,7 @@ namespace MediaBrowser.Common.Json.Converters
     {
     {
         /// <inheritdoc />
         /// <inheritdoc />
         public override Version Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
         public override Version Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
-            => new Version(reader.GetString());
+            => new Version(reader.GetString()!); // Will throw ArgumentNullException on null
 
 
         /// <inheritdoc />
         /// <inheritdoc />
         public override void Write(Utf8JsonWriter writer, Version value, JsonSerializerOptions options)
         public override void Write(Utf8JsonWriter writer, Version value, JsonSerializerOptions options)

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

@@ -33,6 +33,7 @@
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <Nullable>enable</Nullable>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
     <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
     <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
     <PublishRepositoryUrl>true</PublishRepositoryUrl>
     <PublishRepositoryUrl>true</PublishRepositoryUrl>

+ 0 - 1
MediaBrowser.Common/Net/INetworkManager.cs

@@ -1,4 +1,3 @@
-#nullable enable
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Collections.ObjectModel;

+ 0 - 1
MediaBrowser.Common/Net/IPHost.cs

@@ -1,4 +1,3 @@
-#nullable enable
 using System;
 using System;
 using System.Diagnostics;
 using System.Diagnostics;
 using System.Linq;
 using System.Linq;

+ 0 - 1
MediaBrowser.Common/Net/IPNetAddress.cs

@@ -1,4 +1,3 @@
-#nullable enable
 using System;
 using System;
 using System.Net;
 using System.Net;
 using System.Net.Sockets;
 using System.Net.Sockets;

+ 0 - 1
MediaBrowser.Common/Net/IPObject.cs

@@ -1,4 +1,3 @@
-#nullable enable
 using System;
 using System;
 using System.Net;
 using System.Net;
 using System.Net.Sockets;
 using System.Net.Sockets;

+ 2 - 0
MediaBrowser.Common/Plugins/BasePlugin.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 using System;
 using System;
 using System.IO;
 using System.IO;
 using System.Reflection;
 using System.Reflection;

+ 2 - 0
MediaBrowser.Common/Plugins/BasePluginOfT.cs

@@ -1,4 +1,6 @@
+#nullable disable
 #pragma warning disable SA1649 // File name should match first type name
 #pragma warning disable SA1649 // File name should match first type name
+
 using System;
 using System;
 using System.IO;
 using System.IO;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;

+ 2 - 0
MediaBrowser.Common/Plugins/IPlugin.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 using System;
 using System;
 using MediaBrowser.Model.Plugins;
 using MediaBrowser.Model.Plugins;
 
 

+ 0 - 2
MediaBrowser.Common/Plugins/IPluginManager.cs

@@ -1,5 +1,3 @@
-#nullable enable
-
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Reflection;
 using System.Reflection;

+ 0 - 1
MediaBrowser.Common/Plugins/LocalPlugin.cs

@@ -1,4 +1,3 @@
-#nullable enable
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using MediaBrowser.Model.Plugins;
 using MediaBrowser.Model.Plugins;

+ 0 - 2
MediaBrowser.Common/Plugins/PluginManifest.cs

@@ -1,5 +1,3 @@
-#nullable enable
-
 using System;
 using System;
 using System.Text.Json.Serialization;
 using System.Text.Json.Serialization;
 using MediaBrowser.Model.Plugins;
 using MediaBrowser.Model.Plugins;

+ 2 - 2
MediaBrowser.Common/Progress/ActionableProgress.cs

@@ -14,9 +14,9 @@ namespace MediaBrowser.Common.Progress
         /// <summary>
         /// <summary>
         /// The _actions.
         /// The _actions.
         /// </summary>
         /// </summary>
-        private Action<T> _action;
+        private Action<T>? _action;
 
 
-        public event EventHandler<T> ProgressChanged;
+        public event EventHandler<T>? ProgressChanged;
 
 
         /// <summary>
         /// <summary>
         /// Registers the action.
         /// Registers the action.

+ 1 - 1
MediaBrowser.Common/Progress/SimpleProgress.cs

@@ -7,7 +7,7 @@ namespace MediaBrowser.Common.Progress
 {
 {
     public class SimpleProgress<T> : IProgress<T>
     public class SimpleProgress<T> : IProgress<T>
     {
     {
-        public event EventHandler<T> ProgressChanged;
+        public event EventHandler<T>? ProgressChanged;
 
 
         public void Report(T value)
         public void Report(T value)
         {
         {

+ 1 - 3
MediaBrowser.Common/Providers/ProviderIdParsers.cs

@@ -1,6 +1,4 @@
-#nullable enable
-
-using System;
+using System;
 using System.Diagnostics.CodeAnalysis;
 using System.Diagnostics.CodeAnalysis;
 
 
 namespace MediaBrowser.Common.Providers
 namespace MediaBrowser.Common.Providers

+ 0 - 2
MediaBrowser.Common/Updates/IInstallationManager.cs

@@ -1,5 +1,3 @@
-#nullable enable
-
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Threading;
 using System.Threading;

+ 2 - 0
MediaBrowser.Common/Updates/InstallationEventArgs.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 using System;
 using System;
 using MediaBrowser.Model.Updates;
 using MediaBrowser.Model.Updates;
 
 

+ 1 - 0
MediaBrowser.Common/Updates/InstallationFailedEventArgs.cs

@@ -1,3 +1,4 @@
+#nullable disable
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
MediaBrowser.Controller/Authentication/AuthenticationResult.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using MediaBrowser.Controller.Session;
 using MediaBrowser.Controller.Session;

+ 2 - 0
MediaBrowser.Controller/Authentication/IAuthenticationProvider.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System.Threading.Tasks;
 using System.Threading.Tasks;

+ 2 - 0
MediaBrowser.Controller/Authentication/IPasswordResetProvider.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 using System;
 using System;
 using System.Linq;
 using System.Linq;
 using System.Threading;
 using System.Threading;

+ 2 - 0
MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 using System.Threading;
 using System.Threading;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Configuration;

+ 2 - 0
MediaBrowser.Controller/Channels/Channel.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
MediaBrowser.Controller/Channels/ChannelItemInfo.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
MediaBrowser.Controller/Channels/ChannelItemResult.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System.Collections.Generic;
 using System.Collections.Generic;

+ 2 - 0
MediaBrowser.Controller/Channels/ChannelSearchInfo.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 namespace MediaBrowser.Controller.Channels
 namespace MediaBrowser.Controller.Channels

+ 2 - 0
MediaBrowser.Controller/Channels/IChannel.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System.Collections.Generic;
 using System.Collections.Generic;

+ 2 - 0
MediaBrowser.Controller/Channels/IChannelManager.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
MediaBrowser.Controller/Channels/IHasCacheKey.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 namespace MediaBrowser.Controller.Channels
 namespace MediaBrowser.Controller.Channels

+ 2 - 0
MediaBrowser.Controller/Channels/ISearchableChannel.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System.Collections.Generic;
 using System.Collections.Generic;

+ 2 - 0
MediaBrowser.Controller/Channels/InternalChannelFeatures.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System.Collections.Generic;
 using System.Collections.Generic;

+ 2 - 0
MediaBrowser.Controller/Channels/InternalChannelItemQuery.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

+ 2 - 0
MediaBrowser.Controller/Collections/CollectionCreationOptions.cs

@@ -1,3 +1,5 @@
+#nullable disable
+
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio