diff options
Diffstat (limited to 'MediaBrowser.Model')
| -rw-r--r-- | MediaBrowser.Model/Dlna/TranscodingProfile.cs | 1 | ||||
| -rw-r--r-- | MediaBrowser.Model/Entities/ProviderIdsExtensions.cs | 89 |
2 files changed, 81 insertions, 9 deletions
diff --git a/MediaBrowser.Model/Dlna/TranscodingProfile.cs b/MediaBrowser.Model/Dlna/TranscodingProfile.cs index f49b24976a..b5adee173b 100644 --- a/MediaBrowser.Model/Dlna/TranscodingProfile.cs +++ b/MediaBrowser.Model/Dlna/TranscodingProfile.cs @@ -141,6 +141,7 @@ public class TranscodingProfile /// Gets or sets a value indicating whether breaking the video stream on non-keyframes is supported. /// </summary> [DefaultValue(false)] + [XmlIgnore] [XmlAttribute("breakOnNonKeyFrames")] [Obsolete("This is always false")] public bool? BreakOnNonKeyFrames { get; set; } diff --git a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs index 385a86d31c..09eba92d9e 100644 --- a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs +++ b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs @@ -1,14 +1,16 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Linq; +using System.Text.RegularExpressions; namespace MediaBrowser.Model.Entities; /// <summary> /// Class ProviderIdsExtensions. /// </summary> -public static class ProviderIdsExtensions +public static partial class ProviderIdsExtensions { /// <summary> /// Case-insensitive dictionary of <see cref="MetadataProvider"/> string representation. @@ -21,6 +23,27 @@ public static class ProviderIdsExtensions StringComparer.OrdinalIgnoreCase); /// <summary> + /// The known id formats, keyed by provider name. + /// </summary> + private static readonly Dictionary<string, Func<string, bool>> _providerIdValidators = + new(StringComparer.OrdinalIgnoreCase) + { + [MetadataProvider.Imdb.ToString()] = value => ImdbIdRegex().IsMatch(value), + [MetadataProvider.Tmdb.ToString()] = IsPositiveNumber, + [MetadataProvider.TmdbCollection.ToString()] = IsPositiveNumber, + [MetadataProvider.AudioDbArtist.ToString()] = IsPositiveNumber, + [MetadataProvider.AudioDbAlbum.ToString()] = IsPositiveNumber, + + // Every MusicBrainz id is an MBID. + [MetadataProvider.MusicBrainzAlbum.ToString()] = IsGuid, + [MetadataProvider.MusicBrainzAlbumArtist.ToString()] = IsGuid, + [MetadataProvider.MusicBrainzArtist.ToString()] = IsGuid, + [MetadataProvider.MusicBrainzReleaseGroup.ToString()] = IsGuid, + [MetadataProvider.MusicBrainzRecording.ToString()] = IsGuid, + [MetadataProvider.MusicBrainzTrack.ToString()] = IsGuid + }; + + /// <summary> /// Checks if this instance has an id for the given provider. /// </summary> /// <param name="instance">The instance.</param> @@ -102,6 +125,26 @@ public static class ProviderIdsExtensions } /// <summary> + /// Checks whether a value can be an id of the given provider. + /// </summary> + /// <param name="name">The provider name.</param> + /// <param name="value">The provider id.</param> + /// <returns><c>true</c> if the value has a plausible format for the provider; otherwise, <c>false</c>.</returns> + /// <remarks> + /// Providers regularly hand out an id belonging to a different service, e.g. an IMDb person id in the + /// TMDb field. Such an id is not just useless, it also makes the owning provider fail for the item. + /// </remarks> + public static bool IsValidProviderId(string? name, string? value) + { + if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(value)) + { + return false; + } + + return !_providerIdValidators.TryGetValue(name, out var isValid) || isValid(value); + } + + /// <summary> /// Sets a provider id. /// </summary> /// <param name="instance">The instance.</param> @@ -121,6 +164,14 @@ public static class ProviderIdsExtensions return false; } + name = name.Trim(); + value = value.Trim(); + + if (!IsValidProviderId(name, value)) + { + return false; + } + // Ensure it exists instance.ProviderIds ??= new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); @@ -153,7 +204,6 @@ public static class ProviderIdsExtensions /// <param name="instance">The instance.</param> /// <param name="name">The name, this should not contain a '=' character.</param> /// <param name="value">The value.</param> - /// <remarks>Due to how deserialization from the database works the name cannot contain '='.</remarks> public static void SetProviderId(this IHasProviderIds instance, string name, string value) { ArgumentNullException.ThrowIfNull(instance); @@ -166,17 +216,27 @@ public static class ProviderIdsExtensions throw new ArgumentException("Provider id name cannot contain '='", nameof(name)); } - // Ensure it exists - instance.ProviderIds ??= new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + instance.TrySetProviderId(name, value); + } - // Match on internal MetadataProvider enum string values before adding arbitrary providers - if (_metadataProviderEnumDictionary.TryGetValue(name, out var enumValue)) + /// <summary> + /// Replaces all provider ids, dropping the ones that cannot belong to the provider they are filed under. + /// </summary> + /// <param name="instance">The instance.</param> + /// <param name="providerIds">The provider ids to set.</param> + public static void SetProviderIds(this IHasProviderIds instance, IReadOnlyDictionary<string, string>? providerIds) + { + ArgumentNullException.ThrowIfNull(instance); + + instance.ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + if (providerIds is null) { - instance.ProviderIds[enumValue] = value; + return; } - else + + foreach (var (name, value) in providerIds) { - instance.ProviderIds[name] = value; + instance.TrySetProviderId(name, value); } } @@ -213,4 +273,15 @@ public static class ProviderIdsExtensions instance.ProviderIds?.Remove(provider.ToString()); } + + private static bool IsPositiveNumber(string value) + => int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out var id) && id > 0; + + private static bool IsGuid(string value) + => Guid.TryParse(value, CultureInfo.InvariantCulture, out _); + + // An IMDb id is a type prefix (tt for titles, nm for people, co for companies, ...) followed by + // digits. The prefix is optional because a bare number has always been accepted for a title. + [GeneratedRegex(@"^(tt|nm|co|ev|ch|ni)?[0-9]+$", RegexOptions.IgnoreCase)] + private static partial Regex ImdbIdRegex(); } |
