aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Common
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Common')
-rw-r--r--MediaBrowser.Common/Configuration/ConfigurationStore.cs20
-rw-r--r--MediaBrowser.Common/Configuration/IApplicationPaths.cs27
-rw-r--r--MediaBrowser.Common/Configuration/IConfigurationFactory.cs30
-rw-r--r--MediaBrowser.Common/Configuration/IConfigurationManager.cs2
-rw-r--r--MediaBrowser.Common/Configuration/IValidatingConfiguration.cs15
-rw-r--r--MediaBrowser.Common/Extensions/HttpContextExtensions.cs41
-rw-r--r--MediaBrowser.Common/IApplicationHost.cs10
-rw-r--r--MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs53
-rw-r--r--MediaBrowser.Common/Json/Converters/JsonNullableStructConverter.cs45
-rw-r--r--MediaBrowser.Common/Json/Converters/JsonNullableStructConverterFactory.cs27
-rw-r--r--MediaBrowser.Common/Json/JsonDefaults.cs45
-rw-r--r--MediaBrowser.Common/MediaBrowser.Common.csproj19
-rw-r--r--MediaBrowser.Common/Net/DefaultHttpClientHandler.cs20
-rw-r--r--MediaBrowser.Common/Net/HttpRequestOptions.cs119
-rw-r--r--MediaBrowser.Common/Net/HttpResponseInfo.cs80
-rw-r--r--MediaBrowser.Common/Net/IHttpClient.cs53
-rw-r--r--MediaBrowser.Common/Net/INetworkManager.cs49
-rw-r--r--MediaBrowser.Common/Net/NamedClient.cs18
-rw-r--r--MediaBrowser.Common/Plugins/BasePlugin.cs46
-rw-r--r--MediaBrowser.Common/Plugins/IPlugin.cs18
-rw-r--r--MediaBrowser.Common/Progress/ActionableProgress.cs17
-rw-r--r--MediaBrowser.Common/Progress/SimpleProgress.cs16
-rw-r--r--MediaBrowser.Common/Updates/IInstallationManager.cs41
-rw-r--r--MediaBrowser.Common/Updates/InstallationEventArgs.cs3
24 files changed, 417 insertions, 397 deletions
diff --git a/MediaBrowser.Common/Configuration/ConfigurationStore.cs b/MediaBrowser.Common/Configuration/ConfigurationStore.cs
new file mode 100644
index 000000000..d31d45e4c
--- /dev/null
+++ b/MediaBrowser.Common/Configuration/ConfigurationStore.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace MediaBrowser.Common.Configuration
+{
+ /// <summary>
+ /// Describes a single entry in the application configuration.
+ /// </summary>
+ public class ConfigurationStore
+ {
+ /// <summary>
+ /// Gets or sets the unique identifier for the configuration.
+ /// </summary>
+ public string Key { get; set; }
+
+ /// <summary>
+ /// Gets or sets the type used to store the data for this configuration entry.
+ /// </summary>
+ public Type ConfigurationType { get; set; }
+ }
+}
diff --git a/MediaBrowser.Common/Configuration/IApplicationPaths.cs b/MediaBrowser.Common/Configuration/IApplicationPaths.cs
index 870b90796..57c654667 100644
--- a/MediaBrowser.Common/Configuration/IApplicationPaths.cs
+++ b/MediaBrowser.Common/Configuration/IApplicationPaths.cs
@@ -1,14 +1,12 @@
-using MediaBrowser.Model.Configuration;
-
namespace MediaBrowser.Common.Configuration
{
/// <summary>
- /// Interface IApplicationPaths
+ /// Interface IApplicationPaths.
/// </summary>
public interface IApplicationPaths
{
/// <summary>
- /// Gets the path to the program data folder
+ /// Gets the path to the program data folder.
/// </summary>
/// <value>The program data path.</value>
string ProgramDataPath { get; }
@@ -17,19 +15,18 @@ namespace MediaBrowser.Common.Configuration
/// Gets the path to the web UI resources folder.
/// </summary>
/// <remarks>
- /// This value is not relevant if the server is configured to not host any static web content. Additionally,
- /// the value for <see cref="ServerConfiguration.DashboardSourcePath"/> takes precedence over this one.
+ /// This value is not relevant if the server is configured to not host any static web content.
/// </remarks>
string WebPath { get; }
/// <summary>
- /// Gets the path to the program system folder
+ /// Gets the path to the program system folder.
/// </summary>
/// <value>The program data path.</value>
string ProgramSystemPath { get; }
/// <summary>
- /// Gets the folder path to the data directory
+ /// Gets the folder path to the data directory.
/// </summary>
/// <value>The data directory.</value>
string DataPath { get; }
@@ -41,43 +38,43 @@ namespace MediaBrowser.Common.Configuration
string ImageCachePath { get; }
/// <summary>
- /// Gets the path to the plugin directory
+ /// Gets the path to the plugin directory.
/// </summary>
/// <value>The plugins path.</value>
string PluginsPath { get; }
/// <summary>
- /// Gets the path to the plugin configurations directory
+ /// Gets the path to the plugin configurations directory.
/// </summary>
/// <value>The plugin configurations path.</value>
string PluginConfigurationsPath { get; }
/// <summary>
- /// Gets the path to the log directory
+ /// Gets the path to the log directory.
/// </summary>
/// <value>The log directory path.</value>
string LogDirectoryPath { get; }
/// <summary>
- /// Gets the path to the application configuration root directory
+ /// Gets the path to the application configuration root directory.
/// </summary>
/// <value>The configuration directory path.</value>
string ConfigurationDirectoryPath { get; }
/// <summary>
- /// Gets the path to the system configuration file
+ /// Gets the path to the system configuration file.
/// </summary>
/// <value>The system configuration file path.</value>
string SystemConfigurationFilePath { get; }
/// <summary>
- /// Gets the folder path to the cache directory
+ /// Gets the folder path to the cache directory.
/// </summary>
/// <value>The cache directory.</value>
string CachePath { get; }
/// <summary>
- /// Gets the folder path to the temp directory within the cache folder
+ /// Gets the folder path to the temp directory within the cache folder.
/// </summary>
/// <value>The temp directory.</value>
string TempDirectory { get; }
diff --git a/MediaBrowser.Common/Configuration/IConfigurationFactory.cs b/MediaBrowser.Common/Configuration/IConfigurationFactory.cs
index 07ca2b58b..6db1f1364 100644
--- a/MediaBrowser.Common/Configuration/IConfigurationFactory.cs
+++ b/MediaBrowser.Common/Configuration/IConfigurationFactory.cs
@@ -1,4 +1,3 @@
-using System;
using System.Collections.Generic;
namespace MediaBrowser.Common.Configuration
@@ -15,33 +14,4 @@ namespace MediaBrowser.Common.Configuration
/// <returns>The configuration store.</returns>
IEnumerable<ConfigurationStore> GetConfigurations();
}
-
- /// <summary>
- /// Describes a single entry in the application configuration.
- /// </summary>
- public class ConfigurationStore
- {
- /// <summary>
- /// Gets or sets the unique identifier for the configuration.
- /// </summary>
- public string Key { get; set; }
-
- /// <summary>
- /// Gets or sets the type used to store the data for this configuration entry.
- /// </summary>
- public Type ConfigurationType { get; set; }
- }
-
- /// <summary>
- /// A configuration store that can be validated.
- /// </summary>
- public interface IValidatingConfiguration
- {
- /// <summary>
- /// Validation method to be invoked before saving the configuration.
- /// </summary>
- /// <param name="oldConfig">The old configuration.</param>
- /// <param name="newConfig">The new configuration.</param>
- void Validate(object oldConfig, object newConfig);
- }
}
diff --git a/MediaBrowser.Common/Configuration/IConfigurationManager.cs b/MediaBrowser.Common/Configuration/IConfigurationManager.cs
index caf2edd83..fe726090d 100644
--- a/MediaBrowser.Common/Configuration/IConfigurationManager.cs
+++ b/MediaBrowser.Common/Configuration/IConfigurationManager.cs
@@ -24,7 +24,7 @@ namespace MediaBrowser.Common.Configuration
event EventHandler<ConfigurationUpdateEventArgs> NamedConfigurationUpdated;
/// <summary>
- /// Gets or sets the application paths.
+ /// Gets the application paths.
/// </summary>
/// <value>The application paths.</value>
IApplicationPaths CommonApplicationPaths { get; }
diff --git a/MediaBrowser.Common/Configuration/IValidatingConfiguration.cs b/MediaBrowser.Common/Configuration/IValidatingConfiguration.cs
new file mode 100644
index 000000000..3b1d84f3c
--- /dev/null
+++ b/MediaBrowser.Common/Configuration/IValidatingConfiguration.cs
@@ -0,0 +1,15 @@
+namespace MediaBrowser.Common.Configuration
+{
+ /// <summary>
+ /// A configuration store that can be validated.
+ /// </summary>
+ public interface IValidatingConfiguration
+ {
+ /// <summary>
+ /// Validation method to be invoked before saving the configuration.
+ /// </summary>
+ /// <param name="oldConfig">The old configuration.</param>
+ /// <param name="newConfig">The new configuration.</param>
+ void Validate(object oldConfig, object newConfig);
+ }
+}
diff --git a/MediaBrowser.Common/Extensions/HttpContextExtensions.cs b/MediaBrowser.Common/Extensions/HttpContextExtensions.cs
new file mode 100644
index 000000000..19fa95480
--- /dev/null
+++ b/MediaBrowser.Common/Extensions/HttpContextExtensions.cs
@@ -0,0 +1,41 @@
+using System.Net;
+using Microsoft.AspNetCore.Http;
+
+namespace MediaBrowser.Common.Extensions
+{
+ /// <summary>
+ /// Static class containing extension methods for <see cref="HttpContext"/>.
+ /// </summary>
+ public static class HttpContextExtensions
+ {
+ /// <summary>
+ /// Checks the origin of the HTTP context.
+ /// </summary>
+ /// <param name="context">The incoming HTTP context.</param>
+ /// <returns><c>true</c> if the request is coming from LAN, <c>false</c> otherwise.</returns>
+ public static bool IsLocal(this HttpContext context)
+ {
+ return (context.Connection.LocalIpAddress == null
+ && context.Connection.RemoteIpAddress == null)
+ || context.Connection.LocalIpAddress.Equals(context.Connection.RemoteIpAddress);
+ }
+
+ /// <summary>
+ /// Extracts the remote IP address of the caller of the HTTP context.
+ /// </summary>
+ /// <param name="context">The HTTP context.</param>
+ /// <returns>The remote caller IP address.</returns>
+ public static string GetNormalizedRemoteIp(this HttpContext context)
+ {
+ // Default to the loopback address if no RemoteIpAddress is specified (i.e. during integration tests)
+ var ip = context.Connection.RemoteIpAddress ?? IPAddress.Loopback;
+
+ if (ip.IsIPv4MappedToIPv6)
+ {
+ ip = ip.MapToIPv4();
+ }
+
+ return ip.ToString();
+ }
+ }
+}
diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs
index e8d9282e4..849037ac4 100644
--- a/MediaBrowser.Common/IApplicationHost.cs
+++ b/MediaBrowser.Common/IApplicationHost.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Reflection;
using System.Threading.Tasks;
using MediaBrowser.Common.Plugins;
using Microsoft.Extensions.DependencyInjection;
@@ -77,6 +78,12 @@ namespace MediaBrowser.Common
IReadOnlyList<IPlugin> Plugins { get; }
/// <summary>
+ /// Gets all plugin assemblies which implement a custom rest api.
+ /// </summary>
+ /// <returns>An <see cref="IEnumerable{Assembly}"/> containing the plugin assemblies.</returns>
+ IEnumerable<Assembly> GetApiPluginAssemblies();
+
+ /// <summary>
/// Notifies the pending restart.
/// </summary>
void NotifyPendingRestart();
@@ -116,8 +123,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.
diff --git a/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs b/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs
deleted file mode 100644
index fe5dd6cd4..000000000
--- a/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs
+++ /dev/null
@@ -1,53 +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 GUID object or value to/from JSON.
- /// </summary>
- public class JsonInt32Converter : JsonConverter<int>
- {
- /// <inheritdoc />
- public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
- {
- static void ThrowFormatException() => throw new FormatException("Invalid format for an integer.");
- ReadOnlySpan<byte> span = stackalloc byte[0];
-
- if (reader.HasValueSequence)
- {
- long sequenceLength = reader.ValueSequence.Length;
- Span<byte> stackSpan = stackalloc byte[(int)sequenceLength];
- reader.ValueSequence.CopyTo(stackSpan);
- span = stackSpan;
- }
- else
- {
- span = reader.ValueSpan;
- }
-
- if (!Utf8Parser.TryParse(span, out int number, out _))
- {
- ThrowFormatException();
- }
-
- return number;
- }
-
- /// <inheritdoc />
- public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options)
- {
- static void ThrowInvalidOperationException() => throw new InvalidOperationException();
- Span<byte> span = stackalloc byte[16];
- if (Utf8Formatter.TryFormat(value, span, out int bytesWritten))
- {
- writer.WriteStringValue(span.Slice(0, bytesWritten));
- }
-
- ThrowInvalidOperationException();
- }
- }
-}
diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableStructConverter.cs b/MediaBrowser.Common/Json/Converters/JsonNullableStructConverter.cs
new file mode 100644
index 000000000..0501f7b2a
--- /dev/null
+++ b/MediaBrowser.Common/Json/Converters/JsonNullableStructConverter.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace MediaBrowser.Common.Json.Converters
+{
+ /// <summary>
+ /// Converts a nullable struct or value to/from JSON.
+ /// Required - some clients send an empty string.
+ /// </summary>
+ /// <typeparam name="TStruct">The struct type.</typeparam>
+ public class JsonNullableStructConverter<TStruct> : JsonConverter<TStruct?>
+ where TStruct : struct
+ {
+ /// <inheritdoc />
+ public override TStruct? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ if (reader.TokenType == JsonTokenType.Null)
+ {
+ return null;
+ }
+
+ // Token is empty string.
+ if (reader.TokenType == JsonTokenType.String && ((reader.HasValueSequence && reader.ValueSequence.IsEmpty) || reader.ValueSpan.IsEmpty))
+ {
+ return null;
+ }
+
+ return JsonSerializer.Deserialize<TStruct>(ref reader, options);
+ }
+
+ /// <inheritdoc />
+ public override void Write(Utf8JsonWriter writer, TStruct? value, JsonSerializerOptions options)
+ {
+ if (value.HasValue)
+ {
+ JsonSerializer.Serialize(writer, value.Value, options);
+ }
+ else
+ {
+ writer.WriteNullValue();
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableStructConverterFactory.cs b/MediaBrowser.Common/Json/Converters/JsonNullableStructConverterFactory.cs
new file mode 100644
index 000000000..d5b54e3ca
--- /dev/null
+++ b/MediaBrowser.Common/Json/Converters/JsonNullableStructConverterFactory.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace MediaBrowser.Common.Json.Converters
+{
+ /// <summary>
+ /// Json nullable struct converter factory.
+ /// </summary>
+ public class JsonNullableStructConverterFactory : JsonConverterFactory
+ {
+ /// <inheritdoc />
+ public override bool CanConvert(Type typeToConvert)
+ {
+ return typeToConvert.IsGenericType
+ && typeToConvert.GetGenericTypeDefinition() == typeof(Nullable<>)
+ && typeToConvert.GenericTypeArguments[0].IsValueType;
+ }
+
+ /// <inheritdoc />
+ public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
+ {
+ var structType = typeToConvert.GenericTypeArguments[0];
+ return (JsonConverter)Activator.CreateInstance(typeof(JsonNullableStructConverter<>).MakeGenericType(structType));
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Common/Json/JsonDefaults.cs b/MediaBrowser.Common/Json/JsonDefaults.cs
index 4a6ee0a79..6605ae962 100644
--- a/MediaBrowser.Common/Json/JsonDefaults.cs
+++ b/MediaBrowser.Common/Json/JsonDefaults.cs
@@ -10,20 +10,61 @@ namespace MediaBrowser.Common.Json
public static class JsonDefaults
{
/// <summary>
+ /// Pascal case json profile media type.
+ /// </summary>
+ public const string PascalCaseMediaType = "application/json; profile=\"PascalCase\"";
+
+ /// <summary>
+ /// Camel case json profile media type.
+ /// </summary>
+ public const string CamelCaseMediaType = "application/json; profile=\"CamelCase\"";
+
+ /// <summary>
/// Gets the default <see cref="JsonSerializerOptions" /> options.
/// </summary>
+ /// <remarks>
+ /// When changing these options, update
+ /// Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
+ /// -> AddJellyfinApi
+ /// -> AddJsonOptions.
+ /// </remarks>
/// <returns>The default <see cref="JsonSerializerOptions" /> options.</returns>
public static JsonSerializerOptions GetOptions()
{
- var options = new JsonSerializerOptions()
+ var options = new JsonSerializerOptions
{
ReadCommentHandling = JsonCommentHandling.Disallow,
- WriteIndented = false
+ WriteIndented = false,
+ DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
+ NumberHandling = JsonNumberHandling.AllowReadingFromString
};
options.Converters.Add(new JsonGuidConverter());
options.Converters.Add(new JsonStringEnumConverter());
+ options.Converters.Add(new JsonNullableStructConverterFactory());
+
+ return options;
+ }
+ /// <summary>
+ /// Gets camelCase json options.
+ /// </summary>
+ /// <returns>The camelCase <see cref="JsonSerializerOptions" /> options.</returns>
+ public static JsonSerializerOptions GetCamelCaseOptions()
+ {
+ var options = GetOptions();
+ options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
+ return options;
+ }
+
+ /// <summary>
+ /// Gets PascalCase json options.
+ /// </summary>
+ /// <returns>The PascalCase <see cref="JsonSerializerOptions" /> options.</returns>
+ public static JsonSerializerOptions GetPascalCaseOptions()
+ {
+ var options = GetOptions();
+ options.PropertyNamingPolicy = null;
return options;
}
}
diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj
index a597b9052..e716a6610 100644
--- a/MediaBrowser.Common/MediaBrowser.Common.csproj
+++ b/MediaBrowser.Common/MediaBrowser.Common.csproj
@@ -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>
@@ -17,8 +18,9 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.4" />
- <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.4" />
+ <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.9" />
+ <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.9" />
+ <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/>
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.8" />
</ItemGroup>
@@ -31,13 +33,22 @@
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <PublishRepositoryUrl>true</PublishRepositoryUrl>
+ <EmbedUntrackedSources>true</EmbedUntrackedSources>
+ <IncludeSymbols>true</IncludeSymbols>
+ <SymbolPackageFormat>snupkg</SymbolPackageFormat>
+ </PropertyGroup>
+
+ <PropertyGroup Condition=" '$(Stability)'=='Unstable'">
+ <!-- Include all symbols in the main nupkg until Azure Artifact Feed starts supporting ingesting NuGet symbol packages. -->
+ <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
</PropertyGroup>
<!-- Code analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" />
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <!-- <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> -->
+ <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/MediaBrowser.Common/Net/DefaultHttpClientHandler.cs b/MediaBrowser.Common/Net/DefaultHttpClientHandler.cs
new file mode 100644
index 000000000..e189d6e70
--- /dev/null
+++ b/MediaBrowser.Common/Net/DefaultHttpClientHandler.cs
@@ -0,0 +1,20 @@
+using System.Net;
+using System.Net.Http;
+
+namespace MediaBrowser.Common.Net
+{
+ /// <summary>
+ /// Default http client handler.
+ /// </summary>
+ public class DefaultHttpClientHandler : HttpClientHandler
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DefaultHttpClientHandler"/> class.
+ /// </summary>
+ public DefaultHttpClientHandler()
+ {
+ // TODO change to DecompressionMethods.All with .NET5
+ AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
+ }
+ }
+}
diff --git a/MediaBrowser.Common/Net/HttpRequestOptions.cs b/MediaBrowser.Common/Net/HttpRequestOptions.cs
deleted file mode 100644
index 38274a80e..000000000
--- a/MediaBrowser.Common/Net/HttpRequestOptions.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-#pragma warning disable CS1591
-
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using Microsoft.Net.Http.Headers;
-
-namespace MediaBrowser.Common.Net
-{
- /// <summary>
- /// Class HttpRequestOptions.
- /// </summary>
- public class HttpRequestOptions
- {
- /// <summary>
- /// Initializes a new instance of the <see cref="HttpRequestOptions"/> class.
- /// </summary>
- public HttpRequestOptions()
- {
- RequestHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
-
- CacheMode = CacheMode.None;
- DecompressionMethod = CompressionMethods.Deflate;
- }
-
- /// <summary>
- /// Gets or sets the URL.
- /// </summary>
- /// <value>The URL.</value>
- public string Url { get; set; }
-
- public CompressionMethods DecompressionMethod { get; set; }
-
- /// <summary>
- /// Gets or sets the accept header.
- /// </summary>
- /// <value>The accept header.</value>
- public string AcceptHeader
- {
- get => GetHeaderValue(HeaderNames.Accept);
- set => RequestHeaders[HeaderNames.Accept] = value;
- }
-
- /// <summary>
- /// Gets or sets the cancellation token.
- /// </summary>
- /// <value>The cancellation token.</value>
- public CancellationToken CancellationToken { get; set; }
-
- /// <summary>
- /// Gets or sets the user agent.
- /// </summary>
- /// <value>The user agent.</value>
- public string UserAgent
- {
- get => GetHeaderValue(HeaderNames.UserAgent);
- set => RequestHeaders[HeaderNames.UserAgent] = value;
- }
-
- /// <summary>
- /// Gets or sets the referrer.
- /// </summary>
- /// <value>The referrer.</value>
- public string Referer
- {
- get => GetHeaderValue(HeaderNames.Referer);
- set => RequestHeaders[HeaderNames.Referer] = value;
- }
-
- /// <summary>
- /// Gets or sets the host.
- /// </summary>
- /// <value>The host.</value>
- public string Host
- {
- get => GetHeaderValue(HeaderNames.Host);
- set => RequestHeaders[HeaderNames.Host] = value;
- }
-
- public Dictionary<string, string> RequestHeaders { get; private set; }
-
- public string RequestContentType { get; set; }
-
- public string RequestContent { get; set; }
-
- public bool BufferContent { get; set; }
-
- public bool LogErrorResponseBody { get; set; }
-
- public bool EnableKeepAlive { get; set; }
-
- public CacheMode CacheMode { get; set; }
-
- public TimeSpan CacheLength { get; set; }
-
- public bool EnableDefaultUserAgent { get; set; }
-
- private string GetHeaderValue(string name)
- {
- RequestHeaders.TryGetValue(name, out var value);
-
- return value;
- }
- }
-
- public enum CacheMode
- {
- None = 0,
- Unconditional = 1
- }
-
- [Flags]
- public enum CompressionMethods
- {
- None = 0b00000001,
- Deflate = 0b00000010,
- Gzip = 0b00000100
- }
-}
diff --git a/MediaBrowser.Common/Net/HttpResponseInfo.cs b/MediaBrowser.Common/Net/HttpResponseInfo.cs
deleted file mode 100644
index d4fee6c78..000000000
--- a/MediaBrowser.Common/Net/HttpResponseInfo.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using System;
-using System.IO;
-using System.Net;
-using System.Net.Http.Headers;
-
-namespace MediaBrowser.Common.Net
-{
- /// <summary>
- /// Class HttpResponseInfo.
- /// </summary>
- public sealed class HttpResponseInfo : IDisposable
- {
-#pragma warning disable CS1591
- public HttpResponseInfo()
- {
- }
-
- public HttpResponseInfo(HttpResponseHeaders headers, HttpContentHeaders contentHeader)
- {
- Headers = headers;
- ContentHeaders = contentHeader;
- }
-
-#pragma warning restore CS1591
-
- /// <summary>
- /// Gets or sets the type of the content.
- /// </summary>
- /// <value>The type of the content.</value>
- public string ContentType { get; set; }
-
- /// <summary>
- /// Gets or sets the response URL.
- /// </summary>
- /// <value>The response URL.</value>
- public string ResponseUrl { get; set; }
-
- /// <summary>
- /// Gets or sets the content.
- /// </summary>
- /// <value>The content.</value>
- public Stream Content { get; set; }
-
- /// <summary>
- /// Gets or sets the status code.
- /// </summary>
- /// <value>The status code.</value>
- public HttpStatusCode StatusCode { get; set; }
-
- /// <summary>
- /// Gets or sets the temp file path.
- /// </summary>
- /// <value>The temp file path.</value>
- public string TempFilePath { get; set; }
-
- /// <summary>
- /// Gets or sets the length of the content.
- /// </summary>
- /// <value>The length of the content.</value>
- public long? ContentLength { get; set; }
-
- /// <summary>
- /// Gets or sets the headers.
- /// </summary>
- /// <value>The headers.</value>
- public HttpResponseHeaders Headers { get; set; }
-
- /// <summary>
- /// Gets or sets the content headers.
- /// </summary>
- /// <value>The content headers.</value>
- public HttpContentHeaders ContentHeaders { get; set; }
-
- /// <inheritdoc />
- public void Dispose()
- {
- // backwards compatibility
- }
- }
-}
diff --git a/MediaBrowser.Common/Net/IHttpClient.cs b/MediaBrowser.Common/Net/IHttpClient.cs
deleted file mode 100644
index 534e22edd..000000000
--- a/MediaBrowser.Common/Net/IHttpClient.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using System;
-using System.IO;
-using System.Net.Http;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Common.Net
-{
- /// <summary>
- /// Interface IHttpClient.
- /// </summary>
- public interface IHttpClient
- {
- /// <summary>
- /// Gets the response.
- /// </summary>
- /// <param name="options">The options.</param>
- /// <returns>Task{HttpResponseInfo}.</returns>
- Task<HttpResponseInfo> GetResponse(HttpRequestOptions options);
-
- /// <summary>
- /// Gets the specified options.
- /// </summary>
- /// <param name="options">The options.</param>
- /// <returns>Task{Stream}.</returns>
- Task<Stream> Get(HttpRequestOptions options);
-
- /// <summary>
- /// Warning: Deprecated function,
- /// use 'Task{HttpResponseInfo} SendAsync(HttpRequestOptions options, HttpMethod httpMethod);' instead
- /// Sends the asynchronous.
- /// </summary>
- /// <param name="options">The options.</param>
- /// <param name="httpMethod">The HTTP method.</param>
- /// <returns>Task{HttpResponseInfo}.</returns>
- [Obsolete("Use 'Task{HttpResponseInfo} SendAsync(HttpRequestOptions options, HttpMethod httpMethod);' instead")]
- Task<HttpResponseInfo> SendAsync(HttpRequestOptions options, string httpMethod);
-
- /// <summary>
- /// Sends the asynchronous.
- /// </summary>
- /// <param name="options">The options.</param>
- /// <param name="httpMethod">The HTTP method.</param>
- /// <returns>Task{HttpResponseInfo}.</returns>
- Task<HttpResponseInfo> SendAsync(HttpRequestOptions options, HttpMethod httpMethod);
-
- /// <summary>
- /// Posts the specified options.
- /// </summary>
- /// <param name="options">The options.</param>
- /// <returns>Task{HttpResponseInfo}.</returns>
- Task<HttpResponseInfo> Post(HttpRequestOptions options);
- }
-}
diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs
index 3ba75abd8..a0330afef 100644
--- a/MediaBrowser.Common/Net/INetworkManager.cs
+++ b/MediaBrowser.Common/Net/INetworkManager.cs
@@ -11,14 +11,21 @@ namespace MediaBrowser.Common.Net
{
event EventHandler NetworkChanged;
+ /// <summary>
+ /// Gets or sets a function to return the list of user defined LAN addresses.
+ /// </summary>
Func<string[]> LocalSubnetsFn { get; set; }
/// <summary>
- /// Gets a random port number that is currently available.
+ /// Gets a random port TCP number that is currently available.
/// </summary>
/// <returns>System.Int32.</returns>
int GetRandomUnusedTcpPort();
+ /// <summary>
+ /// Gets a random port UDP number that is currently available.
+ /// </summary>
+ /// <returns>System.Int32.</returns>
int GetRandomUnusedUdpPort();
/// <summary>
@@ -35,18 +42,56 @@ namespace MediaBrowser.Common.Net
bool IsInPrivateAddressSpace(string endpoint);
/// <summary>
+ /// Determines whether [is in private address space 10.x.x.x] [the specified endpoint] and exists in the subnets returned by GetSubnets().
+ /// </summary>
+ /// <param name="endpoint">The endpoint.</param>
+ /// <returns><c>true</c> if [is in private address space 10.x.x.x] [the specified endpoint]; otherwise, <c>false</c>.</returns>
+ bool IsInPrivateAddressSpaceAndLocalSubnet(string endpoint);
+
+ /// <summary>
/// Determines whether [is in local network] [the specified endpoint].
/// </summary>
/// <param name="endpoint">The endpoint.</param>
/// <returns><c>true</c> if [is in local network] [the specified endpoint]; otherwise, <c>false</c>.</returns>
bool IsInLocalNetwork(string endpoint);
- IPAddress[] GetLocalIpAddresses(bool ignoreVirtualInterface);
+ /// <summary>
+ /// Investigates an caches a list of interface addresses, excluding local link and LAN excluded addresses.
+ /// </summary>
+ /// <returns>The list of ipaddresses.</returns>
+ IPAddress[] GetLocalIpAddresses();
+ /// <summary>
+ /// Checks if the given address falls within the ranges given in [subnets]. The addresses in subnets can be hosts or subnets in the CIDR format.
+ /// </summary>
+ /// <param name="addressString">The address to check.</param>
+ /// <param name="subnets">If true, check against addresses in the LAN settings surrounded by brackets ([]).</param>
+ /// <returns><c>true</c>if the address is in at least one of the given subnets, <c>false</c> otherwise.</returns>
bool IsAddressInSubnets(string addressString, string[] subnets);
+ /// <summary>
+ /// Returns true if address is in the LAN list in the config file.
+ /// </summary>
+ /// <param name="address">The address to check.</param>
+ /// <param name="excludeInterfaces">If true, check against addresses in the LAN settings which have [] arroud and return true if it matches the address give in address.</param>
+ /// <param name="excludeRFC">If true, returns false if address is in the 127.x.x.x or 169.128.x.x range.</param>
+ /// <returns><c>false</c>if the address isn't in the LAN list, <c>true</c> if the address has been defined as a LAN address.</returns>
+ bool IsAddressInSubnets(IPAddress address, bool excludeInterfaces, bool excludeRFC);
+
+ /// <summary>
+ /// Checks if address is in the LAN list in the config file.
+ /// </summary>
+ /// <param name="address1">Source address to check.</param>
+ /// <param name="address2">Destination address to check against.</param>
+ /// <param name="subnetMask">Destination subnet to check against.</param>
+ /// <returns><c>true/false</c>depending on whether address1 is in the same subnet as IPAddress2 with subnetMask.</returns>
bool IsInSameSubnet(IPAddress address1, IPAddress address2, IPAddress subnetMask);
+ /// <summary>
+ /// Returns the subnet mask of an interface with the given address.
+ /// </summary>
+ /// <param name="address">The address to check.</param>
+ /// <returns>Returns the subnet mask of an interface with the given address, or null if an interface match cannot be found.</returns>
IPAddress GetLocalIpSubnetMask(IPAddress address);
}
}
diff --git a/MediaBrowser.Common/Net/NamedClient.cs b/MediaBrowser.Common/Net/NamedClient.cs
new file mode 100644
index 000000000..0f6161c32
--- /dev/null
+++ b/MediaBrowser.Common/Net/NamedClient.cs
@@ -0,0 +1,18 @@
+namespace MediaBrowser.Common.Net
+{
+ /// <summary>
+ /// Registered http client names.
+ /// </summary>
+ public static class NamedClient
+ {
+ /// <summary>
+ /// Gets the value for the default named http client.
+ /// </summary>
+ public const string Default = nameof(Default);
+
+ /// <summary>
+ /// Gets the value for the MusicBrainz named http client.
+ /// </summary>
+ public const string MusicBrainz = nameof(MusicBrainz);
+ }
+}
diff --git a/MediaBrowser.Common/Plugins/BasePlugin.cs b/MediaBrowser.Common/Plugins/BasePlugin.cs
index 9e4a360c3..8545fd5dc 100644
--- a/MediaBrowser.Common/Plugins/BasePlugin.cs
+++ b/MediaBrowser.Common/Plugins/BasePlugin.cs
@@ -2,9 +2,12 @@
using System;
using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.Plugins;
using MediaBrowser.Model.Serialization;
+using Microsoft.Extensions.DependencyInjection;
namespace MediaBrowser.Common.Plugins
{
@@ -50,6 +53,12 @@ namespace MediaBrowser.Common.Plugins
public string DataFolderPath { get; private set; }
/// <summary>
+ /// Gets a value indicating whether the plugin can be uninstalled.
+ /// </summary>
+ public bool CanUninstall => !Path.GetDirectoryName(AssemblyFilePath)
+ .Equals(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), StringComparison.InvariantCulture);
+
+ /// <summary>
/// Gets the plugin info.
/// </summary>
/// <returns>PluginInfo.</returns>
@@ -60,7 +69,8 @@ namespace MediaBrowser.Common.Plugins
Name = Name,
Version = Version.ToString(),
Description = Description,
- Id = Id.ToString()
+ Id = Id.ToString(),
+ CanUninstall = CanUninstall
};
return info;
@@ -74,6 +84,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)
{
AssemblyFilePath = assemblyFilePath;
@@ -121,6 +141,30 @@ namespace MediaBrowser.Common.Plugins
{
ApplicationPaths = applicationPaths;
XmlSerializer = xmlSerializer;
+ if (this is IPluginAssembly assemblyPlugin)
+ {
+ var assembly = GetType().Assembly;
+ var assemblyName = assembly.GetName();
+ var assemblyFilePath = assembly.Location;
+
+ var dataFolderPath = Path.Combine(ApplicationPaths.PluginsPath, Path.GetFileNameWithoutExtension(assemblyFilePath));
+
+ assemblyPlugin.SetAttributes(assemblyFilePath, dataFolderPath, assemblyName.Version);
+
+ var idAttributes = assembly.GetCustomAttributes(typeof(GuidAttribute), true);
+ if (idAttributes.Length > 0)
+ {
+ var attribute = (GuidAttribute)idAttributes[0];
+ var assemblyId = new Guid(attribute.Value);
+
+ assemblyPlugin.SetId(assemblyId);
+ }
+ }
+
+ if (this is IHasPluginConfiguration hasPluginConfiguration)
+ {
+ hasPluginConfiguration.SetStartupInfo(s => Directory.CreateDirectory(s));
+ }
}
/// <summary>
diff --git a/MediaBrowser.Common/Plugins/IPlugin.cs b/MediaBrowser.Common/Plugins/IPlugin.cs
index d34820961..1844eb124 100644
--- a/MediaBrowser.Common/Plugins/IPlugin.cs
+++ b/MediaBrowser.Common/Plugins/IPlugin.cs
@@ -2,6 +2,7 @@
using System;
using MediaBrowser.Model.Plugins;
+using Microsoft.Extensions.DependencyInjection;
namespace MediaBrowser.Common.Plugins
{
@@ -41,6 +42,11 @@ namespace MediaBrowser.Common.Plugins
string AssemblyFilePath { get; }
/// <summary>
+ /// Gets a value indicating whether the plugin can be uninstalled.
+ /// </summary>
+ bool CanUninstall { get; }
+
+ /// <summary>
/// Gets the full path to the data folder, where the plugin can store any miscellaneous files needed.
/// </summary>
/// <value>The data folder path.</value>
@@ -56,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
diff --git a/MediaBrowser.Common/Progress/ActionableProgress.cs b/MediaBrowser.Common/Progress/ActionableProgress.cs
index af69055aa..d5bcd5be9 100644
--- a/MediaBrowser.Common/Progress/ActionableProgress.cs
+++ b/MediaBrowser.Common/Progress/ActionableProgress.cs
@@ -5,15 +5,16 @@ using System;
namespace MediaBrowser.Common.Progress
{
/// <summary>
- /// Class ActionableProgress
+ /// Class ActionableProgress.
/// </summary>
- /// <typeparam name="T"></typeparam>
+ /// <typeparam name="T">The type for the action parameter.</typeparam>
public class ActionableProgress<T> : IProgress<T>
{
/// <summary>
- /// The _actions
+ /// The _actions.
/// </summary>
private Action<T> _action;
+
public event EventHandler<T> ProgressChanged;
/// <summary>
@@ -32,14 +33,4 @@ namespace MediaBrowser.Common.Progress
_action?.Invoke(value);
}
}
-
- public class SimpleProgress<T> : IProgress<T>
- {
- public event EventHandler<T> ProgressChanged;
-
- public void Report(T value)
- {
- ProgressChanged?.Invoke(this, value);
- }
- }
}
diff --git a/MediaBrowser.Common/Progress/SimpleProgress.cs b/MediaBrowser.Common/Progress/SimpleProgress.cs
new file mode 100644
index 000000000..d75675bf1
--- /dev/null
+++ b/MediaBrowser.Common/Progress/SimpleProgress.cs
@@ -0,0 +1,16 @@
+#pragma warning disable CS1591
+
+using System;
+
+namespace MediaBrowser.Common.Progress
+{
+ public class SimpleProgress<T> : IProgress<T>
+ {
+ public event EventHandler<T> ProgressChanged;
+
+ public void Report(T value)
+ {
+ ProgressChanged?.Invoke(this, value);
+ }
+ }
+}
diff --git a/MediaBrowser.Common/Updates/IInstallationManager.cs b/MediaBrowser.Common/Updates/IInstallationManager.cs
index 950604432..169aca2ca 100644
--- a/MediaBrowser.Common/Updates/IInstallationManager.cs
+++ b/MediaBrowser.Common/Updates/IInstallationManager.cs
@@ -5,35 +5,34 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Plugins;
-using MediaBrowser.Model.Events;
using MediaBrowser.Model.Updates;
namespace MediaBrowser.Common.Updates
{
public interface IInstallationManager : IDisposable
{
- event EventHandler<InstallationEventArgs> PackageInstalling;
+ event EventHandler<InstallationInfo> PackageInstalling;
- event EventHandler<InstallationEventArgs> PackageInstallationCompleted;
+ event EventHandler<InstallationInfo> PackageInstallationCompleted;
event EventHandler<InstallationFailedEventArgs> PackageInstallationFailed;
- event EventHandler<InstallationEventArgs> PackageInstallationCancelled;
+ event EventHandler<InstallationInfo> PackageInstallationCancelled;
/// <summary>
/// Occurs when a plugin is uninstalled.
/// </summary>
- event EventHandler<GenericEventArgs<IPlugin>> PluginUninstalled;
+ event EventHandler<IPlugin> PluginUninstalled;
/// <summary>
/// Occurs when a plugin is updated.
/// </summary>
- event EventHandler<GenericEventArgs<(IPlugin, VersionInfo)>> PluginUpdated;
+ event EventHandler<InstallationInfo> PluginUpdated;
/// <summary>
/// Occurs when a plugin is installed.
/// </summary>
- event EventHandler<GenericEventArgs<VersionInfo>> PluginInstalled;
+ event EventHandler<InstallationInfo> PluginInstalled;
/// <summary>
/// Gets the completed installations.
@@ -41,6 +40,14 @@ namespace MediaBrowser.Common.Updates
IEnumerable<InstallationInfo> CompletedInstallations { get; }
/// <summary>
+ /// Parses a plugin manifest at the supplied URL.
+ /// </summary>
+ /// <param name="manifest">The URL to query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{IReadOnlyList{PackageInfo}}.</returns>
+ Task<IReadOnlyList<PackageInfo>> GetPackages(string manifest, CancellationToken cancellationToken = default);
+
+ /// <summary>
/// Gets all available packages.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
@@ -62,33 +69,25 @@ namespace MediaBrowser.Common.Updates
/// <summary>
/// Returns all compatible versions ordered from newest to oldest.
/// </summary>
- /// <param name="availableVersions">The available version of the plugin.</param>
- /// <param name="minVersion">The minimum required version of the plugin.</param>
- /// <returns>All compatible versions ordered from newest to oldest.</returns>
- IEnumerable<VersionInfo> GetCompatibleVersions(
- IEnumerable<VersionInfo> availableVersions,
- Version minVersion = null);
-
- /// <summary>
- /// Returns all compatible versions ordered from newest to oldest.
- /// </summary>
/// <param name="availablePackages">The available packages.</param>
/// <param name="name">The name.</param>
/// <param name="guid">The guid of the plugin.</param>
/// <param name="minVersion">The minimum required version of the plugin.</param>
+ /// <param name="specificVersion">The specific version of the plugin to install.</param>
/// <returns>All compatible versions ordered from newest to oldest.</returns>
- IEnumerable<VersionInfo> GetCompatibleVersions(
+ IEnumerable<InstallationInfo> GetCompatibleVersions(
IEnumerable<PackageInfo> availablePackages,
string name = null,
Guid guid = default,
- Version minVersion = null);
+ Version minVersion = null,
+ Version specificVersion = null);
/// <summary>
/// Returns the available plugin updates.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The available plugin updates.</returns>
- Task<IEnumerable<VersionInfo>> GetAvailablePluginUpdates(CancellationToken cancellationToken = default);
+ Task<IEnumerable<InstallationInfo>> GetAvailablePluginUpdates(CancellationToken cancellationToken = default);
/// <summary>
/// Installs the package.
@@ -96,7 +95,7 @@ namespace MediaBrowser.Common.Updates
/// <param name="package">The package.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns><see cref="Task" />.</returns>
- Task InstallPackage(VersionInfo package, CancellationToken cancellationToken = default);
+ Task InstallPackage(InstallationInfo package, CancellationToken cancellationToken = default);
/// <summary>
/// Uninstalls a plugin.
diff --git a/MediaBrowser.Common/Updates/InstallationEventArgs.cs b/MediaBrowser.Common/Updates/InstallationEventArgs.cs
index 11eb2ad34..61178f631 100644
--- a/MediaBrowser.Common/Updates/InstallationEventArgs.cs
+++ b/MediaBrowser.Common/Updates/InstallationEventArgs.cs
@@ -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; }