@ -4,6 +4,7 @@ using System;
using System.Collections.Concurrent ;
using System.Collections.Generic ;
using System.Diagnostics ;
using System.Globalization ;
using System.IO ;
using System.Linq ;
using System.Net ;
@ -37,10 +38,11 @@ using Emby.Server.Implementations.LiveTv;
using Emby.Server.Implementations.Localization ;
using Emby.Server.Implementations.Net ;
using Emby.Server.Implementations.Playlists ;
using Emby.Server.Implementations.Plugins ;
using Emby.Server.Implementations.QuickConnect ;
using Emby.Server.Implementations.ScheduledTasks ;
using Emby.Server.Implementations.Security ;
using Emby.Server.Implementations.Serialization ;
using Emby.Server.Implementations.Services ;
using Emby.Server.Implementations.Session ;
using Emby.Server.Implementations.SyncPlay ;
using Emby.Server.Implementations.TV ;
@ -49,11 +51,11 @@ using Jellyfin.Api.Helpers;
using MediaBrowser.Common ;
using MediaBrowser.Common.Configuration ;
using MediaBrowser.Common.Events ;
using MediaBrowser.Common.Json ;
using MediaBrowser.Common.Net ;
using MediaBrowser.Common.Plugins ;
using MediaBrowser.Common.Updates ;
using MediaBrowser.Controller ;
using MediaBrowser.Controller.Authentication ;
using MediaBrowser.Controller.Channels ;
using MediaBrowser.Controller.Chapters ;
using MediaBrowser.Controller.Collections ;
@ -72,6 +74,7 @@ using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Playlists ;
using MediaBrowser.Controller.Plugins ;
using MediaBrowser.Controller.Providers ;
using MediaBrowser.Controller.QuickConnect ;
using MediaBrowser.Controller.Resolvers ;
using MediaBrowser.Controller.Security ;
using MediaBrowser.Controller.Session ;
@ -89,19 +92,20 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo ;
using MediaBrowser.Model.Net ;
using MediaBrowser.Model.Serialization ;
using MediaBrowser.Model.Services ;
using MediaBrowser.Model.System ;
using MediaBrowser.Model.Tasks ;
using MediaBrowser.Providers.Chapters ;
using MediaBrowser.Providers.Manager ;
using MediaBrowser.Providers.Plugins.TheTvdb ;
using MediaBrowser.Providers.Plugins.Tmdb ;
using MediaBrowser.Providers.Subtitles ;
using MediaBrowser.XbmcMetadata.Providers ;
using Microsoft.AspNetCore. Http ;
using Microsoft.AspNetCore. Mvc ;
using Microsoft.Extensions.DependencyInjection ;
using Microsoft.Extensions.Logging ;
using Prometheus.DotNetRuntime ;
using OperatingSystem = MediaBrowser . Common . System . OperatingSystem ;
using WebSocketManager = Emby . Server . Implementations . HttpServer . WebSocketManager ;
namespace Emby.Server.Implementations
{
@ -118,18 +122,22 @@ namespace Emby.Server.Implementations
private readonly IFileSystem _fileSystemManager ;
private readonly INetworkManager _networkManager ;
private readonly IXmlSerializer _xmlSerializer ;
private readonly IJsonSerializer _jsonSerializer ;
private readonly IStartupOptions _startupOptions ;
private IMediaEncoder _mediaEncoder ;
private ISessionManager _sessionManager ;
private IHttpServer _httpServer ;
private IHttpClient _httpClient ;
private IHttpClientFactory _httpClientFactory ;
private string [ ] _urlPrefixes ;
/// <summary>
/// Gets a value indicating whether this instance can self restart.
/// </summary>
public bool CanSelfRestart = > _startupOptions . RestartPath ! = null ;
public bool CoreStartupHasCompleted { get ; private set ; }
public virtual bool CanLaunchWebBrowser
{
get
@ -173,6 +181,8 @@ namespace Emby.Server.Implementations
/// </summary>
protected ILogger < ApplicationHost > Logger { get ; }
protected IServiceCollection ServiceCollection { get ; }
private IPlugin [ ] _plugins ;
/// <summary>
@ -231,16 +241,26 @@ namespace Emby.Server.Implementations
public IServerConfigurationManager ServerConfigurationManager = > ( IServerConfigurationManager ) ConfigurationManager ;
/// <summary>
/// Initializes a new instance of the <see cref="ApplicationHost" /> class.
/// Initializes a new instance of the <see cref="ApplicationHost" /> class.
/// </summary>
/// <param name="applicationPaths">Instance of the <see cref="IServerApplicationPaths"/> interface.</param>
/// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param>
/// <param name="options">Instance of the <see cref="IStartupOptions"/> interface.</param>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
/// <param name="networkManager">Instance of the <see cref="INetworkManager"/> interface.</param>
/// <param name="serviceCollection">Instance of the <see cref="IServiceCollection"/> interface.</param>
public ApplicationHost (
IServerApplicationPaths applicationPaths ,
ILoggerFactory loggerFactory ,
IStartupOptions options ,
IFileSystem fileSystem ,
INetworkManager networkManager )
INetworkManager networkManager ,
IServiceCollection serviceCollection )
{
_xmlSerializer = new MyXmlSerializer ( ) ;
_jsonSerializer = new JsonSerializer ( ) ;
ServiceCollection = serviceCollection ;
_networkManager = networkManager ;
networkManager . LocalSubnetsFn = GetConfiguredLocalSubnets ;
@ -271,6 +291,10 @@ namespace Emby.Server.Implementations
Password = ServerConfigurationManager . Configuration . CertificatePassword
} ;
Certificate = GetCertificate ( CertificateInfo ) ;
ApplicationVersion = typeof ( ApplicationHost ) . Assembly . GetName ( ) . Version ;
ApplicationVersionString = ApplicationVersion . ToString ( 3 ) ;
ApplicationUserAgent = Name . Replace ( ' ' , '-' ) + "/" + ApplicationVersionString ;
}
public string ExpandVirtualPath ( string path )
@ -300,22 +324,22 @@ namespace Emby.Server.Implementations
}
/// <inheritdoc />
public Version ApplicationVersion { get ; } = typeof ( ApplicationHost ) . Assembly . GetName ( ) . Version ;
public Version ApplicationVersion { get ; }
/// <inheritdoc />
public string ApplicationVersionString { get ; } = typeof ( ApplicationHost ) . Assembly . GetName ( ) . Version . ToString ( 3 ) ;
public string ApplicationVersionString { get ; }
/// <summary>
/// Gets the current application user agent.
/// </summary>
/// <value>The application user agent.</value>
public string ApplicationUserAgent => Name . Replace ( ' ' , '-' ) + "/" + ApplicationVersionString ;
public string ApplicationUserAgent { get ; }
/// <summary>
/// Gets the email address for use within a comment section of a user agent field.
/// Presently used to provide contact information to MusicBrainz service.
/// </summary>
public string ApplicationUserAgentAddress { get ; } = "team@jellyfin.org" ;
public string ApplicationUserAgentAddress => "team@jellyfin.org" ;
/// <summary>
/// Gets the current application name.
@ -379,7 +403,7 @@ namespace Emby.Server.Implementations
/// <summary>
/// Resolves this instance.
/// </summary>
/// <typeparam name="T">The type </typeparam>
/// <typeparam name="T">The type . </typeparam>
/// <returns>``0.</returns>
public T Resolve < T > ( ) = > ServiceProvider . GetService < T > ( ) ;
@ -440,8 +464,7 @@ namespace Emby.Server.Implementations
Logger . LogInformation ( "Executed all pre-startup entry points in {Elapsed:g}" , stopWatch . Elapsed ) ;
Logger . LogInformation ( "Core startup complete" ) ;
_httpServer . GlobalResponse = null ;
CoreStartupHasCompleted = true ;
stopWatch . Restart ( ) ;
await Task . WhenAll ( StartEntryPoints ( entryPoints , false ) ) . ConfigureAwait ( false ) ;
Logger . LogInformation ( "Executed all post-startup entry points in {Elapsed:g}" , stopWatch . Elapsed ) ;
@ -464,7 +487,7 @@ namespace Emby.Server.Implementations
}
/// <inheritdoc/>
public void Init ( IServiceCollection serviceCollection )
public void Init ( )
{
HttpPort = ServerConfigurationManager . Configuration . HttpServerPortNumber ;
HttpsPort = ServerConfigurationManager . Configuration . HttpsPortNumber ;
@ -493,145 +516,142 @@ namespace Emby.Server.Implementations
DiscoverTypes ( ) ;
RegisterServices ( serviceCollection ) ;
RegisterServices ( ) ;
}
public Task ExecuteHttpHandlerAsync ( HttpContext context , Func < Task > next )
= > _httpServer . RequestHandler ( context ) ;
/// <summary>
/// Registers services/resources with the service collection that will be available via DI.
/// </summary>
protected virtual void RegisterServices ( IServiceCollection serviceCollection )
protected virtual void RegisterServices ( )
{
serviceCollection . AddSingleton ( _startupOptions ) ;
serviceCollection . AddMemoryCache ( ) ;
serviceCollection . AddSingleton ( ConfigurationManager ) ;
serviceCollection . AddSingleton < IApplicationHost > ( this ) ;
ServiceCollection . AddSingleton ( _startupOptions ) ;
serviceCollection. AddSingleton < IApplicationPaths > ( ApplicationPaths ) ;
ServiceCollection . AddMemoryCache ( ) ;
serviceCollection . AddSingleton < IJsonSerializer , JsonSerializer > ( ) ;
ServiceCollection . AddSingleton ( ConfigurationManager ) ;
ServiceCollection . AddSingleton < IApplicationHost > ( this ) ;
serviceCollection . AddSingleton ( _fileSystemManager ) ;
serviceCollection . AddSingleton < TvdbClientManager > ( ) ;
ServiceCollection . AddSingleton < IApplicationPaths > ( ApplicationPaths ) ;
serviceCollection. AddSingleton < IHttpClient , HttpClientManager . HttpClientManag er> ( ) ;
ServiceCollection. AddSingleton < IJsonSerializer , JsonSerializ er> ( ) ;
serviceCollection . AddSingleton ( _networkManager ) ;
ServiceCollection . AddSingleton ( _fileSystemManager ) ;
ServiceCollection . AddSingleton < TvdbClientManager > ( ) ;
ServiceCollection . AddSingleton < TmdbClientManager > ( ) ;
serviceCollection . AddSingleton < IIsoManager , IsoManager > ( ) ;
ServiceCollection. AddSingleton ( _networkManager ) ;
serviceCollection. AddSingleton < ITaskManager , Task Manager> ( ) ;
ServiceCollection. AddSingleton < IIsoManager , Iso Manager> ( ) ;
serviceCollection. AddSingleton ( _xmlSerializer ) ;
ServiceCollection. AddSingleton < ITaskManager , TaskManager > ( ) ;
serviceCollection. AddSingleton < IStreamHelper , StreamHelper > ( ) ;
ServiceCollection. AddSingleton ( _xmlSerializer ) ;
serviceCollection. AddSingleton < ICryptoProvider , CryptographyProvid er> ( ) ;
ServiceCollection. AddSingleton < IStreamHelper , StreamHelp er> ( ) ;
serviceCollection. AddSingleton < ISocketFactory , SocketFactory > ( ) ;
ServiceCollection. AddSingleton < ICryptoProvider , CryptographyProvider > ( ) ;
serviceCollection. AddSingleton < IInstallationManager , InstallationManager > ( ) ;
ServiceCollection. AddSingleton < ISocketFactory , SocketFactory > ( ) ;
serviceCollection. AddSingleton < IZipClient , ZipClient > ( ) ;
ServiceCollection. AddSingleton < IInstallationManager , InstallationManager > ( ) ;
serviceCollection. AddSingleton < IHttpResultFactory , HttpResultFactory > ( ) ;
ServiceCollection. AddSingleton < IZipClient , ZipClient > ( ) ;
s erviceCollection. AddSingleton < IServerApplicationHost > ( this ) ;
s erviceCollection. AddSingleton < IServerApplicationPaths > ( ApplicationPaths ) ;
S erviceCollection. AddSingleton < IServerApplicationHost > ( this ) ;
S erviceCollection. AddSingleton < IServerApplicationPaths > ( ApplicationPaths ) ;
s erviceCollection. AddSingleton ( ServerConfigurationManager ) ;
S erviceCollection. AddSingleton ( ServerConfigurationManager ) ;
s erviceCollection. AddSingleton < ILocalizationManager , LocalizationManager > ( ) ;
S erviceCollection. AddSingleton < ILocalizationManager , LocalizationManager > ( ) ;
s erviceCollection. AddSingleton < IBlurayExaminer , BdInfoExaminer > ( ) ;
S erviceCollection. AddSingleton < IBlurayExaminer , BdInfoExaminer > ( ) ;
s erviceCollection. AddSingleton < IUserDataRepository , SqliteUserDataRepository > ( ) ;
s erviceCollection. AddSingleton < IUserDataManager , UserDataManager > ( ) ;
S erviceCollection. AddSingleton < IUserDataRepository , SqliteUserDataRepository > ( ) ;
S erviceCollection. AddSingleton < IUserDataManager , UserDataManager > ( ) ;
s erviceCollection. AddSingleton < IItemRepository , SqliteItemRepository > ( ) ;
S erviceCollection. AddSingleton < IItemRepository , SqliteItemRepository > ( ) ;
s erviceCollection. AddSingleton < IAuthenticationRepository , AuthenticationRepository > ( ) ;
S erviceCollection. AddSingleton < IAuthenticationRepository , AuthenticationRepository > ( ) ;
// TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
s erviceCollection. AddTransient ( provider = > new Lazy < IDtoService > ( provider . GetRequiredService < IDtoService > ) ) ;
S erviceCollection. AddTransient ( provider = > new Lazy < IDtoService > ( provider . GetRequiredService < IDtoService > ) ) ;
// TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
s erviceCollection. AddTransient ( provider = > new Lazy < EncodingHelper > ( provider . GetRequiredService < EncodingHelper > ) ) ;
s erviceCollection. AddSingleton < IMediaEncoder , MediaBrowser . MediaEncoding . Encoder . MediaEncoder > ( ) ;
S erviceCollection. AddTransient ( provider = > new Lazy < EncodingHelper > ( provider . GetRequiredService < EncodingHelper > ) ) ;
S erviceCollection. AddSingleton < IMediaEncoder , MediaBrowser . MediaEncoding . Encoder . MediaEncoder > ( ) ;
// TODO: Refactor to eliminate the circular dependencies here so that Lazy<T> isn't required
s erviceCollection. AddTransient ( provider = > new Lazy < ILibraryMonitor > ( provider . GetRequiredService < ILibraryMonitor > ) ) ;
s erviceCollection. AddTransient ( provider = > new Lazy < IProviderManager > ( provider . GetRequiredService < IProviderManager > ) ) ;
s erviceCollection. AddTransient ( provider = > new Lazy < IUserViewManager > ( provider . GetRequiredService < IUserViewManager > ) ) ;
s erviceCollection. AddSingleton < ILibraryManager , LibraryManager > ( ) ;
S erviceCollection. AddTransient ( provider = > new Lazy < ILibraryMonitor > ( provider . GetRequiredService < ILibraryMonitor > ) ) ;
S erviceCollection. AddTransient ( provider = > new Lazy < IProviderManager > ( provider . GetRequiredService < IProviderManager > ) ) ;
S erviceCollection. AddTransient ( provider = > new Lazy < IUserViewManager > ( provider . GetRequiredService < IUserViewManager > ) ) ;
S erviceCollection. AddSingleton < ILibraryManager , LibraryManager > ( ) ;
s erviceCollection. AddSingleton < IMusicManager , MusicManager > ( ) ;
S erviceCollection. AddSingleton < IMusicManager , MusicManager > ( ) ;
s erviceCollection. AddSingleton < ILibraryMonitor , LibraryMonitor > ( ) ;
S erviceCollection. AddSingleton < ILibraryMonitor , LibraryMonitor > ( ) ;
s erviceCollection. AddSingleton < ISearchEngine , SearchEngine > ( ) ;
S erviceCollection. AddSingleton < ISearchEngine , SearchEngine > ( ) ;
serviceCollection . AddSingleton < ServiceController > ( ) ;
serviceCollection . AddSingleton < IHttpServer , HttpListenerHost > ( ) ;
ServiceCollection . AddSingleton < IWebSocketManager , WebSocketManager > ( ) ;
s erviceCollection. AddSingleton < IImageProcessor , ImageProcessor > ( ) ;
S erviceCollection. AddSingleton < IImageProcessor , ImageProcessor > ( ) ;
s erviceCollection. AddSingleton < ITVSeriesManager , TVSeriesManager > ( ) ;
S erviceCollection. AddSingleton < ITVSeriesManager , TVSeriesManager > ( ) ;
s erviceCollection. AddSingleton < IDeviceManager , DeviceManager > ( ) ;
S erviceCollection. AddSingleton < IDeviceManager , DeviceManager > ( ) ;
s erviceCollection. AddSingleton < IMediaSourceManager , MediaSourceManager > ( ) ;
S erviceCollection. AddSingleton < IMediaSourceManager , MediaSourceManager > ( ) ;
s erviceCollection. AddSingleton < ISubtitleManager , SubtitleManager > ( ) ;
S erviceCollection. AddSingleton < ISubtitleManager , SubtitleManager > ( ) ;
s erviceCollection. AddSingleton < IProviderManager , ProviderManager > ( ) ;
S erviceCollection. AddSingleton < IProviderManager , ProviderManager > ( ) ;
// TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
s erviceCollection. AddTransient ( provider = > new Lazy < ILiveTvManager > ( provider . GetRequiredService < ILiveTvManager > ) ) ;
s erviceCollection. AddSingleton < IDtoService , DtoService > ( ) ;
S erviceCollection. AddTransient ( provider = > new Lazy < ILiveTvManager > ( provider . GetRequiredService < ILiveTvManager > ) ) ;
S erviceCollection. AddSingleton < IDtoService , DtoService > ( ) ;
s erviceCollection. AddSingleton < IChannelManager , ChannelManager > ( ) ;
S erviceCollection. AddSingleton < IChannelManager , ChannelManager > ( ) ;
s erviceCollection. AddSingleton < ISessionManager , SessionManager > ( ) ;
S erviceCollection. AddSingleton < ISessionManager , SessionManager > ( ) ;
s erviceCollection. AddSingleton < IDlnaManager , DlnaManager > ( ) ;
S erviceCollection. AddSingleton < IDlnaManager , DlnaManager > ( ) ;
s erviceCollection. AddSingleton < ICollectionManager , CollectionManager > ( ) ;
S erviceCollection. AddSingleton < ICollectionManager , CollectionManager > ( ) ;
s erviceCollection. AddSingleton < IPlaylistManager , PlaylistManager > ( ) ;
S erviceCollection. AddSingleton < IPlaylistManager , PlaylistManager > ( ) ;
s erviceCollection. AddSingleton < ISyncPlayManager , SyncPlayManager > ( ) ;
S erviceCollection. AddSingleton < ISyncPlayManager , SyncPlayManager > ( ) ;
s erviceCollection. AddSingleton < LiveTvDtoService > ( ) ;
s erviceCollection. AddSingleton < ILiveTvManager , LiveTvManager > ( ) ;
S erviceCollection. AddSingleton < LiveTvDtoService > ( ) ;
S erviceCollection. AddSingleton < ILiveTvManager , LiveTvManager > ( ) ;
s erviceCollection. AddSingleton < IUserViewManager , UserViewManager > ( ) ;
S erviceCollection. AddSingleton < IUserViewManager , UserViewManager > ( ) ;
s erviceCollection. AddSingleton < INotificationManager , NotificationManager > ( ) ;
S erviceCollection. AddSingleton < INotificationManager , NotificationManager > ( ) ;
s erviceCollection. AddSingleton < IDeviceDiscovery , DeviceDiscovery > ( ) ;
S erviceCollection. AddSingleton < IDeviceDiscovery , DeviceDiscovery > ( ) ;
s erviceCollection. AddSingleton < IChapterManager , ChapterManager > ( ) ;
S erviceCollection. AddSingleton < IChapterManager , ChapterManager > ( ) ;
s erviceCollection. AddSingleton < IEncodingManager , MediaEncoder . EncodingManager > ( ) ;
S erviceCollection. AddSingleton < IEncodingManager , MediaEncoder . EncodingManager > ( ) ;
s erviceCollection. AddSingleton < IAuthorizationContext , AuthorizationContext > ( ) ;
s erviceCollection. AddSingleton < ISessionContext , SessionContext > ( ) ;
S erviceCollection. AddSingleton < IAuthorizationContext , AuthorizationContext > ( ) ;
S erviceCollection. AddSingleton < ISessionContext , SessionContext > ( ) ;
serviceCollection . AddSingleton < IAuthService , AuthService > ( ) ;
ServiceCollection . AddSingleton < IAuthService , AuthService > ( ) ;
ServiceCollection . AddSingleton < IQuickConnect , QuickConnectManager > ( ) ;
s erviceCollection. AddSingleton < ISubtitleEncoder , MediaBrowser . MediaEncoding . Subtitles . SubtitleEncoder > ( ) ;
S erviceCollection. AddSingleton < ISubtitleEncoder , MediaBrowser . MediaEncoding . Subtitles . SubtitleEncoder > ( ) ;
s erviceCollection. AddSingleton < IResourceFileManager , ResourceFileManager > ( ) ;
s erviceCollection. AddSingleton < EncodingHelper > ( ) ;
S erviceCollection. AddSingleton < IResourceFileManager , ResourceFileManager > ( ) ;
S erviceCollection. AddSingleton < EncodingHelper > ( ) ;
s erviceCollection. AddSingleton < IAttachmentExtractor , MediaBrowser . MediaEncoding . Attachments . AttachmentExtractor > ( ) ;
S erviceCollection. AddSingleton < IAttachmentExtractor , MediaBrowser . MediaEncoding . Attachments . AttachmentExtractor > ( ) ;
serviceCollection . AddSingleton < TranscodingJobHelper > ( ) ;
ServiceCollection . AddSingleton < TranscodingJobHelper > ( ) ;
ServiceCollection . AddScoped < MediaInfoHelper > ( ) ;
ServiceCollection . AddScoped < AudioHelper > ( ) ;
ServiceCollection . AddScoped < DynamicHlsHelper > ( ) ;
}
/// <summary>
@ -645,8 +665,7 @@ namespace Emby.Server.Implementations
_mediaEncoder = Resolve < IMediaEncoder > ( ) ;
_sessionManager = Resolve < ISessionManager > ( ) ;
_httpServer = Resolve < IHttpServer > ( ) ;
_httpClient = Resolve < IHttpClient > ( ) ;
_httpClientFactory = Resolve < IHttpClientFactory > ( ) ;
( ( AuthenticationRepository ) Resolve < IAuthenticationRepository > ( ) ) . Initialize ( ) ;
@ -747,7 +766,6 @@ namespace Emby.Server.Implementations
CollectionFolder . XmlSerializer = _xmlSerializer ;
CollectionFolder . JsonSerializer = Resolve < IJsonSerializer > ( ) ;
CollectionFolder . ApplicationHost = this ;
AuthenticatedAttribute . AuthService = Resolve < IAuthService > ( ) ;
}
/// <summary>
@ -767,7 +785,7 @@ namespace Emby.Server.Implementations
. Where ( i = > i ! = null )
. ToArray ( ) ;
_ httpServer. Init ( GetExportTypes < IService > ( ) , GetExports < IWebSocketListener > ( ) , GetUrlPrefixes ( ) ) ;
_ urlPrefixes = GetUrlPrefixes ( ) . ToArray ( ) ;
Resolve < ILibraryManager > ( ) . AddParts (
GetExports < IResolverIgnoreRule > ( ) ,
@ -800,37 +818,7 @@ namespace Emby.Server.Implementations
{
try
{
if ( plugin is IPluginAssembly assemblyPlugin )
{
var assembly = plugin . 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 ) ;
try
{
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 ) ;
}
}
catch ( Exception ex )
{
Logger . LogError ( ex , "Error getting plugin Id from {PluginName}." , plugin . GetType ( ) . FullName ) ;
}
}
if ( plugin is IHasPluginConfiguration hasPluginConfiguration )
{
hasPluginConfiguration . SetStartupInfo ( s = > Directory . CreateDirectory ( s ) ) ;
}
plugin . RegisterServices ( ServiceCollection ) ;
}
catch ( Exception ex )
{
@ -931,7 +919,7 @@ namespace Emby.Server.Implementations
}
}
if ( ! _ httpServer. U rlPrefixes. SequenceEqual ( GetUrlPrefixes ( ) , StringComparer . OrdinalIgnoreCase ) )
if ( ! _ u rlPrefixes. SequenceEqual ( GetUrlPrefixes ( ) , StringComparer . OrdinalIgnoreCase ) )
{
requiresRestart = true ;
}
@ -1005,6 +993,119 @@ namespace Emby.Server.Implementations
protected abstract void RestartInternal ( ) ;
/// <summary>
/// Comparison function used in <see cref="GetPlugins" />.
/// </summary>
/// <param name="a">Item to compare.</param>
/// <param name="b">Item to compare with.</param>
/// <returns>Boolean result of the operation.</returns>
private static int VersionCompare (
( Version PluginVersion , string Name , string Path ) a ,
( Version PluginVersion , string Name , string Path ) b )
{
int compare = string . Compare ( a . Name , b . Name , true , CultureInfo . InvariantCulture ) ;
if ( compare = = 0 )
{
return a . PluginVersion . CompareTo ( b . PluginVersion ) ;
}
return compare ;
}
/// <summary>
/// Returns a list of plugins to install.
/// </summary>
/// <param name="path">Path to check.</param>
/// <param name="cleanup">True if an attempt should be made to delete old plugs.</param>
/// <returns>Enumerable list of dlls to load.</returns>
private IEnumerable < string > GetPlugins ( string path , bool cleanup = true )
{
var dllList = new List < string > ( ) ;
var versions = new List < ( Version PluginVersion , string Name , string Path ) > ( ) ;
var directories = Directory . EnumerateDirectories ( path , "*.*" , SearchOption . TopDirectoryOnly ) ;
string metafile ;
foreach ( var dir in directories )
{
try
{
metafile = Path . Combine ( dir , "meta.json" ) ;
if ( File . Exists ( metafile ) )
{
var manifest = _jsonSerializer . DeserializeFromFile < PluginManifest > ( metafile ) ;
if ( ! Version . TryParse ( manifest . TargetAbi , out var targetAbi ) )
{
targetAbi = new Version ( 0 , 0 , 0 , 1 ) ;
}
if ( ! Version . TryParse ( manifest . Version , out var version ) )
{
version = new Version ( 0 , 0 , 0 , 1 ) ;
}
if ( ApplicationVersion > = targetAbi )
{
// Only load Plugins if the plugin is built for this version or below.
versions . Add ( ( version , manifest . Name , dir ) ) ;
}
}
else
{
// No metafile, so lets see if the folder is versioned.
metafile = dir . Split ( new [ ] { Path . DirectorySeparatorChar } , StringSplitOptions . RemoveEmptyEntries ) [ ^ 1 ] ;
int versionIndex = dir . LastIndexOf ( '_' ) ;
if ( versionIndex ! = - 1 & & Version . TryParse ( dir . Substring ( versionIndex + 1 ) , out Version ver ) )
{
// Versioned folder.
versions . Add ( ( ver , metafile , dir ) ) ;
}
else
{
// Un-versioned folder - Add it under the path name and version 0.0.0.1.
versions . Add ( ( new Version ( 0 , 0 , 0 , 1 ) , metafile , dir ) ) ;
}
}
}
catch
{
continue ;
}
}
string lastName = string . Empty ;
versions . Sort ( VersionCompare ) ;
// Traverse backwards through the list.
// The first item will be the latest version.
for ( int x = versions . Count - 1 ; x > = 0 ; x - - )
{
if ( ! string . Equals ( lastName , versions [ x ] . Name , StringComparison . OrdinalIgnoreCase ) )
{
dllList . AddRange ( Directory . EnumerateFiles ( versions [ x ] . Path , "*.dll" , SearchOption . AllDirectories ) ) ;
lastName = versions [ x ] . Name ;
continue ;
}
if ( ! string . IsNullOrEmpty ( lastName ) & & cleanup )
{
// Attempt a cleanup of old folders.
try
{
Logger . LogDebug ( "Deleting {Path}" , versions [ x ] . Path ) ;
Directory . Delete ( versions [ x ] . Path , true ) ;
}
catch ( Exception e )
{
Logger . LogWarning ( e , "Unable to delete {Path}" , versions [ x ] . Path ) ;
}
}
}
return dllList ;
}
/// <summary>
/// Gets the composable part assemblies.
/// </summary>
@ -1013,7 +1114,7 @@ namespace Emby.Server.Implementations
{
if ( Directory . Exists ( ApplicationPaths . PluginsPath ) )
{
foreach ( var file in Directory. EnumerateFile s( ApplicationPaths . PluginsPath , "*.dll" , SearchOption . AllDirectories ) )
foreach ( var file in GetPlugin s( ApplicationPaths . PluginsPath ) )
{
Assembly plugAss ;
try
@ -1127,7 +1228,8 @@ namespace Emby.Server.Implementations
Id = SystemId ,
OperatingSystem = OperatingSystem . Id . ToString ( ) ,
ServerName = FriendlyName ,
LocalAddress = localAddress
LocalAddress = localAddress ,
StartupWizardCompleted = ConfigurationManager . CommonConfiguration . IsStartupWizardCompleted
} ;
}
@ -1289,25 +1391,17 @@ namespace Emby.Server.Implementations
try
{
using ( var response = await _httpClient . SendAsync (
new HttpRequestOptions
{
Url = apiUrl ,
LogErrorResponseBody = false ,
BufferContent = false ,
CancellationToken = cancellationToken
} , HttpMethod . Post ) . ConfigureAwait ( false ) )
{
using ( var reader = new StreamReader ( response . Content ) )
{
var result = await reader . ReadToEndAsync ( ) . ConfigureAwait ( false ) ;
var valid = string . Equals ( Name , result , StringComparison . OrdinalIgnoreCase ) ;
using var request = new HttpRequestMessage ( HttpMethod . Post , apiUrl ) ;
using var response = await _httpClientFactory . CreateClient ( NamedClient . Default )
. SendAsync ( request , HttpCompletionOption . ResponseHeadersRead , cancellationToken ) . ConfigureAwait ( false ) ;
_validAddressResults . AddOrUpdate ( apiUrl , valid , ( k , v ) = > valid ) ;
Logger . LogDebug ( "Ping test result to {0}. Success: {1}" , apiUrl , valid ) ;
return valid ;
}
}
await using var stream = await response . Content . ReadAsStreamAsync ( ) . ConfigureAwait ( false ) ;
var result = await System . Text . Json . JsonSerializer . DeserializeAsync < string > ( stream , JsonDefaults . GetOptions ( ) , cancellationToken ) . ConfigureAwait ( false ) ;
var valid = string . Equals ( Name , result , StringComparison . OrdinalIgnoreCase ) ;
_validAddressResults . AddOrUpdate ( apiUrl , valid , ( k , v ) = > valid ) ;
Logger . LogDebug ( "Ping test result to {0}. Success: {1}" , apiUrl , valid ) ;
return valid ;
}
catch ( OperationCanceledException )
{
@ -1385,6 +1479,20 @@ namespace Emby.Server.Implementations
_plugins = list . ToArray ( ) ;
}
public IEnumerable < Assembly > GetApiPluginAssemblies ( )
{
var assemblies = _allConcreteTypes
. Where ( i = > typeof ( ControllerBase ) . IsAssignableFrom ( i ) )
. Select ( i = > i . Assembly )
. Distinct ( ) ;
foreach ( var assembly in assemblies )
{
Logger . LogDebug ( "Found API endpoints in plugin {Name}" , assembly . FullName ) ;
yield return assembly ;
}
}
public virtual void LaunchUrl ( string url )
{
if ( ! CanLaunchWebBrowser )
@ -1415,10 +1523,6 @@ namespace Emby.Server.Implementations
}
}
public virtual void EnableLoopback ( string appName )
{
}
private bool _disposed = false ;
/// <summary>