mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-03-16 07:06:18 +00:00
Merge remote-tracking branch 'upstream/master' into 3.1.7
This commit is contained in:
@@ -116,8 +116,7 @@ namespace MediaBrowser.Common
|
||||
/// <summary>
|
||||
/// Initializes this instance.
|
||||
/// </summary>
|
||||
/// <param name="serviceCollection">The service collection.</param>
|
||||
void Init(IServiceCollection serviceCollection);
|
||||
void Init();
|
||||
|
||||
/// <summary>
|
||||
/// Creates the instance.
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Buffers.Text;
|
||||
using System.Globalization;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace MediaBrowser.Common.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Double to String JSON converter.
|
||||
/// Web client send quoted doubles.
|
||||
/// </summary>
|
||||
public class JsonDoubleConverter : JsonConverter<double>
|
||||
{
|
||||
/// <summary>
|
||||
/// Read JSON string as double.
|
||||
/// </summary>
|
||||
/// <param name="reader"><see cref="Utf8JsonReader"/>.</param>
|
||||
/// <param name="typeToConvert">Type.</param>
|
||||
/// <param name="options">Options.</param>
|
||||
/// <returns>Parsed value.</returns>
|
||||
public override double Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.String)
|
||||
{
|
||||
// try to parse number directly from bytes
|
||||
var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
|
||||
if (Utf8Parser.TryParse(span, out double number, out var bytesConsumed) && span.Length == bytesConsumed)
|
||||
{
|
||||
return number;
|
||||
}
|
||||
|
||||
// try to parse from a string if the above failed, this covers cases with other escaped/UTF characters
|
||||
if (double.TryParse(reader.GetString(), out number))
|
||||
{
|
||||
return number;
|
||||
}
|
||||
}
|
||||
|
||||
// fallback to default handling
|
||||
return reader.GetDouble();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write double to JSON string.
|
||||
/// </summary>
|
||||
/// <param name="writer"><see cref="Utf8JsonWriter"/>.</param>
|
||||
/// <param name="value">Value to write.</param>
|
||||
/// <param name="options">Options.</param>
|
||||
public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteNumberValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Buffers.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace MediaBrowser.Common.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a int32 object or value to/from JSON.
|
||||
/// </summary>
|
||||
public class JsonInt32Converter : JsonConverter<int>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.String)
|
||||
{
|
||||
ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
|
||||
if (Utf8Parser.TryParse(span, out int number, out int bytesConsumed) && span.Length == bytesConsumed)
|
||||
{
|
||||
return number;
|
||||
}
|
||||
|
||||
if (int.TryParse(reader.GetString(), out number))
|
||||
{
|
||||
return number;
|
||||
}
|
||||
}
|
||||
|
||||
return reader.GetInt32();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteNumberValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Buffers.Text;
|
||||
using System.Globalization;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace MediaBrowser.Common.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Parse JSON string as long.
|
||||
/// Javascript does not support 64-bit integers.
|
||||
/// </summary>
|
||||
public class JsonInt64Converter : JsonConverter<long>
|
||||
{
|
||||
/// <summary>
|
||||
/// Read JSON string as int64.
|
||||
/// </summary>
|
||||
/// <param name="reader"><see cref="Utf8JsonReader"/>.</param>
|
||||
/// <param name="type">Type.</param>
|
||||
/// <param name="options">Options.</param>
|
||||
/// <returns>Parsed value.</returns>
|
||||
public override long Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.String)
|
||||
{
|
||||
// try to parse number directly from bytes
|
||||
var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
|
||||
if (Utf8Parser.TryParse(span, out long number, out var bytesConsumed) && span.Length == bytesConsumed)
|
||||
{
|
||||
return number;
|
||||
}
|
||||
|
||||
// try to parse from a string if the above failed, this covers cases with other escaped/UTF characters
|
||||
if (long.TryParse(reader.GetString(), out number))
|
||||
{
|
||||
return number;
|
||||
}
|
||||
}
|
||||
|
||||
// fallback to default handling
|
||||
return reader.GetInt64();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write long to JSON long.
|
||||
/// </summary>
|
||||
/// <param name="writer"><see cref="Utf8JsonWriter"/>.</param>
|
||||
/// <param name="value">Value to write.</param>
|
||||
/// <param name="options">Options.</param>
|
||||
public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteNumberValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace MediaBrowser.Common.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converter for Dictionaries without string key.
|
||||
/// TODO This can be removed when System.Text.Json supports Dictionaries with non-string keys.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">Type of key.</typeparam>
|
||||
/// <typeparam name="TValue">Type of value.</typeparam>
|
||||
internal sealed class JsonNonStringKeyDictionaryConverter<TKey, TValue> : JsonConverter<IDictionary<TKey, TValue>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Read JSON.
|
||||
/// </summary>
|
||||
/// <param name="reader">The Utf8JsonReader.</param>
|
||||
/// <param name="typeToConvert">The type to convert.</param>
|
||||
/// <param name="options">The json serializer options.</param>
|
||||
/// <returns>Typed dictionary.</returns>
|
||||
/// <exception cref="NotSupportedException">Dictionary key type not supported.</exception>
|
||||
public override IDictionary<TKey, TValue> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
var convertedType = typeof(Dictionary<,>).MakeGenericType(typeof(string), typeToConvert.GenericTypeArguments[1]);
|
||||
var value = JsonSerializer.Deserialize(ref reader, convertedType, options);
|
||||
var instance = (Dictionary<TKey, TValue>)Activator.CreateInstance(
|
||||
typeToConvert,
|
||||
BindingFlags.Instance | BindingFlags.Public,
|
||||
null,
|
||||
null,
|
||||
CultureInfo.CurrentCulture);
|
||||
var enumerator = (IEnumerator)convertedType.GetMethod("GetEnumerator")!.Invoke(value, null);
|
||||
var parse = typeof(TKey).GetMethod(
|
||||
"Parse",
|
||||
0,
|
||||
BindingFlags.Public | BindingFlags.Static,
|
||||
null,
|
||||
CallingConventions.Any,
|
||||
new[] { typeof(string) },
|
||||
null);
|
||||
if (parse == null)
|
||||
{
|
||||
throw new NotSupportedException($"{typeof(TKey)} as TKey in IDictionary<TKey, TValue> is not supported.");
|
||||
}
|
||||
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
var element = (KeyValuePair<string?, TValue>)enumerator.Current;
|
||||
instance.Add((TKey)parse.Invoke(null, new[] { (object?)element.Key }), element.Value);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write dictionary as Json.
|
||||
/// </summary>
|
||||
/// <param name="writer">The Utf8JsonWriter.</param>
|
||||
/// <param name="value">The dictionary value.</param>
|
||||
/// <param name="options">The Json serializer options.</param>
|
||||
public override void Write(Utf8JsonWriter writer, IDictionary<TKey, TValue> value, JsonSerializerOptions options)
|
||||
{
|
||||
var convertedDictionary = new Dictionary<string?, TValue>(value.Count);
|
||||
foreach (var (k, v) in value)
|
||||
{
|
||||
if (k != null)
|
||||
{
|
||||
convertedDictionary[k.ToString()] = v;
|
||||
}
|
||||
}
|
||||
|
||||
JsonSerializer.Serialize(writer, convertedDictionary, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace MediaBrowser.Common.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// https://github.com/dotnet/runtime/issues/30524#issuecomment-524619972.
|
||||
/// TODO This can be removed when System.Text.Json supports Dictionaries with non-string keys.
|
||||
/// </summary>
|
||||
internal sealed class JsonNonStringKeyDictionaryConverterFactory : JsonConverterFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Only convert objects that implement IDictionary and do not have string keys.
|
||||
/// </summary>
|
||||
/// <param name="typeToConvert">Type convert.</param>
|
||||
/// <returns>Conversion ability.</returns>
|
||||
public override bool CanConvert(Type typeToConvert)
|
||||
{
|
||||
if (!typeToConvert.IsGenericType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Let built in converter handle string keys
|
||||
if (typeToConvert.GenericTypeArguments[0] == typeof(string))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only support objects that implement IDictionary
|
||||
return typeToConvert.GetInterface(nameof(IDictionary)) != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create converter for generic dictionary type.
|
||||
/// </summary>
|
||||
/// <param name="typeToConvert">Type to convert.</param>
|
||||
/// <param name="options">Json serializer options.</param>
|
||||
/// <returns>JsonConverter for given type.</returns>
|
||||
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
var converterType = typeof(JsonNonStringKeyDictionaryConverter<,>)
|
||||
.MakeGenericType(typeToConvert.GenericTypeArguments[0], typeToConvert.GenericTypeArguments[1]);
|
||||
var converter = (JsonConverter)Activator.CreateInstance(
|
||||
converterType,
|
||||
BindingFlags.Instance | BindingFlags.Public,
|
||||
null,
|
||||
null,
|
||||
CultureInfo.CurrentCulture);
|
||||
return converter;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Buffers.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace MediaBrowser.Common.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a nullable int32 object or value to/from JSON.
|
||||
/// </summary>
|
||||
public class JsonNullableInt32Converter : JsonConverter<int?>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override int? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.String)
|
||||
{
|
||||
ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
|
||||
if (Utf8Parser.TryParse(span, out int number, out int bytesConsumed) && span.Length == bytesConsumed)
|
||||
{
|
||||
return number;
|
||||
}
|
||||
|
||||
var stringValue = reader.GetString().AsSpan();
|
||||
|
||||
// value is null or empty, just return null.
|
||||
if (stringValue.IsEmpty)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (int.TryParse(stringValue, out number))
|
||||
{
|
||||
return number;
|
||||
}
|
||||
}
|
||||
|
||||
return reader.GetInt32();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Write(Utf8JsonWriter writer, int? value, JsonSerializerOptions options)
|
||||
{
|
||||
if (value is null)
|
||||
{
|
||||
writer.WriteNullValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteNumberValue(value.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Buffers.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace MediaBrowser.Common.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Parse JSON string as nullable long.
|
||||
/// Javascript does not support 64-bit integers.
|
||||
/// </summary>
|
||||
public class JsonNullableInt64Converter : JsonConverter<long?>
|
||||
{
|
||||
/// <summary>
|
||||
/// Read JSON string as int64.
|
||||
/// </summary>
|
||||
/// <param name="reader"><see cref="Utf8JsonReader"/>.</param>
|
||||
/// <param name="type">Type.</param>
|
||||
/// <param name="options">Options.</param>
|
||||
/// <returns>Parsed value.</returns>
|
||||
public override long? Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.String)
|
||||
{
|
||||
// try to parse number directly from bytes
|
||||
var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
|
||||
if (Utf8Parser.TryParse(span, out long number, out var bytesConsumed) && span.Length == bytesConsumed)
|
||||
{
|
||||
return number;
|
||||
}
|
||||
|
||||
var stringValue = reader.GetString().AsSpan();
|
||||
|
||||
// value is null or empty, just return null.
|
||||
if (stringValue.IsEmpty)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// try to parse from a string if the above failed, this covers cases with other escaped/UTF characters
|
||||
if (long.TryParse(stringValue, out number))
|
||||
{
|
||||
return number;
|
||||
}
|
||||
}
|
||||
|
||||
// fallback to default handling
|
||||
return reader.GetInt64();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write long to JSON long.
|
||||
/// </summary>
|
||||
/// <param name="writer"><see cref="Utf8JsonWriter"/>.</param>
|
||||
/// <param name="value">Value to write.</param>
|
||||
/// <param name="options">Options.</param>
|
||||
public override void Write(Utf8JsonWriter writer, long? value, JsonSerializerOptions options)
|
||||
{
|
||||
if (value is null)
|
||||
{
|
||||
writer.WriteNullValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteNumberValue(value.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,17 +25,12 @@ namespace MediaBrowser.Common.Json
|
||||
{
|
||||
ReadCommentHandling = JsonCommentHandling.Disallow,
|
||||
WriteIndented = false,
|
||||
IgnoreNullValues = true
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
NumberHandling = JsonNumberHandling.AllowReadingFromString
|
||||
};
|
||||
|
||||
options.Converters.Add(new JsonGuidConverter());
|
||||
options.Converters.Add(new JsonInt32Converter());
|
||||
options.Converters.Add(new JsonNullableInt32Converter());
|
||||
options.Converters.Add(new JsonStringEnumConverter());
|
||||
options.Converters.Add(new JsonNonStringKeyDictionaryConverterFactory());
|
||||
options.Converters.Add(new JsonInt64Converter());
|
||||
options.Converters.Add(new JsonNullableInt64Converter());
|
||||
options.Converters.Add(new JsonDoubleConverter());
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
<PropertyGroup>
|
||||
<Authors>Jellyfin Contributors</Authors>
|
||||
<PackageId>Jellyfin.Common</PackageId>
|
||||
<PackageLicenseUrl>https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt</PackageLicenseUrl>
|
||||
<VersionPrefix>10.7.0</VersionPrefix>
|
||||
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Reflection;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Model.Plugins;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace MediaBrowser.Common.Plugins
|
||||
{
|
||||
@@ -81,6 +82,16 @@ namespace MediaBrowser.Common.Plugins
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void RegisterServices(IServiceCollection serviceCollection)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void UnregisterServices(IServiceCollection serviceCollection)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SetAttributes(string assemblyFilePath, string dataFolderPath, Version assemblyVersion)
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using System;
|
||||
using MediaBrowser.Model.Plugins;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace MediaBrowser.Common.Plugins
|
||||
{
|
||||
@@ -61,6 +62,18 @@ namespace MediaBrowser.Common.Plugins
|
||||
/// Called when just before the plugin is uninstalled from the server.
|
||||
/// </summary>
|
||||
void OnUninstalling();
|
||||
|
||||
/// <summary>
|
||||
/// Registers the plugin's services to the service collection.
|
||||
/// </summary>
|
||||
/// <param name="serviceCollection">The service collection.</param>
|
||||
void RegisterServices(IServiceCollection serviceCollection);
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters the plugin's services from the service collection.
|
||||
/// </summary>
|
||||
/// <param name="serviceCollection">The service collection.</param>
|
||||
void UnregisterServices(IServiceCollection serviceCollection);
|
||||
}
|
||||
|
||||
public interface IHasPluginConfiguration
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using MediaBrowser.Model.Updates;
|
||||
|
||||
namespace MediaBrowser.Common.Updates
|
||||
{
|
||||
public class InstallationEventArgs
|
||||
public class InstallationEventArgs : EventArgs
|
||||
{
|
||||
public InstallationInfo InstallationInfo { get; set; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user