From a6d1e542e62548f177523f0acd67260f58066731 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 19 Sep 2021 20:53:31 +0200 Subject: Reduce allocations --- MediaBrowser.Model/Net/MimeTypes.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.Model/Net') diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 96f5ab51ae..7b3c17c85a 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using Jellyfin.Extensions; namespace MediaBrowser.Model.Net { @@ -221,7 +222,7 @@ namespace MediaBrowser.Model.Net } // handle text/html; charset=UTF-8 - mimeType = mimeType.Split(';')[0]; + mimeType = mimeType.AsSpan().LeftPart(';').ToString(); if (_extensionLookup.TryGetValue(mimeType, out string? result)) { -- cgit v1.2.3 From 13fbfe6091e61450aedc07bc78c96bf4c414bc65 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 14 Feb 2021 15:11:46 +0100 Subject: Target net6.0 --- DvdLib/DvdLib.csproj | 2 +- DvdLib/Ifo/Dvd.cs | 3 ++- Emby.Dlna/DlnaManager.cs | 2 +- Emby.Dlna/Emby.Dlna.csproj | 2 +- Emby.Dlna/Server/DescriptionXmlBuilder.cs | 3 +-- Emby.Dlna/Service/BaseService.cs | 8 ++++---- Emby.Drawing/Emby.Drawing.csproj | 2 +- Emby.Naming/Emby.Naming.csproj | 2 +- Emby.Notifications/Emby.Notifications.csproj | 2 +- Emby.Photos/Emby.Photos.csproj | 2 +- .../Emby.Server.Implementations.csproj | 2 +- .../LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 2 +- .../FirstTimeSetupOrDefaultHandler.cs | 6 +++--- .../FirstTimeSetupOrElevatedHandler.cs | 6 +++--- Jellyfin.Api/Controllers/ImageController.cs | 10 +++++----- Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs | 3 ++- Jellyfin.Api/Jellyfin.Api.csproj | 2 +- Jellyfin.Api/ModelBinders/NullableEnumModelBinder.cs | 5 +++-- Jellyfin.Data/Jellyfin.Data.csproj | 2 +- Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 7 +------ Jellyfin.Networking/Jellyfin.Networking.csproj | 2 +- .../Jellyfin.Server.Implementations.csproj | 2 +- Jellyfin.Server/Configuration/CorsPolicyProvider.cs | 4 ++-- .../SymlinkFollowingPhysicalFileResultExecutor.cs | 2 +- Jellyfin.Server/Jellyfin.Server.csproj | 2 +- .../Middleware/QueryStringDecodingMiddleware.cs | 6 +++++- MediaBrowser.Common/MediaBrowser.Common.csproj | 2 +- MediaBrowser.Controller/Dlna/IDlnaManager.cs | 2 +- MediaBrowser.Controller/Drawing/IImageProcessor.cs | 2 +- MediaBrowser.Controller/MediaBrowser.Controller.csproj | 2 +- MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs | 7 ++++++- .../MediaBrowser.LocalMetadata.csproj | 2 +- .../MediaBrowser.MediaEncoding.csproj | 2 +- .../Subtitles/SubtitleEditParser.cs | 2 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 2 +- MediaBrowser.Model/Net/MimeTypes.cs | 12 +++++++----- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 2 +- .../Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs | 2 +- .../MediaBrowser.XbmcMetadata.csproj | 2 +- RSSDP/DisposableManagedObjectBase.cs | 5 +++-- RSSDP/RSSDP.csproj | 2 +- RSSDP/SsdpDevice.cs | 13 ++++++++----- RSSDP/SsdpDevicePublisher.cs | 15 ++++++++------- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 2 +- tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj | 2 +- .../Jellyfin.Controller.Tests.csproj | 2 +- tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj | 2 +- .../Jellyfin.Extensions.Tests.csproj | 2 +- .../Jellyfin.MediaEncoding.Tests.csproj | 2 +- tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj | 2 +- tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj | 2 +- .../Jellyfin.Networking.Tests.csproj | 2 +- .../Jellyfin.Server.Implementations.Tests.csproj | 2 +- .../Jellyfin.Server.Integration.Tests.csproj | 2 +- tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj | 2 +- .../Jellyfin.XbmcMetadata.Tests.csproj | 2 +- 56 files changed, 103 insertions(+), 90 deletions(-) (limited to 'MediaBrowser.Model/Net') diff --git a/DvdLib/DvdLib.csproj b/DvdLib/DvdLib.csproj index b8301e2f27..755d29160c 100644 --- a/DvdLib/DvdLib.csproj +++ b/DvdLib/DvdLib.csproj @@ -10,7 +10,7 @@ - net5.0 + net6.0 false true AllDisabledByDefault diff --git a/DvdLib/Ifo/Dvd.cs b/DvdLib/Ifo/Dvd.cs index b4a11ed5d6..7f8ece47dc 100644 --- a/DvdLib/Ifo/Dvd.cs +++ b/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 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)); diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 68fc80c0a0..3855504324 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -486,7 +486,7 @@ namespace Emby.Dlna } /// - public ImageStream GetIcon(string filename) + public ImageStream? GetIcon(string filename) { var format = filename.EndsWith(".png", StringComparison.OrdinalIgnoreCase) ? ImageFormat.Png diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index 970c16d2e6..1d4e3b047d 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -17,7 +17,7 @@ - net5.0 + net6.0 false true AllDisabledByDefault diff --git a/Emby.Dlna/Server/DescriptionXmlBuilder.cs b/Emby.Dlna/Server/DescriptionXmlBuilder.cs index 3f3dfccd3a..09525aae4e 100644 --- a/Emby.Dlna/Server/DescriptionXmlBuilder.cs +++ b/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 GetIcons() diff --git a/Emby.Dlna/Service/BaseService.cs b/Emby.Dlna/Service/BaseService.cs index a97c4d63a6..68fd987585 100644 --- a/Emby.Dlna/Service/BaseService.cs +++ b/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); } } } diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index baf350c6f1..300eea9680 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false true AllDisabledByDefault diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index 07d879e96a..96f8f389b3 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false true true diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj index 5edcf2f295..d200682e65 100644 --- a/Emby.Notifications/Emby.Notifications.csproj +++ b/Emby.Notifications/Emby.Notifications.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false true diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index 00b2f0f94c..bf6252c195 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -19,7 +19,7 @@ - net5.0 + net6.0 false true diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 769972d8c4..0e1386ef55 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -42,7 +42,7 @@ - net5.0 + net6.0 false true diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index a8f761fdeb..6a2e7f6998 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/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(); diff --git a/Jellyfin.Api/Auth/FirstTimeSetupOrDefaultPolicy/FirstTimeSetupOrDefaultHandler.cs b/Jellyfin.Api/Auth/FirstTimeSetupOrDefaultPolicy/FirstTimeSetupOrDefaultHandler.cs index 9815e252ee..dd0bd4ec2f 100644 --- a/Jellyfin.Api/Auth/FirstTimeSetupOrDefaultPolicy/FirstTimeSetupOrDefaultHandler.cs +++ b/Jellyfin.Api/Auth/FirstTimeSetupOrDefaultPolicy/FirstTimeSetupOrDefaultHandler.cs @@ -32,18 +32,18 @@ namespace Jellyfin.Api.Auth.FirstTimeSetupOrDefaultPolicy } /// - 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 { diff --git a/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs b/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs index decbe0c035..90b76ee99a 100644 --- a/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs +++ b/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs @@ -33,18 +33,18 @@ namespace Jellyfin.Api.Auth.FirstTimeSetupOrElevatedPolicy } /// - 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 { diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 9dc280e138..b1c860d61f 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/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); } } } diff --git a/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs b/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs index b0fd59e5e3..6385b62c96 100644 --- a/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs +++ b/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"; diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 7f4eb0378a..8cc4711a72 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 true AD0001 diff --git a/Jellyfin.Api/ModelBinders/NullableEnumModelBinder.cs b/Jellyfin.Api/ModelBinders/NullableEnumModelBinder.cs index be2045fbab..d2e78ac884 100644 --- a/Jellyfin.Api/ModelBinders/NullableEnumModelBinder.cs +++ b/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; } } -} \ No newline at end of file +} diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 65bbd49da2..19aef704c0 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -1,7 +1,7 @@  - net5.0 + net6.0 false true true diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index 8cee5dcaee..5fa386ecac 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false true @@ -28,11 +28,6 @@ - - - - - diff --git a/Jellyfin.Networking/Jellyfin.Networking.csproj b/Jellyfin.Networking/Jellyfin.Networking.csproj index 227a41ce44..0cd9a59156 100644 --- a/Jellyfin.Networking/Jellyfin.Networking.csproj +++ b/Jellyfin.Networking/Jellyfin.Networking.csproj @@ -1,6 +1,6 @@ - net5.0 + net6.0 false true diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index 434c414a4a..337f5cb82a 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 false true diff --git a/Jellyfin.Server/Configuration/CorsPolicyProvider.cs b/Jellyfin.Server/Configuration/CorsPolicyProvider.cs index 0d04b6bb13..b061be33b5 100644 --- a/Jellyfin.Server/Configuration/CorsPolicyProvider.cs +++ b/Jellyfin.Server/Configuration/CorsPolicyProvider.cs @@ -23,7 +23,7 @@ namespace Jellyfin.Server.Configuration } /// - public Task GetPolicyAsync(HttpContext context, string policyName) + public Task 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(builder.Build()); } } } diff --git a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs index e171fc145c..4abd5b36d1 100644 --- a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs +++ b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs @@ -68,7 +68,7 @@ namespace Jellyfin.Server.Infrastructure } /// - 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) { diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index fc935cecb2..074d43fba8 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -8,7 +8,7 @@ jellyfin Exe - net5.0 + net6.0 false false true diff --git a/Jellyfin.Server/Middleware/QueryStringDecodingMiddleware.cs b/Jellyfin.Server/Middleware/QueryStringDecodingMiddleware.cs index fd0ebbf438..cdd86e28e6 100644 --- a/Jellyfin.Server/Middleware/QueryStringDecodingMiddleware.cs +++ b/Jellyfin.Server/Middleware/QueryStringDecodingMiddleware.cs @@ -27,7 +27,11 @@ namespace Jellyfin.Server.Middleware /// The async task. public async Task Invoke(HttpContext httpContext) { - httpContext.Features.Set(new UrlDecodeQueryFeature(httpContext.Features.Get())); + var feature = httpContext.Features.Get(); + if (feature != null) + { + httpContext.Features.Set(new UrlDecodeQueryFeature(feature)); + } await _next(httpContext).ConfigureAwait(false); } diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 12cfaf9789..6358c00001 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -29,7 +29,7 @@ - net5.0 + net6.0 false true true diff --git a/MediaBrowser.Controller/Dlna/IDlnaManager.cs b/MediaBrowser.Controller/Dlna/IDlnaManager.cs index a64919700d..cc0a107a81 100644 --- a/MediaBrowser.Controller/Dlna/IDlnaManager.cs +++ b/MediaBrowser.Controller/Dlna/IDlnaManager.cs @@ -74,6 +74,6 @@ namespace MediaBrowser.Controller.Dlna /// /// The filename. /// DlnaIconResponse. - ImageStream GetIcon(string filename); + ImageStream? GetIcon(string filename); } } diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index c7f61a90bb..7ca0e851bd 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Controller.Drawing /// Guid. string GetImageCacheTag(BaseItem item, ItemImageInfo image); - string GetImageCacheTag(BaseItem item, ChapterInfo info); + string GetImageCacheTag(BaseItem item, ChapterInfo chapter); string? GetImageCacheTag(User user); diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 0f697bcccd..47cec7d77f 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -32,7 +32,7 @@ - net5.0 + net6.0 false true true diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index b09b7dba6c..e92c4a08a6 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/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) diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index 1cf8fcd1b5..a3db717b9f 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -11,7 +11,7 @@ - net5.0 + net6.0 false true diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 5deaecc952..30cfb904e1 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false true diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs index 3d864e29ca..20e4be7802 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs +++ b/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(); diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index a371afc2cf..b0a12a9c90 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -14,7 +14,7 @@ - net5.0 + net6.0 false true true diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 7b3c17c85a..1d9150f02b 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/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"); /// /// Gets the type of the MIME. /// /// The filename to find the MIME type of. - /// Whether of not to return a default value if no fitting MIME type is found. - /// The worrect MIME type for the given filename, or `null` if it wasn't found and is false. - public static string? GetMimeType(string filename, bool enableStreamDefault) + /// Theefault value to return if no fitting MIME type is found. + /// The correct MIME type for the given filename, or if it wasn't found. + [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) diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 3a6e162746..29d6b01f23 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -26,7 +26,7 @@ - net5.0 + net6.0 false true ../jellyfin.ruleset diff --git a/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs index 268538815e..19d90b9a1b 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs +++ b/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; } diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index 3e2a9bacf1..926be5a927 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -15,7 +15,7 @@ - net5.0 + net6.0 false true diff --git a/RSSDP/DisposableManagedObjectBase.cs b/RSSDP/DisposableManagedObjectBase.cs index 7d6a471f95..5d7da4124e 100644 --- a/RSSDP/DisposableManagedObjectBase.cs +++ b/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"); diff --git a/RSSDP/RSSDP.csproj b/RSSDP/RSSDP.csproj index 54113d4644..77130983b5 100644 --- a/RSSDP/RSSDP.csproj +++ b/RSSDP/RSSDP.csproj @@ -11,7 +11,7 @@ - net5.0 + net6.0 false AllDisabledByDefault disable diff --git a/RSSDP/SsdpDevice.cs b/RSSDP/SsdpDevice.cs index 4005d836d9..c826830f1d 100644 --- a/RSSDP/SsdpDevice.cs +++ b/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"); } } diff --git a/RSSDP/SsdpDevicePublisher.cs b/RSSDP/SsdpDevicePublisher.cs index c9e795d565..64d19803df 100644 --- a/RSSDP/SsdpDevicePublisher.cs +++ b/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); } diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 9dac63e703..b52ea078af 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index 1619fa89c8..1fe4e25656 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index a5778b59c8..e9a9515710 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj index 5a48631c29..1fb95aab4d 100644 --- a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj +++ b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj index 20680157f5..2dc4ac19a5 100644 --- a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj +++ b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index e9cd8c0623..201f63a2d6 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj index 09b8a7a948..a37e5ac920 100644 --- a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj +++ b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index a4ebab141e..75d466198a 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj index 5fa2ecfe9e..75d9b9ea90 100644 --- a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj +++ b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index 9b6ab7bdf5..5ecd846047 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset Jellyfin.Server.Implementations.Tests diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 42e60df5fb..7939c7118e 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -1,6 +1,6 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index 4f0bbc36cf..b30e690a5e 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj index e085907583..94294c8bf3 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj +++ b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset -- cgit v1.2.3 From 5fd315b17c7c95c05eaba0713b27f6a95d31e164 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 24 Sep 2021 20:15:10 +0200 Subject: Address comments --- Emby.Server.Implementations/Data/SqliteItemRepository.cs | 6 +++--- MediaBrowser.Model/Net/MimeTypes.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.Model/Net') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 88cd4476a7..0a48b844dd 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1610,7 +1610,7 @@ namespace Emby.Server.Implementations.Data if (reader.TryGetString(index++, out var lockedFields)) { List fields = null; - foreach (var i in lockedFields.Split('|')) + foreach (var i in lockedFields.AsSpan().Split('|')) { if (Enum.TryParse(i, true, out MetadataField parsedValue)) { @@ -1645,7 +1645,7 @@ namespace Emby.Server.Implementations.Data if (reader.TryGetString(index, out var trailerTypes)) { List types = null; - foreach (var i in trailerTypes.Split('|')) + foreach (var i in trailerTypes.AsSpan().Split('|')) { if (Enum.TryParse(i, true, out TrailerType parsedValue)) { @@ -1653,7 +1653,7 @@ namespace Emby.Server.Implementations.Data } } - trailer.TrailerTypes = types.ToArray() ?? Array.Empty(); + trailer.TrailerTypes = types?.ToArray() ?? Array.Empty(); } } diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 1d9150f02b..748170a0e1 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -171,7 +171,7 @@ namespace MediaBrowser.Model.Net /// Gets the type of the MIME. /// /// The filename to find the MIME type of. - /// Theefault value to return if no fitting MIME type is found. + /// The default value to return if no fitting MIME type is found. /// The correct MIME type for the given filename, or if it wasn't found. [return: NotNullIfNotNullAttribute("defaultValue")] public static string? GetMimeType(string filename, string? defaultValue = null) -- cgit v1.2.3 From 994101fcf455b7566bbd6212992d849ad6105fa0 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 9 Nov 2021 16:28:39 +0100 Subject: Remove some dead code --- .../Providers/ImageRefreshOptions.cs | 2 - MediaBrowser.Controller/Providers/ItemInfo.cs | 2 - MediaBrowser.Model/MediaInfo/AudioCodec.cs | 27 +++++----- MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs | 16 ------ .../MediaInfo/PlaybackInfoRequest.cs | 58 ---------------------- MediaBrowser.Model/MediaInfo/SubtitleFormat.cs | 2 - MediaBrowser.Model/Net/NetworkShareType.cs | 33 ------------ .../Manager/ItemImageProviderTests.cs | 18 +++---- 8 files changed, 23 insertions(+), 135 deletions(-) delete mode 100644 MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs delete mode 100644 MediaBrowser.Model/Net/NetworkShareType.cs (limited to 'MediaBrowser.Model/Net') diff --git a/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs b/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs index 2ac4c728ba..08d129a82e 100644 --- a/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs +++ b/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs @@ -1,5 +1,3 @@ -#nullable disable - #pragma warning disable CA1819, CS1591 using System; diff --git a/MediaBrowser.Controller/Providers/ItemInfo.cs b/MediaBrowser.Controller/Providers/ItemInfo.cs index b8dd416a2d..3a97127eaa 100644 --- a/MediaBrowser.Controller/Providers/ItemInfo.cs +++ b/MediaBrowser.Controller/Providers/ItemInfo.cs @@ -1,5 +1,3 @@ -#nullable disable - #pragma warning disable CS1591 using System; diff --git a/MediaBrowser.Model/MediaInfo/AudioCodec.cs b/MediaBrowser.Model/MediaInfo/AudioCodec.cs index 8b17757b89..7b83b1b9df 100644 --- a/MediaBrowser.Model/MediaInfo/AudioCodec.cs +++ b/MediaBrowser.Model/MediaInfo/AudioCodec.cs @@ -1,13 +1,11 @@ #pragma warning disable CS1591 +using System; + namespace MediaBrowser.Model.MediaInfo { public static class AudioCodec { - public const string AAC = "aac"; - public const string MP3 = "mp3"; - public const string AC3 = "ac3"; - public static string GetFriendlyName(string codec) { if (codec.Length == 0) @@ -15,17 +13,20 @@ namespace MediaBrowser.Model.MediaInfo return codec; } - switch (codec.ToLowerInvariant()) + if (string.Equals(codec, "ac3", StringComparison.OrdinalIgnoreCase)) + { + return "Dolby Digital"; + } + else if (string.Equals(codec, "eac3", StringComparison.OrdinalIgnoreCase)) { - case "ac3": - return "Dolby Digital"; - case "eac3": - return "Dolby Digital+"; - case "dca": - return "DTS"; - default: - return codec.ToUpperInvariant(); + return "Dolby Digital+"; } + else if (string.Equals(codec, "dca", StringComparison.OrdinalIgnoreCase)) + { + return "DTS"; + } + + return codec.ToUpperInvariant(); } } } diff --git a/MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs b/MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs index 36a2407067..24eab1a744 100644 --- a/MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs +++ b/MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs @@ -16,22 +16,6 @@ namespace MediaBrowser.Model.MediaInfo DirectPlayProtocols = new MediaProtocol[] { MediaProtocol.Http }; } - public LiveStreamRequest(AudioOptions options) - { - MaxStreamingBitrate = options.MaxBitrate; - ItemId = options.ItemId; - DeviceProfile = options.Profile; - MaxAudioChannels = options.MaxAudioChannels; - - DirectPlayProtocols = new MediaProtocol[] { MediaProtocol.Http }; - - if (options is VideoOptions videoOptions) - { - AudioStreamIndex = videoOptions.AudioStreamIndex; - SubtitleStreamIndex = videoOptions.SubtitleStreamIndex; - } - } - public string OpenToken { get; set; } public Guid UserId { get; set; } diff --git a/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs b/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs deleted file mode 100644 index ecd9b8834e..0000000000 --- a/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs +++ /dev/null @@ -1,58 +0,0 @@ -#nullable disable -#pragma warning disable CS1591 - -using System; -using MediaBrowser.Model.Dlna; - -namespace MediaBrowser.Model.MediaInfo -{ - public class PlaybackInfoRequest - { - public PlaybackInfoRequest() - { - EnableDirectPlay = true; - EnableDirectStream = true; - EnableTranscoding = true; - AllowVideoStreamCopy = true; - AllowAudioStreamCopy = true; - IsPlayback = true; - DirectPlayProtocols = new MediaProtocol[] { MediaProtocol.Http }; - } - - public Guid Id { get; set; } - - public Guid UserId { get; set; } - - public long? MaxStreamingBitrate { get; set; } - - public long? StartTimeTicks { get; set; } - - public int? AudioStreamIndex { get; set; } - - public int? SubtitleStreamIndex { get; set; } - - public int? MaxAudioChannels { get; set; } - - public string MediaSourceId { get; set; } - - public string LiveStreamId { get; set; } - - public DeviceProfile DeviceProfile { get; set; } - - public bool EnableDirectPlay { get; set; } - - public bool EnableDirectStream { get; set; } - - public bool EnableTranscoding { get; set; } - - public bool AllowVideoStreamCopy { get; set; } - - public bool AllowAudioStreamCopy { get; set; } - - public bool IsPlayback { get; set; } - - public bool AutoOpenLiveStream { get; set; } - - public MediaProtocol[] DirectPlayProtocols { get; set; } - } -} diff --git a/MediaBrowser.Model/MediaInfo/SubtitleFormat.cs b/MediaBrowser.Model/MediaInfo/SubtitleFormat.cs index 2bd45695a3..9bc5c31f62 100644 --- a/MediaBrowser.Model/MediaInfo/SubtitleFormat.cs +++ b/MediaBrowser.Model/MediaInfo/SubtitleFormat.cs @@ -8,8 +8,6 @@ namespace MediaBrowser.Model.MediaInfo public const string SSA = "ssa"; public const string ASS = "ass"; public const string VTT = "vtt"; - public const string SUB = "sub"; - public const string SMI = "smi"; public const string TTML = "ttml"; } } diff --git a/MediaBrowser.Model/Net/NetworkShareType.cs b/MediaBrowser.Model/Net/NetworkShareType.cs deleted file mode 100644 index 5d985f85d3..0000000000 --- a/MediaBrowser.Model/Net/NetworkShareType.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace MediaBrowser.Model.Net -{ - /// - /// Enum NetworkShareType. - /// - public enum NetworkShareType - { - /// - /// Disk share. - /// - Disk, - - /// - /// Printer share. - /// - Printer, - - /// - /// Device share. - /// - Device, - - /// - /// IPC share. - /// - Ipc, - - /// - /// Special share. - /// - Special - } -} diff --git a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs index f9ac8f46b9..9e6afe9b19 100644 --- a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs @@ -235,12 +235,12 @@ namespace Jellyfin.Providers.Tests.Manager .ReturnsAsync(imageResponse); var refreshOptions = forceRefresh - ? new ImageRefreshOptions(null) + ? new ImageRefreshOptions(Mock.Of()) { ImageRefreshMode = MetadataRefreshMode.FullRefresh, ReplaceAllImages = true } - : new ImageRefreshOptions(null); + : new ImageRefreshOptions(Mock.Of()); var itemImageProvider = GetItemImageProvider(null, new Mock()); var result = await itemImageProvider.RefreshImages(item, libraryOptions, new List { dynamicProvider.Object }, refreshOptions, CancellationToken.None); @@ -290,7 +290,7 @@ namespace Jellyfin.Providers.Tests.Manager dynamicProvider.Setup(rp => rp.GetImage(item, imageType, It.IsAny())) .ReturnsAsync(imageResponse); - var refreshOptions = new ImageRefreshOptions(null); + var refreshOptions = new ImageRefreshOptions(Mock.Of()); var providerManager = new Mock(MockBehavior.Strict); providerManager.Setup(pm => pm.SaveImage(item, It.IsAny(), It.IsAny(), imageType, null, It.IsAny())) @@ -329,12 +329,12 @@ namespace Jellyfin.Providers.Tests.Manager .Returns(new[] { imageType }); var refreshOptions = forceRefresh - ? new ImageRefreshOptions(null) + ? new ImageRefreshOptions(Mock.Of()) { ImageRefreshMode = MetadataRefreshMode.FullRefresh, ReplaceAllImages = true } - : new ImageRefreshOptions(null); + : new ImageRefreshOptions(Mock.Of()); var remoteInfo = new RemoteImageInfo[imageCount]; for (int i = 0; i < imageCount; i++) @@ -399,12 +399,12 @@ namespace Jellyfin.Providers.Tests.Manager }); var refreshOptions = fullRefresh - ? new ImageRefreshOptions(null) + ? new ImageRefreshOptions(Mock.Of()) { ImageRefreshMode = MetadataRefreshMode.FullRefresh, ReplaceAllImages = true } - : new ImageRefreshOptions(null); + : new ImageRefreshOptions(Mock.Of()); var remoteInfo = new RemoteImageInfo[targetImageCount]; for (int i = 0; i < targetImageCount; i++) @@ -448,7 +448,7 @@ namespace Jellyfin.Providers.Tests.Manager remoteProvider.Setup(rp => rp.GetSupportedImages(item)) .Returns(new[] { imageType }); - var refreshOptions = new ImageRefreshOptions(null); + var refreshOptions = new ImageRefreshOptions(Mock.Of()); // populate remote with double the required images to verify count is trimmed to the library option count var remoteInfoCount = imageCount * 2; @@ -493,7 +493,7 @@ namespace Jellyfin.Providers.Tests.Manager remoteProvider.Setup(rp => rp.GetSupportedImages(item)) .Returns(new[] { imageType }); - var refreshOptions = new ImageRefreshOptions(null) + var refreshOptions = new ImageRefreshOptions(Mock.Of()) { ImageRefreshMode = MetadataRefreshMode.FullRefresh, ReplaceAllImages = true -- cgit v1.2.3 From 257e1be95f2b3be629501a95f6a7c5da083697fd Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 16 Nov 2021 16:31:57 +0100 Subject: Fix some warnings --- .../Channels/ChannelManager.cs | 8 -------- Jellyfin.Api/Attributes/AcceptsFileAttribute.cs | 4 +++- .../Attributes/AcceptsImageFileAttribute.cs | 2 +- Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs | 2 +- .../Attributes/HttpUnsubscribeAttribute.cs | 2 +- .../Attributes/ParameterObsoleteAttribute.cs | 2 +- .../Attributes/ProducesAudioFileAttribute.cs | 2 +- Jellyfin.Api/Attributes/ProducesFileAttribute.cs | 4 +++- .../Attributes/ProducesImageFileAttribute.cs | 2 +- .../Attributes/ProducesPlaylistFileAttribute.cs | 2 +- .../Attributes/ProducesVideoFileAttribute.cs | 2 +- MediaBrowser.Controller/Entities/Audio/Audio.cs | 8 ++------ MediaBrowser.Controller/Entities/BaseItem.cs | 12 ++---------- MediaBrowser.Controller/Entities/Video.cs | 22 +++++++++++----------- MediaBrowser.Model/Net/MimeTypes.cs | 2 +- jellyfin.ruleset | 4 ++++ 16 files changed, 34 insertions(+), 46 deletions(-) (limited to 'MediaBrowser.Model/Net') diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 09aee602af..f65eaec1c8 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -1075,14 +1075,6 @@ namespace Emby.Server.Implementations.Channels forceUpdate = true; } - // was used for status - // if (!string.Equals(item.ExternalEtag ?? string.Empty, info.Etag ?? string.Empty, StringComparison.Ordinal)) - // { - // item.ExternalEtag = info.Etag; - // forceUpdate = true; - // _logger.LogDebug("Forcing update due to ExternalEtag {0}", item.Name); - // } - if (!internalChannelId.Equals(item.ChannelId)) { forceUpdate = true; diff --git a/Jellyfin.Api/Attributes/AcceptsFileAttribute.cs b/Jellyfin.Api/Attributes/AcceptsFileAttribute.cs index 49b6689cde..58552d847d 100644 --- a/Jellyfin.Api/Attributes/AcceptsFileAttribute.cs +++ b/Jellyfin.Api/Attributes/AcceptsFileAttribute.cs @@ -1,4 +1,6 @@ -using System; +#pragma warning disable CA1813 // Avoid unsealed attributes + +using System; namespace Jellyfin.Api.Attributes { diff --git a/Jellyfin.Api/Attributes/AcceptsImageFileAttribute.cs b/Jellyfin.Api/Attributes/AcceptsImageFileAttribute.cs index 001f27409e..244a29da45 100644 --- a/Jellyfin.Api/Attributes/AcceptsImageFileAttribute.cs +++ b/Jellyfin.Api/Attributes/AcceptsImageFileAttribute.cs @@ -3,7 +3,7 @@ /// /// Produces file attribute of "image/*". /// - public class AcceptsImageFileAttribute : AcceptsFileAttribute + public sealed class AcceptsImageFileAttribute : AcceptsFileAttribute { private const string ContentType = "image/*"; diff --git a/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs b/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs index 2fdd1e4899..af8727552c 100644 --- a/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs +++ b/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs @@ -7,7 +7,7 @@ namespace Jellyfin.Api.Attributes /// /// Identifies an action that supports the HTTP GET method. /// - public class HttpSubscribeAttribute : HttpMethodAttribute + public sealed class HttpSubscribeAttribute : HttpMethodAttribute { private static readonly IEnumerable _supportedMethods = new[] { "SUBSCRIBE" }; diff --git a/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs b/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs index d6d7e4563d..1c0b70e719 100644 --- a/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs +++ b/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs @@ -7,7 +7,7 @@ namespace Jellyfin.Api.Attributes /// /// Identifies an action that supports the HTTP GET method. /// - public class HttpUnsubscribeAttribute : HttpMethodAttribute + public sealed class HttpUnsubscribeAttribute : HttpMethodAttribute { private static readonly IEnumerable _supportedMethods = new[] { "UNSUBSCRIBE" }; diff --git a/Jellyfin.Api/Attributes/ParameterObsoleteAttribute.cs b/Jellyfin.Api/Attributes/ParameterObsoleteAttribute.cs index 56c9772b6d..514e7ce974 100644 --- a/Jellyfin.Api/Attributes/ParameterObsoleteAttribute.cs +++ b/Jellyfin.Api/Attributes/ParameterObsoleteAttribute.cs @@ -6,7 +6,7 @@ namespace Jellyfin.Api.Attributes /// Attribute to mark a parameter as obsolete. /// [AttributeUsage(AttributeTargets.Parameter)] - public class ParameterObsoleteAttribute : Attribute + public sealed class ParameterObsoleteAttribute : Attribute { } } diff --git a/Jellyfin.Api/Attributes/ProducesAudioFileAttribute.cs b/Jellyfin.Api/Attributes/ProducesAudioFileAttribute.cs index 3adb700eb5..9fc25f192e 100644 --- a/Jellyfin.Api/Attributes/ProducesAudioFileAttribute.cs +++ b/Jellyfin.Api/Attributes/ProducesAudioFileAttribute.cs @@ -3,7 +3,7 @@ /// /// Produces file attribute of "image/*". /// - public class ProducesAudioFileAttribute : ProducesFileAttribute + public sealed class ProducesAudioFileAttribute : ProducesFileAttribute { private const string ContentType = "audio/*"; diff --git a/Jellyfin.Api/Attributes/ProducesFileAttribute.cs b/Jellyfin.Api/Attributes/ProducesFileAttribute.cs index 62a576ede2..2bf77d729a 100644 --- a/Jellyfin.Api/Attributes/ProducesFileAttribute.cs +++ b/Jellyfin.Api/Attributes/ProducesFileAttribute.cs @@ -1,4 +1,6 @@ -using System; +#pragma warning disable CA1813 // Avoid unsealed attributes + +using System; namespace Jellyfin.Api.Attributes { diff --git a/Jellyfin.Api/Attributes/ProducesImageFileAttribute.cs b/Jellyfin.Api/Attributes/ProducesImageFileAttribute.cs index e158136762..1e5b542e27 100644 --- a/Jellyfin.Api/Attributes/ProducesImageFileAttribute.cs +++ b/Jellyfin.Api/Attributes/ProducesImageFileAttribute.cs @@ -3,7 +3,7 @@ /// /// Produces file attribute of "image/*". /// - public class ProducesImageFileAttribute : ProducesFileAttribute + public sealed class ProducesImageFileAttribute : ProducesFileAttribute { private const string ContentType = "image/*"; diff --git a/Jellyfin.Api/Attributes/ProducesPlaylistFileAttribute.cs b/Jellyfin.Api/Attributes/ProducesPlaylistFileAttribute.cs index 5d928ab914..5b15cb1a56 100644 --- a/Jellyfin.Api/Attributes/ProducesPlaylistFileAttribute.cs +++ b/Jellyfin.Api/Attributes/ProducesPlaylistFileAttribute.cs @@ -3,7 +3,7 @@ /// /// Produces file attribute of "image/*". /// - public class ProducesPlaylistFileAttribute : ProducesFileAttribute + public sealed class ProducesPlaylistFileAttribute : ProducesFileAttribute { private const string ContentType = "application/x-mpegURL"; diff --git a/Jellyfin.Api/Attributes/ProducesVideoFileAttribute.cs b/Jellyfin.Api/Attributes/ProducesVideoFileAttribute.cs index d8b2856dca..6857d45ecc 100644 --- a/Jellyfin.Api/Attributes/ProducesVideoFileAttribute.cs +++ b/Jellyfin.Api/Attributes/ProducesVideoFileAttribute.cs @@ -3,7 +3,7 @@ /// /// Produces file attribute of "video/*". /// - public class ProducesVideoFileAttribute : ProducesFileAttribute + public sealed class ProducesVideoFileAttribute : ProducesFileAttribute { private const string ContentType = "video/*"; diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 536668e508..30111a9af2 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -146,11 +146,7 @@ namespace MediaBrowser.Controller.Entities.Audio return info; } - protected override List> GetAllItemsForMediaSources() - { - var list = new List>(); - list.Add(new Tuple(this, MediaSourceType.Default)); - return list; - } + protected override IEnumerable<(BaseItem, MediaSourceType)> GetAllItemsForMediaSources() + => new[] { ((BaseItem)this, MediaSourceType.Default) }; } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index a76ca23055..b1ac2fe8ee 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.IO; using System.Linq; using System.Text; using System.Text.Json.Serialization; @@ -333,13 +332,6 @@ namespace MediaBrowser.Controller.Entities [JsonIgnore] public string ExternalSeriesId { get; set; } - /// - /// Gets or sets the etag. - /// - /// The etag. - [JsonIgnore] - public string ExternalEtag { get; set; } - [JsonIgnore] public virtual bool IsHidden => false; @@ -1161,9 +1153,9 @@ namespace MediaBrowser.Controller.Entities .ToList(); } - protected virtual List> GetAllItemsForMediaSources() + protected virtual IEnumerable<(BaseItem, MediaSourceType)> GetAllItemsForMediaSources() { - return new List>(); + return Enumerable.Empty<(BaseItem, MediaSourceType)>(); } private MediaSourceInfo GetVersionInfo(bool enablePathSubstitution, BaseItem item, MediaSourceType type) diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 7dd95b85cf..de42c67d38 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -509,35 +509,35 @@ namespace MediaBrowser.Controller.Entities }).FirstOrDefault(); } - protected override List> GetAllItemsForMediaSources() + protected override IEnumerable<(BaseItem, MediaSourceType)> GetAllItemsForMediaSources() { - var list = new List>(); + var list = new List<(BaseItem, MediaSourceType)> + { + (this, MediaSourceType.Default) + }; - list.Add(new Tuple(this, MediaSourceType.Default)); - list.AddRange(GetLinkedAlternateVersions().Select(i => new Tuple(i, MediaSourceType.Grouping))); + list.AddRange(GetLinkedAlternateVersions().Select(i => ((BaseItem)i, MediaSourceType.Grouping))); if (!string.IsNullOrEmpty(PrimaryVersionId)) { - var primary = LibraryManager.GetItemById(PrimaryVersionId) as Video; - if (primary != null) + if (LibraryManager.GetItemById(PrimaryVersionId) is Video primary) { var existingIds = list.Select(i => i.Item1.Id).ToList(); - list.Add(new Tuple(primary, MediaSourceType.Grouping)); - list.AddRange(primary.GetLinkedAlternateVersions().Where(i => !existingIds.Contains(i.Id)).Select(i => new Tuple(i, MediaSourceType.Grouping))); + list.Add((primary, MediaSourceType.Grouping)); + list.AddRange(primary.GetLinkedAlternateVersions().Where(i => !existingIds.Contains(i.Id)).Select(i => ((BaseItem)i, MediaSourceType.Grouping))); } } var localAlternates = list .SelectMany(i => { - var video = i.Item1 as Video; - return video == null ? new List() : video.GetLocalAlternateVersionIds(); + return i.Item1 is Video video ? video.GetLocalAlternateVersionIds() : Enumerable.Empty(); }) .Select(LibraryManager.GetItemById) .Where(i => i != null) .ToList(); - list.AddRange(localAlternates.Select(i => new Tuple(i, MediaSourceType.Default))); + list.AddRange(localAlternates.Select(i => (i, MediaSourceType.Default))); return list; } diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 748170a0e1..043cee2a25 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -191,7 +191,7 @@ namespace MediaBrowser.Model.Net // Catch-all for all video types that don't require specific mime types if (_videoFileExtensions.Contains(ext)) { - return "video/" + ext.Substring(1); + return string.Concat("video/", ext.AsSpan(1)); } // Type text diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 469f61021a..7adc35087f 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -50,8 +50,12 @@ + + + + -- cgit v1.2.3 From 6193fdea698ad4486140bc6a00a9547ab979c8f7 Mon Sep 17 00:00:00 2001 From: Ahmed Rafiq Date: Sat, 4 Dec 2021 19:50:48 +0600 Subject: Use MimeTypes package to determine MIME type This simplifies the code since we don't have to keep large mappings of extensions and MIME types. We still keep the ability to override the mappings for: - filling in entries not present in the package, for e.g. ".azw3" - picking preferred extensions, for e.g. MimeTypes provides ".conf" as a possible extionsion for "text/plain", and while that is correct, ".txt" would be preferrable - compatibility reasons --- MediaBrowser.Model/MediaBrowser.Model.csproj | 4 + MediaBrowser.Model/Net/MimeTypes.cs | 147 +++++++------------- tests/Jellyfin.Model.Tests/Net/MimeTypesTests.cs | 164 +++++++++++++++++++++++ 3 files changed, 217 insertions(+), 98 deletions(-) create mode 100644 tests/Jellyfin.Model.Tests/Net/MimeTypesTests.cs (limited to 'MediaBrowser.Model/Net') diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 70fef5d661..b1fbe864b4 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -31,6 +31,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 043cee2a25..ff8d1fbae5 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -12,6 +12,10 @@ namespace MediaBrowser.Model.Net /// /// Class MimeTypes. /// + /// + /// http://en.wikipedia.org/wiki/Internet_media_type + /// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types + /// http://www.iana.org/assignments/media-types/media-types.xhtml public static class MimeTypes { /// @@ -50,81 +54,26 @@ namespace MediaBrowser.Model.Net ".wtv", }; - // http://en.wikipedia.org/wiki/Internet_media_type - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types - // http://www.iana.org/assignments/media-types/media-types.xhtml - // Add more as needed + /// + /// Used for extensions not in or to override them. + /// private static readonly Dictionary _mimeTypeLookup = new Dictionary(StringComparer.OrdinalIgnoreCase) { // Type application - { ".7z", "application/x-7z-compressed" }, - { ".azw", "application/vnd.amazon.ebook" }, { ".azw3", "application/vnd.amazon.ebook" }, - { ".cbz", "application/x-cbz" }, - { ".cbr", "application/epub+zip" }, - { ".eot", "application/vnd.ms-fontobject" }, - { ".epub", "application/epub+zip" }, - { ".js", "application/x-javascript" }, - { ".json", "application/json" }, - { ".m3u8", "application/x-mpegURL" }, - { ".map", "application/x-javascript" }, - { ".mobi", "application/x-mobipocket-ebook" }, - { ".opf", "application/oebps-package+xml" }, - { ".pdf", "application/pdf" }, - { ".rar", "application/vnd.rar" }, - { ".srt", "application/x-subrip" }, - { ".ttml", "application/ttml+xml" }, - { ".wasm", "application/wasm" }, - { ".xml", "application/xml" }, - { ".zip", "application/zip" }, // Type image - { ".bmp", "image/bmp" }, - { ".gif", "image/gif" }, - { ".ico", "image/vnd.microsoft.icon" }, - { ".jpg", "image/jpeg" }, - { ".jpeg", "image/jpeg" }, - { ".png", "image/png" }, - { ".svg", "image/svg+xml" }, - { ".svgz", "image/svg+xml" }, { ".tbn", "image/jpeg" }, - { ".tif", "image/tiff" }, - { ".tiff", "image/tiff" }, - { ".webp", "image/webp" }, - - // Type font - { ".ttf", "font/ttf" }, - { ".woff", "font/woff" }, - { ".woff2", "font/woff2" }, // Type text { ".ass", "text/x-ssa" }, { ".ssa", "text/x-ssa" }, - { ".css", "text/css" }, - { ".csv", "text/csv" }, { ".edl", "text/plain" }, - { ".rtf", "text/rtf" }, - { ".txt", "text/plain" }, - { ".vtt", "text/vtt" }, + { ".html", "text/html; charset=UTF-8" }, + { ".htm", "text/html; charset=UTF-8" }, // Type video - { ".3gp", "video/3gpp" }, - { ".3g2", "video/3gpp2" }, - { ".asf", "video/x-ms-asf" }, - { ".avi", "video/x-msvideo" }, - { ".flv", "video/x-flv" }, - { ".mp4", "video/mp4" }, - { ".m4s", "video/mp4" }, - { ".m4v", "video/x-m4v" }, { ".mpegts", "video/mp2t" }, - { ".mpg", "video/mpeg" }, - { ".mkv", "video/x-matroska" }, - { ".mov", "video/quicktime" }, - { ".mpd", "video/vnd.mpeg.dash.mpd" }, - { ".ogv", "video/ogg" }, - { ".ts", "video/mp2t" }, - { ".webm", "video/webm" }, - { ".wmv", "video/x-ms-wmv" }, // Type audio { ".aac", "audio/aac" }, @@ -133,37 +82,47 @@ namespace MediaBrowser.Model.Net { ".dsf", "audio/dsf" }, { ".dsp", "audio/dsp" }, { ".flac", "audio/flac" }, - { ".m4a", "audio/mp4" }, { ".m4b", "audio/m4b" }, - { ".mid", "audio/midi" }, - { ".midi", "audio/midi" }, { ".mp3", "audio/mpeg" }, - { ".oga", "audio/ogg" }, - { ".ogg", "audio/ogg" }, - { ".opus", "audio/ogg" }, { ".vorbis", "audio/vorbis" }, - { ".wav", "audio/wav" }, { ".webma", "audio/webm" }, - { ".wma", "audio/x-ms-wma" }, { ".wv", "audio/x-wavpack" }, { ".xsp", "audio/xsp" }, }; - private static readonly Dictionary _extensionLookup = CreateExtensionLookup(); - - private static Dictionary CreateExtensionLookup() + private static readonly Dictionary _extensionLookup = new Dictionary(StringComparer.OrdinalIgnoreCase) { - var dict = _mimeTypeLookup - .GroupBy(i => i.Value) - .ToDictionary(x => x.Key, x => x.First().Key, StringComparer.OrdinalIgnoreCase); + // Type application + { "application/x-cbz", ".cbz" }, + { "application/x-javascript", ".js" }, + { "application/xml", ".xml" }, + { "application/x-mpegURL", ".m3u8" }, + + // Type audio + { "audio/aac", ".aac" }, + { "audio/ac3", ".ac3" }, + { "audio/dsf", ".dsf" }, + { "audio/dsp", ".dsp" }, + { "audio/flac", ".flac" }, + { "audio/m4b", ".m4b" }, + { "audio/vorbis", ".vorbis" }, + { "audio/x-ape", ".ape" }, + { "audio/xsp", ".xsp" }, + { "audio/x-wavpack", ".wv" }, - dict["image/jpg"] = ".jpg"; - dict["image/x-png"] = ".png"; + // Type image + { "image/jpg", ".jpg" }, + { "image/x-png", ".png" }, - dict["audio/x-aac"] = ".aac"; + // Type text + { "text/plain", ".txt" }, + { "text/rtf", ".rtf" }, + { "text/x-ssa", ".ssa" }, - return dict; - } + // Type video + { "video/vnd.mpeg.dash.mpd", ".mpd" }, + { "video/x-matroska", ".mkv" }, + }; public static string GetMimeType(string path) => GetMimeType(path, "application/octet-stream"); @@ -188,29 +147,15 @@ namespace MediaBrowser.Model.Net return result; } - // Catch-all for all video types that don't require specific mime types - if (_videoFileExtensions.Contains(ext)) - { - return string.Concat("video/", ext.AsSpan(1)); - } - - // Type text - if (string.Equals(ext, ".html", StringComparison.OrdinalIgnoreCase) - || string.Equals(ext, ".htm", StringComparison.OrdinalIgnoreCase)) - { - return "text/html; charset=UTF-8"; - } - - if (string.Equals(ext, ".log", StringComparison.OrdinalIgnoreCase) - || string.Equals(ext, ".srt", StringComparison.OrdinalIgnoreCase)) + if (Model.MimeTypes.TryGetMimeType(filename, out var mimeType)) { - return "text/plain"; + return mimeType; } - // Misc - if (string.Equals(ext, ".dll", StringComparison.OrdinalIgnoreCase)) + // Catch-all for all video types that don't require specific mime types + if (_videoFileExtensions.Contains(ext)) { - return "application/octet-stream"; + return string.Concat("video/", ext.AsSpan(1)); } return defaultValue; @@ -231,6 +176,12 @@ namespace MediaBrowser.Model.Net return result; } + var extensions = Model.MimeTypes.GetMimeTypeExtensions(mimeType); + if (extensions.Any()) + { + return "." + extensions.First(); + } + return null; } } diff --git a/tests/Jellyfin.Model.Tests/Net/MimeTypesTests.cs b/tests/Jellyfin.Model.Tests/Net/MimeTypesTests.cs new file mode 100644 index 0000000000..b82607bf0e --- /dev/null +++ b/tests/Jellyfin.Model.Tests/Net/MimeTypesTests.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MediaBrowser.Model.Net; +using Xunit; + +namespace Jellyfin.Model.Tests.Net +{ + public class MimeTypesTests + { + [Theory] + [InlineData(".dll", "application/octet-stream")] + [InlineData(".log", "text/plain")] + [InlineData(".srt", "application/x-subrip")] + [InlineData(".html", "text/html; charset=UTF-8")] + [InlineData(".htm", "text/html; charset=UTF-8")] + [InlineData(".7z", "application/x-7z-compressed")] + [InlineData(".azw", "application/vnd.amazon.ebook")] + [InlineData(".azw3", "application/vnd.amazon.ebook")] + [InlineData(".eot", "application/vnd.ms-fontobject")] + [InlineData(".epub", "application/epub+zip")] + [InlineData(".json", "application/json")] + [InlineData(".mobi", "application/x-mobipocket-ebook")] + [InlineData(".opf", "application/oebps-package+xml")] + [InlineData(".pdf", "application/pdf")] + [InlineData(".rar", "application/vnd.rar")] + [InlineData(".ttml", "application/ttml+xml")] + [InlineData(".wasm", "application/wasm")] + [InlineData(".xml", "application/xml")] + [InlineData(".zip", "application/zip")] + [InlineData(".bmp", "image/bmp")] + [InlineData(".gif", "image/gif")] + [InlineData(".ico", "image/vnd.microsoft.icon")] + [InlineData(".jpg", "image/jpeg")] + [InlineData(".jpeg", "image/jpeg")] + [InlineData(".png", "image/png")] + [InlineData(".svg", "image/svg+xml")] + [InlineData(".svgz", "image/svg+xml")] + [InlineData(".tbn", "image/jpeg")] + [InlineData(".tif", "image/tiff")] + [InlineData(".tiff", "image/tiff")] + [InlineData(".webp", "image/webp")] + [InlineData(".ttf", "font/ttf")] + [InlineData(".woff", "font/woff")] + [InlineData(".woff2", "font/woff2")] + [InlineData(".ass", "text/x-ssa")] + [InlineData(".ssa", "text/x-ssa")] + [InlineData(".css", "text/css")] + [InlineData(".csv", "text/csv")] + [InlineData(".edl", "text/plain")] + [InlineData(".txt", "text/plain")] + [InlineData(".vtt", "text/vtt")] + [InlineData(".3gp", "video/3gpp")] + [InlineData(".3g2", "video/3gpp2")] + [InlineData(".asf", "video/x-ms-asf")] + [InlineData(".avi", "video/x-msvideo")] + [InlineData(".flv", "video/x-flv")] + [InlineData(".mp4", "video/mp4")] + [InlineData(".m4v", "video/x-m4v")] + [InlineData(".mpegts", "video/mp2t")] + [InlineData(".mpg", "video/mpeg")] + [InlineData(".mkv", "video/x-matroska")] + [InlineData(".mov", "video/quicktime")] + [InlineData(".ogv", "video/ogg")] + [InlineData(".ts", "video/mp2t")] + [InlineData(".webm", "video/webm")] + [InlineData(".wmv", "video/x-ms-wmv")] + [InlineData(".aac", "audio/aac")] + [InlineData(".ac3", "audio/ac3")] + [InlineData(".ape", "audio/x-ape")] + [InlineData(".dsf", "audio/dsf")] + [InlineData(".dsp", "audio/dsp")] + [InlineData(".flac", "audio/flac")] + [InlineData(".m4a", "audio/mp4")] + [InlineData(".m4b", "audio/m4b")] + [InlineData(".mid", "audio/midi")] + [InlineData(".midi", "audio/midi")] + [InlineData(".mp3", "audio/mpeg")] + [InlineData(".oga", "audio/ogg")] + [InlineData(".ogg", "audio/ogg")] + [InlineData(".opus", "audio/ogg")] + [InlineData(".vorbis", "audio/vorbis")] + [InlineData(".wav", "audio/wav")] + [InlineData(".webma", "audio/webm")] + [InlineData(".wma", "audio/x-ms-wma")] + [InlineData(".wv", "audio/x-wavpack")] + [InlineData(".xsp", "audio/xsp")] + public void GetMimeType(string input, string expectedResult) + { + Assert.Equal(expectedResult, MimeTypes.GetMimeType(input, null)); + } + + [Theory] + [InlineData("application/epub+zip", ".epub")] + [InlineData("application/json", ".json")] + [InlineData("application/oebps-package+xml", ".opf")] + [InlineData("application/pdf", ".pdf")] + [InlineData("application/ttml+xml", ".ttml")] + [InlineData("application/vnd.amazon.ebook", ".azw")] + [InlineData("application/vnd.ms-fontobject", ".eot")] + [InlineData("application/vnd.rar", ".rar")] + [InlineData("application/wasm", ".wasm")] + [InlineData("application/x-7z-compressed", ".7z")] + [InlineData("application/x-cbz", ".cbz")] + [InlineData("application/x-javascript", ".js")] + [InlineData("application/x-mobipocket-ebook", ".mobi")] + [InlineData("application/x-mpegURL", ".m3u8")] + [InlineData("application/x-subrip", ".srt")] + [InlineData("application/xml", ".xml")] + [InlineData("application/zip", ".zip")] + [InlineData("audio/aac", ".aac")] + [InlineData("audio/ac3", ".ac3")] + [InlineData("audio/dsf", ".dsf")] + [InlineData("audio/dsp", ".dsp")] + [InlineData("audio/flac", ".flac")] + [InlineData("audio/m4b", ".m4b")] + [InlineData("audio/mp4", ".m4a")] + [InlineData("audio/vorbis", ".vorbis")] + [InlineData("audio/wav", ".wav")] + [InlineData("audio/x-aac", ".aac")] + [InlineData("audio/x-ape", ".ape")] + [InlineData("audio/x-ms-wma", ".wma")] + [InlineData("audio/x-wavpack", ".wv")] + [InlineData("audio/xsp", ".xsp")] + [InlineData("font/ttf", ".ttf")] + [InlineData("font/woff", ".woff")] + [InlineData("font/woff2", ".woff2")] + [InlineData("image/bmp", ".bmp")] + [InlineData("image/gif", ".gif")] + [InlineData("image/jpg", ".jpg")] + [InlineData("image/png", ".png")] + [InlineData("image/svg+xml", ".svg")] + [InlineData("image/tiff", ".tif")] + [InlineData("image/vnd.microsoft.icon", ".ico")] + [InlineData("image/webp", ".webp")] + [InlineData("image/x-png", ".png")] + [InlineData("text/css", ".css")] + [InlineData("text/csv", ".csv")] + [InlineData("text/plain", ".txt")] + [InlineData("text/rtf", ".rtf")] + [InlineData("text/vtt", ".vtt")] + [InlineData("text/x-ssa", ".ssa")] + [InlineData("video/3gpp", ".3gp")] + [InlineData("video/3gpp2", ".3g2")] + [InlineData("video/mp2t", ".ts")] + [InlineData("video/mp4", ".mp4")] + [InlineData("video/ogg", ".ogv")] + [InlineData("video/quicktime", ".mov")] + [InlineData("video/vnd.mpeg.dash.mpd", ".mpd")] + [InlineData("video/webm", ".webm")] + [InlineData("video/x-flv", ".flv")] + [InlineData("video/x-m4v", ".m4v")] + [InlineData("video/x-matroska", ".mkv")] + [InlineData("video/x-ms-asf", ".asf")] + [InlineData("video/x-ms-wmv", ".wmv")] + [InlineData("video/x-msvideo", ".avi")] + public void ToExtension(string input, string expectedResult) + { + Assert.Equal(expectedResult, MimeTypes.ToExtension(input)); + } + } +} -- cgit v1.2.3 From 40e05a7993599c43b58acb34f59ca5149dc76040 Mon Sep 17 00:00:00 2001 From: Ahmed Rafiq Date: Sat, 4 Dec 2021 21:06:51 +0600 Subject: Update documentation --- MediaBrowser.Model/Net/MimeTypes.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'MediaBrowser.Model/Net') diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index ff8d1fbae5..18a3f82599 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -13,9 +13,14 @@ namespace MediaBrowser.Model.Net /// Class MimeTypes. /// /// - /// http://en.wikipedia.org/wiki/Internet_media_type - /// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types - /// http://www.iana.org/assignments/media-types/media-types.xhtml + /// + /// For more information on MIME types: + /// + /// http://en.wikipedia.org/wiki/Internet_media_type + /// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types + /// http://www.iana.org/assignments/media-types/media-types.xhtml + /// + /// public static class MimeTypes { /// -- cgit v1.2.3 From 0e491025aec8ef11acf86b189b5e16692fb8d4a6 Mon Sep 17 00:00:00 2001 From: Ahmed Rafiq Date: Sat, 4 Dec 2021 21:13:18 +0600 Subject: Refactor MimeTypes.ToExtension() Co-authored-by: Cody Robibero --- MediaBrowser.Model/Net/MimeTypes.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.Model/Net') diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 18a3f82599..506e8e9d63 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -181,13 +181,8 @@ namespace MediaBrowser.Model.Net return result; } - var extensions = Model.MimeTypes.GetMimeTypeExtensions(mimeType); - if (extensions.Any()) - { - return "." + extensions.First(); - } - - return null; + var extension = Model.MimeTypes.GetMimeTypeExtensions(mimeType).FirstOrDefault(); + return string.IsNullOrEmpty(extension) ? null : "." + extension; } } } -- cgit v1.2.3 From 7ee96a59d3b69e15aec1df33ad46f47021f8a20b Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 12 Dec 2021 02:07:35 +0100 Subject: Use correct jpeg MIME type image/jpg isn't a valid MIME type --- MediaBrowser.Model/Net/MimeTypes.cs | 4 ++-- tests/Jellyfin.Model.Tests/Net/MimeTypesTests.cs | 7 +------ 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'MediaBrowser.Model/Net') diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 506e8e9d63..3b03466e9d 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -116,7 +116,7 @@ namespace MediaBrowser.Model.Net { "audio/x-wavpack", ".wv" }, // Type image - { "image/jpg", ".jpg" }, + { "image/jpeg", ".jpg" }, { "image/x-png", ".png" }, // Type text @@ -137,7 +137,7 @@ namespace MediaBrowser.Model.Net /// The filename to find the MIME type of. /// The default value to return if no fitting MIME type is found. /// The correct MIME type for the given filename, or if it wasn't found. - [return: NotNullIfNotNullAttribute("defaultValue")] + [return: NotNullIfNotNull("defaultValue")] public static string? GetMimeType(string filename, string? defaultValue = null) { if (filename.Length == 0) diff --git a/tests/Jellyfin.Model.Tests/Net/MimeTypesTests.cs b/tests/Jellyfin.Model.Tests/Net/MimeTypesTests.cs index 55050cc954..cbab455f01 100644 --- a/tests/Jellyfin.Model.Tests/Net/MimeTypesTests.cs +++ b/tests/Jellyfin.Model.Tests/Net/MimeTypesTests.cs @@ -1,8 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using MediaBrowser.Model.Net; using Xunit; @@ -129,7 +124,7 @@ namespace Jellyfin.Model.Tests.Net [InlineData("font/woff2", ".woff2")] [InlineData("image/bmp", ".bmp")] [InlineData("image/gif", ".gif")] - [InlineData("image/jpg", ".jpg")] + [InlineData("image/jpeg", ".jpg")] [InlineData("image/png", ".png")] [InlineData("image/svg+xml", ".svg")] [InlineData("image/tiff", ".tif")] -- cgit v1.2.3