mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-18 00:06:27 +01:00
Merge branch 'master' into embytv
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
@@ -39,6 +41,19 @@ namespace Emby.Server.Implementations.Activity
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
private readonly IDeviceManager _deviceManager;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ActivityLogEntryPoint"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="sessionManager"></param>
|
||||
/// <param name="deviceManager"></param>
|
||||
/// <param name="taskManager"></param>
|
||||
/// <param name="activityManager"></param>
|
||||
/// <param name="localization"></param>
|
||||
/// <param name="installationManager"></param>
|
||||
/// <param name="subManager"></param>
|
||||
/// <param name="userManager"></param>
|
||||
/// <param name="appHost"></param>
|
||||
public ActivityLogEntryPoint(
|
||||
ILogger<ActivityLogEntryPoint> logger,
|
||||
ISessionManager sessionManager,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Controller.Library;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
@@ -84,6 +84,7 @@ namespace Emby.Server.Implementations.AppBase
|
||||
/// </summary>
|
||||
/// <value>The logger.</value>
|
||||
protected ILogger Logger { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the XML serializer.
|
||||
/// </summary>
|
||||
@@ -97,7 +98,7 @@ namespace Emby.Server.Implementations.AppBase
|
||||
public IApplicationPaths CommonApplicationPaths { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the system configuration.
|
||||
/// Gets or sets the system configuration.
|
||||
/// </summary>
|
||||
/// <value>The configuration.</value>
|
||||
public BaseApplicationConfiguration CommonConfiguration
|
||||
@@ -123,6 +124,7 @@ namespace Emby.Server.Implementations.AppBase
|
||||
return _configuration;
|
||||
}
|
||||
}
|
||||
|
||||
protected set
|
||||
{
|
||||
_configuration = value;
|
||||
@@ -131,6 +133,10 @@ namespace Emby.Server.Implementations.AppBase
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds parts.
|
||||
/// </summary>
|
||||
/// <param name="factories">The configuration factories.</param>
|
||||
public virtual void AddParts(IEnumerable<IConfigurationFactory> factories)
|
||||
{
|
||||
_configurationFactories = factories.ToArray();
|
||||
@@ -215,7 +221,7 @@ namespace Emby.Server.Implementations.AppBase
|
||||
cachePath = CommonConfiguration.CachePath;
|
||||
}
|
||||
|
||||
Logger.LogInformation("Setting cache path to " + cachePath);
|
||||
Logger.LogInformation("Setting cache path: {Path}", cachePath);
|
||||
((BaseApplicationPaths)CommonApplicationPaths).CachePath = cachePath;
|
||||
}
|
||||
|
||||
@@ -223,7 +229,7 @@ namespace Emby.Server.Implementations.AppBase
|
||||
/// Replaces the cache path.
|
||||
/// </summary>
|
||||
/// <param name="newConfig">The new configuration.</param>
|
||||
/// <exception cref="DirectoryNotFoundException"></exception>
|
||||
/// <exception cref="DirectoryNotFoundException">The new cache path doesn't exist.</exception>
|
||||
private void ValidateCachePath(BaseApplicationConfiguration newConfig)
|
||||
{
|
||||
var newPath = newConfig.CachePath;
|
||||
@@ -234,7 +240,7 @@ namespace Emby.Server.Implementations.AppBase
|
||||
// Validate
|
||||
if (!Directory.Exists(newPath))
|
||||
{
|
||||
throw new FileNotFoundException(
|
||||
throw new DirectoryNotFoundException(
|
||||
string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"{0} does not exist.",
|
||||
@@ -245,6 +251,10 @@ namespace Emby.Server.Implementations.AppBase
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that we have write access to the path.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
protected void EnsureWriteAccess(string path)
|
||||
{
|
||||
var file = Path.Combine(path, Guid.NewGuid().ToString());
|
||||
@@ -257,6 +267,7 @@ namespace Emby.Server.Implementations.AppBase
|
||||
return Path.Combine(CommonApplicationPaths.ConfigurationDirectoryPath, key.ToLowerInvariant() + ".xml");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public object GetConfiguration(string key)
|
||||
{
|
||||
return _configurations.GetOrAdd(key, k =>
|
||||
@@ -303,6 +314,7 @@ namespace Emby.Server.Implementations.AppBase
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SaveConfiguration(string key, object configuration)
|
||||
{
|
||||
var configurationStore = GetConfigurationStore(key);
|
||||
@@ -339,6 +351,11 @@ namespace Emby.Server.Implementations.AppBase
|
||||
OnNamedConfigurationUpdated(key, configuration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler for when a named configuration has been updated.
|
||||
/// </summary>
|
||||
/// <param name="key">The key of the configuration.</param>
|
||||
/// <param name="configuration">The old configuration.</param>
|
||||
protected virtual void OnNamedConfigurationUpdated(string key, object configuration)
|
||||
{
|
||||
NamedConfigurationUpdated?.Invoke(this, new ConfigurationUpdateEventArgs
|
||||
@@ -348,6 +365,7 @@ namespace Emby.Server.Implementations.AppBase
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Type GetConfigurationType(string key)
|
||||
{
|
||||
return GetConfigurationStore(key)
|
||||
|
||||
@@ -103,14 +103,11 @@ using MediaBrowser.Providers.Subtitles;
|
||||
using MediaBrowser.Providers.TV.TheTVDB;
|
||||
using MediaBrowser.WebDashboard.Api;
|
||||
using MediaBrowser.XbmcMetadata.Providers;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
|
||||
|
||||
namespace Emby.Server.Implementations
|
||||
@@ -764,9 +761,8 @@ namespace Emby.Server.Implementations
|
||||
LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, () => UserViewManager);
|
||||
serviceCollection.AddSingleton(LibraryManager);
|
||||
|
||||
// TODO wtaylor: investigate use of second music manager
|
||||
var musicManager = new MusicManager(LibraryManager);
|
||||
serviceCollection.AddSingleton<IMusicManager>(new MusicManager(LibraryManager));
|
||||
serviceCollection.AddSingleton<IMusicManager>(musicManager);
|
||||
|
||||
LibraryMonitor = new LibraryMonitor(LoggerFactory, LibraryManager, ServerConfigurationManager, FileSystemManager);
|
||||
serviceCollection.AddSingleton(LibraryMonitor);
|
||||
@@ -841,16 +837,14 @@ namespace Emby.Server.Implementations
|
||||
serviceCollection.AddSingleton(ChapterManager);
|
||||
|
||||
MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder(
|
||||
LoggerFactory,
|
||||
JsonSerializer,
|
||||
StartupOptions.FFmpegPath,
|
||||
LoggerFactory.CreateLogger<MediaBrowser.MediaEncoding.Encoder.MediaEncoder>(),
|
||||
ServerConfigurationManager,
|
||||
FileSystemManager,
|
||||
() => SubtitleEncoder,
|
||||
() => MediaSourceManager,
|
||||
ProcessFactory,
|
||||
5000,
|
||||
LocalizationManager);
|
||||
LocalizationManager,
|
||||
() => SubtitleEncoder,
|
||||
_configuration,
|
||||
StartupOptions.FFmpegPath);
|
||||
serviceCollection.AddSingleton(MediaEncoder);
|
||||
|
||||
EncodingManager = new MediaEncoder.EncodingManager(FileSystemManager, LoggerFactory, MediaEncoder, ChapterManager, LibraryManager);
|
||||
@@ -867,10 +861,21 @@ namespace Emby.Server.Implementations
|
||||
AuthService = new AuthService(LoggerFactory.CreateLogger<AuthService>(), authContext, ServerConfigurationManager, SessionManager, NetworkManager);
|
||||
serviceCollection.AddSingleton(AuthService);
|
||||
|
||||
SubtitleEncoder = new MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder(LibraryManager, LoggerFactory, ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager, ProcessFactory);
|
||||
SubtitleEncoder = new MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder(
|
||||
LibraryManager,
|
||||
LoggerFactory.CreateLogger<MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder>(),
|
||||
ApplicationPaths,
|
||||
FileSystemManager,
|
||||
MediaEncoder,
|
||||
HttpClient,
|
||||
MediaSourceManager,
|
||||
ProcessFactory);
|
||||
serviceCollection.AddSingleton(SubtitleEncoder);
|
||||
|
||||
serviceCollection.AddSingleton(typeof(IResourceFileManager), typeof(ResourceFileManager));
|
||||
serviceCollection.AddSingleton<EncodingHelper>();
|
||||
|
||||
serviceCollection.AddSingleton(typeof(IAttachmentExtractor), typeof(MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor));
|
||||
|
||||
_displayPreferencesRepository.Initialize();
|
||||
|
||||
@@ -1472,7 +1477,7 @@ namespace Emby.Server.Implementations
|
||||
/// </summary>
|
||||
/// <param name="address">The IPv6 address.</param>
|
||||
/// <returns>The IPv6 address without the scope id.</returns>
|
||||
private string RemoveScopeId(string address)
|
||||
private ReadOnlySpan<char> RemoveScopeId(ReadOnlySpan<char> address)
|
||||
{
|
||||
var index = address.IndexOf('%');
|
||||
if (index == -1)
|
||||
@@ -1480,33 +1485,50 @@ namespace Emby.Server.Implementations
|
||||
return address;
|
||||
}
|
||||
|
||||
return address.Substring(0, index);
|
||||
return address.Slice(0, index);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetLocalApiUrl(IPAddress ipAddress)
|
||||
{
|
||||
if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
|
||||
{
|
||||
var str = RemoveScopeId(ipAddress.ToString());
|
||||
Span<char> span = new char[str.Length + 2];
|
||||
span[0] = '[';
|
||||
str.CopyTo(span.Slice(1));
|
||||
span[^1] = ']';
|
||||
|
||||
return GetLocalApiUrl("[" + str + "]");
|
||||
return GetLocalApiUrl(span);
|
||||
}
|
||||
|
||||
return GetLocalApiUrl(ipAddress.ToString());
|
||||
}
|
||||
|
||||
public string GetLocalApiUrl(string host)
|
||||
/// <inheritdoc />
|
||||
public string GetLocalApiUrl(ReadOnlySpan<char> host)
|
||||
{
|
||||
var url = new StringBuilder(64);
|
||||
if (EnableHttps)
|
||||
{
|
||||
return string.Format("https://{0}:{1}",
|
||||
host,
|
||||
HttpsPort.ToString(CultureInfo.InvariantCulture));
|
||||
url.Append("https://");
|
||||
}
|
||||
else
|
||||
{
|
||||
url.Append("http://");
|
||||
}
|
||||
|
||||
return string.Format("http://{0}:{1}",
|
||||
host,
|
||||
HttpPort.ToString(CultureInfo.InvariantCulture));
|
||||
url.Append(host)
|
||||
.Append(':')
|
||||
.Append(HttpPort);
|
||||
|
||||
string baseUrl = ServerConfigurationManager.Configuration.BaseUrl;
|
||||
if (baseUrl.Length != 0)
|
||||
{
|
||||
url.Append('/').Append(baseUrl);
|
||||
}
|
||||
|
||||
return url.ToString();
|
||||
}
|
||||
|
||||
public Task<List<IPAddress>> GetLocalIpAddresses(CancellationToken cancellationToken)
|
||||
|
||||
@@ -10,15 +10,10 @@ using SharpCompress.Readers.Zip;
|
||||
namespace Emby.Server.Implementations.Archiving
|
||||
{
|
||||
/// <summary>
|
||||
/// Class DotNetZipClient
|
||||
/// Class DotNetZipClient.
|
||||
/// </summary>
|
||||
public class ZipClient : IZipClient
|
||||
{
|
||||
public ZipClient()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts all.
|
||||
/// </summary>
|
||||
@@ -144,7 +139,6 @@ namespace Emby.Server.Implementations.Archiving
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Extracts all from tar.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Model.Branding;
|
||||
|
||||
@@ -4,7 +4,7 @@ using MediaBrowser.Controller;
|
||||
namespace Emby.Server.Implementations.Browser
|
||||
{
|
||||
/// <summary>
|
||||
/// Class BrowserLauncher
|
||||
/// Class BrowserLauncher.
|
||||
/// </summary>
|
||||
public static class BrowserLauncher
|
||||
{
|
||||
@@ -32,6 +32,7 @@ namespace Emby.Server.Implementations.Browser
|
||||
/// <summary>
|
||||
/// Opens the URL.
|
||||
/// </summary>
|
||||
/// <param name="appHost">The application host instance.</param>
|
||||
/// <param name="url">The URL.</param>
|
||||
private static void OpenUrl(IServerApplicationHost appHost, string url)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
@@ -13,11 +15,16 @@ namespace Emby.Server.Implementations.Channels
|
||||
{
|
||||
private readonly ChannelManager _channelManager;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ChannelDynamicMediaSourceProvider"/> class.
|
||||
/// </summary>
|
||||
/// <param name="channelManager">The channel manager.</param>
|
||||
public ChannelDynamicMediaSourceProvider(IChannelManager channelManager)
|
||||
{
|
||||
_channelManager = (ChannelManager)channelManager;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IEnumerable<MediaSourceInfo>> GetMediaSources(BaseItem item, CancellationToken cancellationToken)
|
||||
{
|
||||
if (item.SourceType == SourceType.Channel)
|
||||
@@ -28,6 +35,7 @@ namespace Emby.Server.Implementations.Channels
|
||||
return Task.FromResult<IEnumerable<MediaSourceInfo>>(new List<MediaSourceInfo>());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<ILiveStream> OpenMediaSource(string openToken, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@@ -510,7 +512,7 @@ namespace Emby.Server.Implementations.Channels
|
||||
return _libraryManager.GetItemIds(new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(Channel).Name },
|
||||
OrderBy = new ValueTuple<string, SortOrder>[] { new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending) }
|
||||
OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }
|
||||
|
||||
}).Select(i => GetChannelFeatures(i.ToString("N", CultureInfo.InvariantCulture))).ToArray();
|
||||
}
|
||||
@@ -618,16 +620,16 @@ namespace Emby.Server.Implementations.Channels
|
||||
{
|
||||
query.OrderBy = new[]
|
||||
{
|
||||
new ValueTuple<string, SortOrder>(ItemSortBy.PremiereDate, SortOrder.Descending),
|
||||
new ValueTuple<string, SortOrder>(ItemSortBy.ProductionYear, SortOrder.Descending),
|
||||
new ValueTuple<string, SortOrder>(ItemSortBy.DateCreated, SortOrder.Descending)
|
||||
(ItemSortBy.PremiereDate, SortOrder.Descending),
|
||||
(ItemSortBy.ProductionYear, SortOrder.Descending),
|
||||
(ItemSortBy.DateCreated, SortOrder.Descending)
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
query.OrderBy = new[]
|
||||
{
|
||||
new ValueTuple<string, SortOrder>(ItemSortBy.DateCreated, SortOrder.Descending)
|
||||
(ItemSortBy.DateCreated, SortOrder.Descending)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -76,7 +78,6 @@ namespace Emby.Server.Implementations.Collections
|
||||
.Where(i => i != null)
|
||||
.GroupBy(x => x.Id)
|
||||
.Select(x => x.First())
|
||||
.OrderBy(i => Guid.NewGuid())
|
||||
.ToList();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
@@ -29,11 +31,7 @@ namespace Emby.Server.Implementations.Collections
|
||||
private readonly ILogger _logger;
|
||||
private readonly IProviderManager _providerManager;
|
||||
private readonly ILocalizationManager _localizationManager;
|
||||
private IApplicationPaths _appPaths;
|
||||
|
||||
public event EventHandler<CollectionCreatedEventArgs> CollectionCreated;
|
||||
public event EventHandler<CollectionModifiedEventArgs> ItemsAddedToCollection;
|
||||
public event EventHandler<CollectionModifiedEventArgs> ItemsRemovedFromCollection;
|
||||
private readonly IApplicationPaths _appPaths;
|
||||
|
||||
public CollectionManager(
|
||||
ILibraryManager libraryManager,
|
||||
@@ -53,6 +51,10 @@ namespace Emby.Server.Implementations.Collections
|
||||
_appPaths = appPaths;
|
||||
}
|
||||
|
||||
public event EventHandler<CollectionCreatedEventArgs> CollectionCreated;
|
||||
public event EventHandler<CollectionModifiedEventArgs> ItemsAddedToCollection;
|
||||
public event EventHandler<CollectionModifiedEventArgs> ItemsRemovedFromCollection;
|
||||
|
||||
private IEnumerable<Folder> FindFolders(string path)
|
||||
{
|
||||
return _libraryManager
|
||||
@@ -339,11 +341,11 @@ namespace Emby.Server.Implementations.Collections
|
||||
}
|
||||
}
|
||||
|
||||
public class CollectionManagerEntryPoint : IServerEntryPoint
|
||||
public sealed class CollectionManagerEntryPoint : IServerEntryPoint
|
||||
{
|
||||
private readonly CollectionManager _collectionManager;
|
||||
private readonly IServerConfigurationManager _config;
|
||||
private ILogger _logger;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public CollectionManagerEntryPoint(ICollectionManager collectionManager, IServerConfigurationManager config, ILogger logger)
|
||||
{
|
||||
@@ -352,6 +354,7 @@ namespace Emby.Server.Implementations.Collections
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task RunAsync()
|
||||
{
|
||||
if (!_config.Configuration.CollectionsUpgraded && _config.Configuration.IsStartupWizardCompleted)
|
||||
@@ -375,39 +378,10 @@ namespace Emby.Server.Implementations.Collections
|
||||
}
|
||||
}
|
||||
|
||||
#region IDisposable Support
|
||||
private bool disposedValue = false; // To detect redundant calls
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// TODO: dispose managed state (managed objects).
|
||||
}
|
||||
|
||||
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
|
||||
// TODO: set large fields to null.
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
|
||||
// ~CollectionManagerEntryPoint() {
|
||||
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
||||
// Dispose(false);
|
||||
// }
|
||||
|
||||
// This code added to correctly implement the disposable pattern.
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
||||
Dispose(true);
|
||||
// TODO: uncomment the following line if the finalizer is overridden above.
|
||||
// GC.SuppressFinalize(this);
|
||||
// Nothing to dispose
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using Emby.Server.Implementations.AppBase;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
@@ -17,7 +19,6 @@ namespace Emby.Server.Implementations.Configuration
|
||||
/// </summary>
|
||||
public class ServerConfigurationManager : BaseConfigurationManager, IServerConfigurationManager
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ServerConfigurationManager" /> class.
|
||||
/// </summary>
|
||||
@@ -31,6 +32,9 @@ namespace Emby.Server.Implementations.Configuration
|
||||
UpdateMetadataPath();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configuration updating event.
|
||||
/// </summary>
|
||||
public event EventHandler<GenericEventArgs<ServerConfiguration>> ConfigurationUpdating;
|
||||
|
||||
/// <summary>
|
||||
@@ -97,7 +101,7 @@ namespace Emby.Server.Implementations.Configuration
|
||||
/// Validates the SSL certificate.
|
||||
/// </summary>
|
||||
/// <param name="newConfig">The new configuration.</param>
|
||||
/// <exception cref="DirectoryNotFoundException"></exception>
|
||||
/// <exception cref="FileNotFoundException">The certificate path doesn't exist.</exception>
|
||||
private void ValidateSslCertificate(BaseApplicationConfiguration newConfig)
|
||||
{
|
||||
var serverConfig = (ServerConfiguration)newConfig;
|
||||
@@ -105,12 +109,16 @@ namespace Emby.Server.Implementations.Configuration
|
||||
var newPath = serverConfig.CertificatePath;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(newPath)
|
||||
&& !string.Equals(Configuration.CertificatePath ?? string.Empty, newPath))
|
||||
&& !string.Equals(Configuration.CertificatePath, newPath, StringComparison.Ordinal))
|
||||
{
|
||||
// Validate
|
||||
if (!File.Exists(newPath))
|
||||
{
|
||||
throw new FileNotFoundException(string.Format("Certificate file '{0}' does not exist.", newPath));
|
||||
throw new FileNotFoundException(
|
||||
string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"Certificate file '{0}' does not exist.",
|
||||
newPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,24 +127,32 @@ namespace Emby.Server.Implementations.Configuration
|
||||
/// Validates the metadata path.
|
||||
/// </summary>
|
||||
/// <param name="newConfig">The new configuration.</param>
|
||||
/// <exception cref="DirectoryNotFoundException"></exception>
|
||||
/// <exception cref="DirectoryNotFoundException">The new config path doesn't exist.</exception>
|
||||
private void ValidateMetadataPath(ServerConfiguration newConfig)
|
||||
{
|
||||
var newPath = newConfig.MetadataPath;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(newPath)
|
||||
&& !string.Equals(Configuration.MetadataPath ?? string.Empty, newPath))
|
||||
&& !string.Equals(Configuration.MetadataPath, newPath, StringComparison.Ordinal))
|
||||
{
|
||||
// Validate
|
||||
if (!Directory.Exists(newPath))
|
||||
{
|
||||
throw new FileNotFoundException(string.Format("{0} does not exist.", newPath));
|
||||
throw new DirectoryNotFoundException(
|
||||
string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"{0} does not exist.",
|
||||
newPath));
|
||||
}
|
||||
|
||||
EnsureWriteAccess(newPath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets all configuration values to their optimal values.
|
||||
/// </summary>
|
||||
/// <returns>If the configuration changed.</returns>
|
||||
public bool SetOptimalValues()
|
||||
{
|
||||
var config = Configuration;
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
using static MediaBrowser.Controller.Extensions.ConfigurationExtensions;
|
||||
|
||||
namespace Emby.Server.Implementations
|
||||
{
|
||||
public static class ConfigurationOptions
|
||||
{
|
||||
public static readonly Dictionary<string, string> Configuration = new Dictionary<string, string>
|
||||
public static Dictionary<string, string> Configuration => new Dictionary<string, string>
|
||||
{
|
||||
{ "HttpListenerHost:DefaultRedirectPath", "web/index.html" },
|
||||
{ "MusicBrainz:BaseUrl", "https://www.musicbrainz.org" }
|
||||
{ "MusicBrainz:BaseUrl", "https://www.musicbrainz.org" },
|
||||
{ FfmpegProbeSizeKey, "1G" },
|
||||
{ FfmpegAnalyzeDurationKey, "200M" }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ using static MediaBrowser.Common.Cryptography.Constants;
|
||||
|
||||
namespace Emby.Server.Implementations.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// Class providing abstractions over cryptographic functions.
|
||||
/// </summary>
|
||||
public class CryptographyProvider : ICryptoProvider, IDisposable
|
||||
{
|
||||
private static readonly HashSet<string> _supportedHashMethods = new HashSet<string>()
|
||||
@@ -42,8 +45,10 @@ namespace Emby.Server.Implementations.Cryptography
|
||||
_randomNumberGenerator = RandomNumberGenerator.Create();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string DefaultHashMethod => "PBKDF2";
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<string> GetSupportedHashMethods()
|
||||
=> _supportedHashMethods;
|
||||
|
||||
@@ -62,6 +67,7 @@ namespace Emby.Server.Implementations.Cryptography
|
||||
throw new CryptographicException($"Cannot currently use PBKDF2 with requested hash method: {method}");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte[] ComputeHash(string hashMethod, byte[] bytes, byte[] salt)
|
||||
{
|
||||
if (hashMethod == DefaultHashMethod)
|
||||
@@ -89,12 +95,15 @@ namespace Emby.Server.Implementations.Cryptography
|
||||
throw new CryptographicException($"Requested hash method is not supported: {hashMethod}");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte[] ComputeHashWithDefaultMethod(byte[] bytes, byte[] salt)
|
||||
=> PBKDF2(DefaultHashMethod, bytes, salt, DefaultIterations);
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte[] GenerateSalt()
|
||||
=> GenerateSalt(DefaultSaltLength);
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte[] GenerateSalt(int length)
|
||||
{
|
||||
byte[] salt = new byte[length];
|
||||
@@ -109,6 +118,10 @@ namespace Emby.Server.Implementations.Cryptography
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases unmanaged and - optionally - managed resources.
|
||||
/// </summary>
|
||||
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -11,6 +13,10 @@ namespace Emby.Server.Implementations.Data
|
||||
{
|
||||
private bool _disposed = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BaseSqliteRepository"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">The logger.</param>
|
||||
protected BaseSqliteRepository(ILogger logger)
|
||||
{
|
||||
Logger = logger;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using Emby.Server.Implementations.Playlists;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Common.Json;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Channels;
|
||||
@@ -48,6 +49,21 @@ namespace Emby.Server.Implementations.Data
|
||||
private readonly TypeMapper _typeMapper;
|
||||
private readonly JsonSerializerOptions _jsonOptions;
|
||||
|
||||
static SqliteItemRepository()
|
||||
{
|
||||
var queryPrefixText = new StringBuilder();
|
||||
queryPrefixText.Append("insert into mediaattachments (");
|
||||
foreach (var column in _mediaAttachmentSaveColumns)
|
||||
{
|
||||
queryPrefixText.Append(column)
|
||||
.Append(',');
|
||||
}
|
||||
|
||||
queryPrefixText.Length -= 1;
|
||||
queryPrefixText.Append(") values ");
|
||||
_mediaAttachmentInsertPrefix = queryPrefixText.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
|
||||
/// </summary>
|
||||
@@ -91,6 +107,8 @@ namespace Emby.Server.Implementations.Data
|
||||
{
|
||||
const string CreateMediaStreamsTableCommand
|
||||
= "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, IsAvc BIT NULL, Title TEXT NULL, TimeBase TEXT NULL, CodecTimeBase TEXT NULL, ColorPrimaries TEXT NULL, ColorSpace TEXT NULL, ColorTransfer TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))";
|
||||
const string CreateMediaAttachmentsTableCommand
|
||||
= "create table if not exists mediaattachments (ItemId GUID, AttachmentIndex INT, Codec TEXT, CodecTag TEXT NULL, Comment TEXT NULL, Filename TEXT NULL, MIMEType TEXT NULL, PRIMARY KEY (ItemId, AttachmentIndex))";
|
||||
|
||||
string[] queries =
|
||||
{
|
||||
@@ -113,6 +131,7 @@ namespace Emby.Server.Implementations.Data
|
||||
"create table if not exists " + ChaptersTableName + " (ItemId GUID, ChapterIndex INT NOT NULL, StartPositionTicks BIGINT NOT NULL, Name TEXT, ImagePath TEXT, PRIMARY KEY (ItemId, ChapterIndex))",
|
||||
|
||||
CreateMediaStreamsTableCommand,
|
||||
CreateMediaAttachmentsTableCommand,
|
||||
|
||||
"pragma shrink_memory"
|
||||
};
|
||||
@@ -420,6 +439,19 @@ namespace Emby.Server.Implementations.Data
|
||||
"ColorTransfer"
|
||||
};
|
||||
|
||||
private static readonly string[] _mediaAttachmentSaveColumns =
|
||||
{
|
||||
"ItemId",
|
||||
"AttachmentIndex",
|
||||
"Codec",
|
||||
"CodecTag",
|
||||
"Comment",
|
||||
"Filename",
|
||||
"MIMEType"
|
||||
};
|
||||
|
||||
private static readonly string _mediaAttachmentInsertPrefix;
|
||||
|
||||
private static string GetSaveItemCommandText()
|
||||
{
|
||||
var saveColumns = new []
|
||||
@@ -2831,8 +2863,8 @@ namespace Emby.Server.Implementations.Data
|
||||
BindSimilarParams(query, statement);
|
||||
BindSearchParams(query, statement);
|
||||
|
||||
// Running this again will bind the params
|
||||
GetWhereClauses(query, statement);
|
||||
// Running this again will bind the params
|
||||
GetWhereClauses(query, statement);
|
||||
|
||||
var hasEpisodeAttributes = HasEpisodeAttributes(query);
|
||||
var hasServiceName = HasServiceName(query);
|
||||
@@ -2881,14 +2913,14 @@ namespace Emby.Server.Implementations.Data
|
||||
|
||||
private string GetOrderByText(InternalItemsQuery query)
|
||||
{
|
||||
var orderBy = query.OrderBy;
|
||||
if (string.IsNullOrEmpty(query.SearchTerm))
|
||||
{
|
||||
int oldLen = query.OrderBy.Length;
|
||||
|
||||
if (query.SimilarTo != null && oldLen == 0)
|
||||
int oldLen = orderBy.Count;
|
||||
if (oldLen == 0 && query.SimilarTo != null)
|
||||
{
|
||||
var arr = new (string, SortOrder)[oldLen + 2];
|
||||
query.OrderBy.CopyTo(arr, 0);
|
||||
orderBy.CopyTo(arr, 0);
|
||||
arr[oldLen] = ("SimilarityScore", SortOrder.Descending);
|
||||
arr[oldLen + 1] = (ItemSortBy.Random, SortOrder.Ascending);
|
||||
query.OrderBy = arr;
|
||||
@@ -2896,16 +2928,15 @@ namespace Emby.Server.Implementations.Data
|
||||
}
|
||||
else
|
||||
{
|
||||
query.OrderBy = new []
|
||||
query.OrderBy = new[]
|
||||
{
|
||||
("SearchScore", SortOrder.Descending),
|
||||
(ItemSortBy.SortName, SortOrder.Ascending)
|
||||
};
|
||||
}
|
||||
|
||||
var orderBy = query.OrderBy;
|
||||
|
||||
if (orderBy.Length == 0)
|
||||
if (orderBy.Count == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
@@ -2913,14 +2944,8 @@ namespace Emby.Server.Implementations.Data
|
||||
return " ORDER BY " + string.Join(",", orderBy.Select(i =>
|
||||
{
|
||||
var columnMap = MapOrderByField(i.Item1, query);
|
||||
var columnAscending = i.Item2 == SortOrder.Ascending;
|
||||
const bool enableOrderInversion = false;
|
||||
if (columnMap.Item2 && enableOrderInversion)
|
||||
{
|
||||
columnAscending = !columnAscending;
|
||||
}
|
||||
|
||||
var sortOrder = columnAscending ? "ASC" : "DESC";
|
||||
var sortOrder = i.Item2 == SortOrder.Ascending ? "ASC" : "DESC";
|
||||
|
||||
return columnMap.Item1 + " " + sortOrder;
|
||||
}));
|
||||
@@ -4599,10 +4624,20 @@ namespace Emby.Server.Implementations.Data
|
||||
|
||||
if (query.ExcludeInheritedTags.Length > 0)
|
||||
{
|
||||
var tagValues = query.ExcludeInheritedTags.Select(i => "'" + GetCleanValue(i) + "'");
|
||||
var tagValuesList = string.Join(",", tagValues);
|
||||
|
||||
whereClauses.Add("((select CleanValue from itemvalues where ItemId=Guid and Type=6 and cleanvalue in (" + tagValuesList + ")) is null)");
|
||||
var paramName = "@ExcludeInheritedTags";
|
||||
if (statement == null)
|
||||
{
|
||||
int index = 0;
|
||||
string excludedTags = string.Join(",", query.ExcludeInheritedTags.Select(t => paramName + index++));
|
||||
whereClauses.Add("((select CleanValue from itemvalues where ItemId=Guid and Type=6 and cleanvalue in (" + excludedTags + ")) is null)");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int index = 0; index < query.ExcludeInheritedTags.Length; index++)
|
||||
{
|
||||
statement.TryBind(paramName + index, GetCleanValue(query.ExcludeInheritedTags[index]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (query.SeriesStatuses.Length > 0)
|
||||
@@ -6132,5 +6167,175 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public List<MediaAttachment> GetMediaAttachments(MediaAttachmentQuery query)
|
||||
{
|
||||
CheckDisposed();
|
||||
|
||||
if (query == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(query));
|
||||
}
|
||||
|
||||
var cmdText = "select "
|
||||
+ string.Join(",", _mediaAttachmentSaveColumns)
|
||||
+ " from mediaattachments where"
|
||||
+ " ItemId=@ItemId";
|
||||
|
||||
if (query.Index.HasValue)
|
||||
{
|
||||
cmdText += " AND AttachmentIndex=@AttachmentIndex";
|
||||
}
|
||||
|
||||
cmdText += " order by AttachmentIndex ASC";
|
||||
|
||||
var list = new List<MediaAttachment>();
|
||||
using (var connection = GetConnection(true))
|
||||
using (var statement = PrepareStatement(connection, cmdText))
|
||||
{
|
||||
statement.TryBind("@ItemId", query.ItemId.ToByteArray());
|
||||
|
||||
if (query.Index.HasValue)
|
||||
{
|
||||
statement.TryBind("@AttachmentIndex", query.Index.Value);
|
||||
}
|
||||
|
||||
foreach (var row in statement.ExecuteQuery())
|
||||
{
|
||||
list.Add(GetMediaAttachment(row));
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public void SaveMediaAttachments(
|
||||
Guid id,
|
||||
IReadOnlyList<MediaAttachment> attachments,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
CheckDisposed();
|
||||
if (id == Guid.Empty)
|
||||
{
|
||||
throw new ArgumentException(nameof(id));
|
||||
}
|
||||
|
||||
if (attachments == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(attachments));
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
using (var connection = GetConnection())
|
||||
{
|
||||
connection.RunInTransaction(db =>
|
||||
{
|
||||
var itemIdBlob = id.ToByteArray();
|
||||
|
||||
db.Execute("delete from mediaattachments where ItemId=@ItemId", itemIdBlob);
|
||||
|
||||
InsertMediaAttachments(itemIdBlob, attachments, db, cancellationToken);
|
||||
|
||||
}, TransactionMode);
|
||||
}
|
||||
}
|
||||
|
||||
private void InsertMediaAttachments(
|
||||
byte[] idBlob,
|
||||
IReadOnlyList<MediaAttachment> attachments,
|
||||
IDatabaseConnection db,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
const int InsertAtOnce = 10;
|
||||
|
||||
for (var startIndex = 0; startIndex < attachments.Count; startIndex += InsertAtOnce)
|
||||
{
|
||||
var insertText = new StringBuilder(_mediaAttachmentInsertPrefix);
|
||||
|
||||
var endIndex = Math.Min(attachments.Count, startIndex + InsertAtOnce);
|
||||
|
||||
for (var i = startIndex; i < endIndex; i++)
|
||||
{
|
||||
var index = i.ToString(CultureInfo.InvariantCulture);
|
||||
insertText.Append("(@ItemId, ");
|
||||
|
||||
foreach (var column in _mediaAttachmentSaveColumns.Skip(1))
|
||||
{
|
||||
insertText.Append("@" + column + index + ",");
|
||||
}
|
||||
|
||||
insertText.Length -= 1;
|
||||
|
||||
insertText.Append("),");
|
||||
}
|
||||
|
||||
insertText.Length--;
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
using (var statement = PrepareStatement(db, insertText.ToString()))
|
||||
{
|
||||
statement.TryBind("@ItemId", idBlob);
|
||||
|
||||
for (var i = startIndex; i < endIndex; i++)
|
||||
{
|
||||
var index = i.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
var attachment = attachments[i];
|
||||
|
||||
statement.TryBind("@AttachmentIndex" + index, attachment.Index);
|
||||
statement.TryBind("@Codec" + index, attachment.Codec);
|
||||
statement.TryBind("@CodecTag" + index, attachment.CodecTag);
|
||||
statement.TryBind("@Comment" + index, attachment.Comment);
|
||||
statement.TryBind("@FileName" + index, attachment.FileName);
|
||||
statement.TryBind("@MimeType" + index, attachment.MimeType);
|
||||
}
|
||||
|
||||
statement.Reset();
|
||||
statement.MoveNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the attachment.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader.</param>
|
||||
/// <returns>MediaAttachment</returns>
|
||||
private MediaAttachment GetMediaAttachment(IReadOnlyList<IResultSetValue> reader)
|
||||
{
|
||||
var item = new MediaAttachment
|
||||
{
|
||||
Index = reader[1].ToInt()
|
||||
};
|
||||
|
||||
if (reader[2].SQLiteType != SQLiteType.Null)
|
||||
{
|
||||
item.Codec = reader[2].ToString();
|
||||
}
|
||||
|
||||
if (reader[2].SQLiteType != SQLiteType.Null)
|
||||
{
|
||||
item.CodecTag = reader[3].ToString();
|
||||
}
|
||||
|
||||
if (reader[4].SQLiteType != SQLiteType.Null)
|
||||
{
|
||||
item.Comment = reader[4].ToString();
|
||||
}
|
||||
|
||||
if (reader[6].SQLiteType != SQLiteType.Null)
|
||||
{
|
||||
item.FileName = reader[5].ToString();
|
||||
}
|
||||
|
||||
if (reader[6].SQLiteType != SQLiteType.Null)
|
||||
{
|
||||
item.MimeType = reader[6].ToString();
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
@@ -5,25 +5,22 @@ using System.Linq;
|
||||
namespace Emby.Server.Implementations.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Class TypeMapper
|
||||
/// Class TypeMapper.
|
||||
/// </summary>
|
||||
public class TypeMapper
|
||||
{
|
||||
/// <summary>
|
||||
/// This holds all the types in the running assemblies so that we can de-serialize properly when we don't have strong types
|
||||
/// This holds all the types in the running assemblies
|
||||
/// so that we can de-serialize properly when we don't have strong types.
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<string, Type> _typeMap = new ConcurrentDictionary<string, Type>();
|
||||
|
||||
public TypeMapper()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type.
|
||||
/// </summary>
|
||||
/// <param name="typeName">Name of the type.</param>
|
||||
/// <returns>Type.</returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
/// <exception cref="ArgumentNullException"><c>typeName</c> is null.</exception>
|
||||
public Type GetType(string typeName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(typeName))
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using MediaBrowser.Model.Diagnostics;
|
||||
|
||||
namespace Emby.Server.Implementations.Diagnostics
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
<ProjectReference Include="..\MediaBrowser.LocalMetadata\MediaBrowser.LocalMetadata.csproj" />
|
||||
<ProjectReference Include="..\Emby.Photos\Emby.Photos.csproj" />
|
||||
<ProjectReference Include="..\Emby.Drawing\Emby.Drawing.csproj" />
|
||||
<ProjectReference Include="..\Emby.XmlTv\Emby.XmlTv\Emby.XmlTv.csproj" />
|
||||
<ProjectReference Include="..\MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="IPNetwork2" Version="2.4.0.126" />
|
||||
<PackageReference Include="Jellyfin.XmlTv" Version="10.4.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" Version="2.2.0" />
|
||||
@@ -29,7 +29,6 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.0.1" />
|
||||
@@ -37,6 +36,7 @@
|
||||
<PackageReference Include="ServiceStack.Text.Core" Version="5.7.0" />
|
||||
<PackageReference Include="sharpcompress" Version="0.24.0" />
|
||||
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="2.0.1" />
|
||||
<PackageReference Include="System.Interactive.Async" Version="4.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -49,7 +49,7 @@
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Code analysers-->
|
||||
<!-- Code Analyzers-->
|
||||
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7" />
|
||||
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" />
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Library;
|
||||
@@ -12,32 +11,19 @@ using Microsoft.Extensions.Logging;
|
||||
namespace Emby.Server.Implementations.EntryPoints
|
||||
{
|
||||
/// <summary>
|
||||
/// Class RefreshUsersMetadata
|
||||
/// Class RefreshUsersMetadata.
|
||||
/// </summary>
|
||||
public class RefreshUsersMetadata : IScheduledTask, IConfigurableScheduledTask
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// The _user manager
|
||||
/// The user manager.
|
||||
/// </summary>
|
||||
private readonly IUserManager _userManager;
|
||||
|
||||
private IFileSystem _fileSystem;
|
||||
|
||||
public string Name => "Refresh Users";
|
||||
|
||||
public string Key => "RefreshUsers";
|
||||
|
||||
public string Description => "Refresh user infos";
|
||||
|
||||
public string Category => "Library";
|
||||
|
||||
public bool IsHidden => true;
|
||||
|
||||
public bool IsEnabled => true;
|
||||
|
||||
public bool IsLogged => true;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RefreshUsersMetadata" /> class.
|
||||
/// </summary>
|
||||
@@ -48,6 +34,28 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => "Refresh Users";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => "RefreshUsers";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description => "Refresh user infos";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Category => "Library";
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsHidden => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEnabled => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsLogged => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
|
||||
{
|
||||
foreach (var user in _userManager.Users)
|
||||
@@ -58,9 +66,10 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
|
||||
{
|
||||
return new List<TaskTriggerInfo>
|
||||
return new[]
|
||||
{
|
||||
new TaskTriggerInfo
|
||||
{
|
||||
|
||||
@@ -16,33 +16,46 @@ using MediaBrowser.Model.Tasks;
|
||||
namespace Emby.Server.Implementations.EntryPoints
|
||||
{
|
||||
/// <summary>
|
||||
/// Class WebSocketEvents
|
||||
/// Class WebSocketEvents.
|
||||
/// </summary>
|
||||
public class ServerEventNotifier : IServerEntryPoint
|
||||
{
|
||||
/// <summary>
|
||||
/// The _user manager
|
||||
/// The user manager.
|
||||
/// </summary>
|
||||
private readonly IUserManager _userManager;
|
||||
|
||||
/// <summary>
|
||||
/// The _installation manager
|
||||
/// The installation manager.
|
||||
/// </summary>
|
||||
private readonly IInstallationManager _installationManager;
|
||||
|
||||
/// <summary>
|
||||
/// The _kernel
|
||||
/// The kernel.
|
||||
/// </summary>
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
|
||||
/// <summary>
|
||||
/// The _task manager
|
||||
/// The task manager.
|
||||
/// </summary>
|
||||
private readonly ITaskManager _taskManager;
|
||||
|
||||
private readonly ISessionManager _sessionManager;
|
||||
|
||||
public ServerEventNotifier(IServerApplicationHost appHost, IUserManager userManager, IInstallationManager installationManager, ITaskManager taskManager, ISessionManager sessionManager)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ServerEventNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="appHost">The application host.</param>
|
||||
/// <param name="userManager">The user manager.</param>
|
||||
/// <param name="installationManager">The installation manager.</param>
|
||||
/// <param name="taskManager">The task manager.</param>
|
||||
/// <param name="sessionManager">The session manager.</param>
|
||||
public ServerEventNotifier(
|
||||
IServerApplicationHost appHost,
|
||||
IUserManager userManager,
|
||||
IInstallationManager installationManager,
|
||||
ITaskManager taskManager,
|
||||
ISessionManager sessionManager)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_installationManager = installationManager;
|
||||
@@ -51,47 +64,48 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
_sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task RunAsync()
|
||||
{
|
||||
_userManager.UserDeleted += userManager_UserDeleted;
|
||||
_userManager.UserUpdated += userManager_UserUpdated;
|
||||
_userManager.UserPolicyUpdated += _userManager_UserPolicyUpdated;
|
||||
_userManager.UserConfigurationUpdated += _userManager_UserConfigurationUpdated;
|
||||
_userManager.UserDeleted += OnUserDeleted;
|
||||
_userManager.UserUpdated += OnUserUpdated;
|
||||
_userManager.UserPolicyUpdated += OnUserPolicyUpdated;
|
||||
_userManager.UserConfigurationUpdated += OnUserConfigurationUpdated;
|
||||
|
||||
_appHost.HasPendingRestartChanged += kernel_HasPendingRestartChanged;
|
||||
_appHost.HasPendingRestartChanged += OnHasPendingRestartChanged;
|
||||
|
||||
_installationManager.PluginUninstalled += InstallationManager_PluginUninstalled;
|
||||
_installationManager.PackageInstalling += _installationManager_PackageInstalling;
|
||||
_installationManager.PackageInstallationCancelled += _installationManager_PackageInstallationCancelled;
|
||||
_installationManager.PackageInstallationCompleted += _installationManager_PackageInstallationCompleted;
|
||||
_installationManager.PackageInstallationFailed += _installationManager_PackageInstallationFailed;
|
||||
_installationManager.PluginUninstalled += OnPluginUninstalled;
|
||||
_installationManager.PackageInstalling += OnPackageInstalling;
|
||||
_installationManager.PackageInstallationCancelled += OnPackageInstallationCancelled;
|
||||
_installationManager.PackageInstallationCompleted += OnPackageInstallationCompleted;
|
||||
_installationManager.PackageInstallationFailed += OnPackageInstallationFailed;
|
||||
|
||||
_taskManager.TaskCompleted += _taskManager_TaskCompleted;
|
||||
_taskManager.TaskCompleted += OnTaskCompleted;
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
void _installationManager_PackageInstalling(object sender, InstallationEventArgs e)
|
||||
private void OnPackageInstalling(object sender, InstallationEventArgs e)
|
||||
{
|
||||
SendMessageToAdminSessions("PackageInstalling", e.InstallationInfo);
|
||||
}
|
||||
|
||||
void _installationManager_PackageInstallationCancelled(object sender, InstallationEventArgs e)
|
||||
private void OnPackageInstallationCancelled(object sender, InstallationEventArgs e)
|
||||
{
|
||||
SendMessageToAdminSessions("PackageInstallationCancelled", e.InstallationInfo);
|
||||
}
|
||||
|
||||
void _installationManager_PackageInstallationCompleted(object sender, InstallationEventArgs e)
|
||||
private void OnPackageInstallationCompleted(object sender, InstallationEventArgs e)
|
||||
{
|
||||
SendMessageToAdminSessions("PackageInstallationCompleted", e.InstallationInfo);
|
||||
}
|
||||
|
||||
void _installationManager_PackageInstallationFailed(object sender, InstallationFailedEventArgs e)
|
||||
private void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e)
|
||||
{
|
||||
SendMessageToAdminSessions("PackageInstallationFailed", e.InstallationInfo);
|
||||
}
|
||||
|
||||
void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e)
|
||||
private void OnTaskCompleted(object sender, TaskCompletionEventArgs e)
|
||||
{
|
||||
SendMessageToAdminSessions("ScheduledTaskEnded", e.Result);
|
||||
}
|
||||
@@ -101,7 +115,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="e">The e.</param>
|
||||
void InstallationManager_PluginUninstalled(object sender, GenericEventArgs<IPlugin> e)
|
||||
private void OnPluginUninstalled(object sender, GenericEventArgs<IPlugin> e)
|
||||
{
|
||||
SendMessageToAdminSessions("PluginUninstalled", e.Argument.GetPluginInfo());
|
||||
}
|
||||
@@ -111,7 +125,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
/// </summary>
|
||||
/// <param name="sender">The source of the event.</param>
|
||||
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
|
||||
void kernel_HasPendingRestartChanged(object sender, EventArgs e)
|
||||
private void OnHasPendingRestartChanged(object sender, EventArgs e)
|
||||
{
|
||||
_sessionManager.SendRestartRequiredNotification(CancellationToken.None);
|
||||
}
|
||||
@@ -121,7 +135,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="e">The e.</param>
|
||||
void userManager_UserUpdated(object sender, GenericEventArgs<User> e)
|
||||
private void OnUserUpdated(object sender, GenericEventArgs<User> e)
|
||||
{
|
||||
var dto = _userManager.GetUserDto(e.Argument);
|
||||
|
||||
@@ -133,19 +147,19 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="e">The e.</param>
|
||||
void userManager_UserDeleted(object sender, GenericEventArgs<User> e)
|
||||
private void OnUserDeleted(object sender, GenericEventArgs<User> e)
|
||||
{
|
||||
SendMessageToUserSession(e.Argument, "UserDeleted", e.Argument.Id.ToString("N", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
void _userManager_UserPolicyUpdated(object sender, GenericEventArgs<User> e)
|
||||
private void OnUserPolicyUpdated(object sender, GenericEventArgs<User> e)
|
||||
{
|
||||
var dto = _userManager.GetUserDto(e.Argument);
|
||||
|
||||
SendMessageToUserSession(e.Argument, "UserPolicyUpdated", dto);
|
||||
}
|
||||
|
||||
void _userManager_UserConfigurationUpdated(object sender, GenericEventArgs<User> e)
|
||||
private void OnUserConfigurationUpdated(object sender, GenericEventArgs<User> e)
|
||||
{
|
||||
var dto = _userManager.GetUserDto(e.Argument);
|
||||
|
||||
@@ -168,7 +182,11 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
{
|
||||
try
|
||||
{
|
||||
await _sessionManager.SendMessageToUserSessions(new List<Guid> { user.Id }, name, data, CancellationToken.None);
|
||||
await _sessionManager.SendMessageToUserSessions(
|
||||
new List<Guid> { user.Id },
|
||||
name,
|
||||
data,
|
||||
CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -176,12 +194,11 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -192,18 +209,20 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
{
|
||||
if (dispose)
|
||||
{
|
||||
_userManager.UserDeleted -= userManager_UserDeleted;
|
||||
_userManager.UserUpdated -= userManager_UserUpdated;
|
||||
_userManager.UserPolicyUpdated -= _userManager_UserPolicyUpdated;
|
||||
_userManager.UserConfigurationUpdated -= _userManager_UserConfigurationUpdated;
|
||||
_userManager.UserDeleted -= OnUserDeleted;
|
||||
_userManager.UserUpdated -= OnUserUpdated;
|
||||
_userManager.UserPolicyUpdated -= OnUserPolicyUpdated;
|
||||
_userManager.UserConfigurationUpdated -= OnUserConfigurationUpdated;
|
||||
|
||||
_installationManager.PluginUninstalled -= InstallationManager_PluginUninstalled;
|
||||
_installationManager.PackageInstalling -= _installationManager_PackageInstalling;
|
||||
_installationManager.PackageInstallationCancelled -= _installationManager_PackageInstallationCancelled;
|
||||
_installationManager.PackageInstallationCompleted -= _installationManager_PackageInstallationCompleted;
|
||||
_installationManager.PackageInstallationFailed -= _installationManager_PackageInstallationFailed;
|
||||
_installationManager.PluginUninstalled -= OnPluginUninstalled;
|
||||
_installationManager.PackageInstalling -= OnPackageInstalling;
|
||||
_installationManager.PackageInstallationCancelled -= OnPackageInstallationCancelled;
|
||||
_installationManager.PackageInstallationCompleted -= OnPackageInstallationCompleted;
|
||||
_installationManager.PackageInstallationFailed -= OnPackageInstallationFailed;
|
||||
|
||||
_appHost.HasPendingRestartChanged -= kernel_HasPendingRestartChanged;
|
||||
_appHost.HasPendingRestartChanged -= OnHasPendingRestartChanged;
|
||||
|
||||
_taskManager.TaskCompleted -= OnTaskCompleted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,21 +8,28 @@ using Microsoft.Extensions.Logging;
|
||||
namespace Emby.Server.Implementations.EntryPoints
|
||||
{
|
||||
/// <summary>
|
||||
/// Class StartupWizard
|
||||
/// Class StartupWizard.
|
||||
/// </summary>
|
||||
public class StartupWizard : IServerEntryPoint
|
||||
{
|
||||
/// <summary>
|
||||
/// The _app host
|
||||
/// The app host.
|
||||
/// </summary>
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
|
||||
/// <summary>
|
||||
/// The _user manager
|
||||
/// The user manager.
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
|
||||
private IServerConfigurationManager _config;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StartupWizard"/> class.
|
||||
/// </summary>
|
||||
/// <param name="appHost">The application host.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="config">The configuration manager.</param>
|
||||
public StartupWizard(IServerApplicationHost appHost, ILogger logger, IServerConfigurationManager config)
|
||||
{
|
||||
_appHost = appHost;
|
||||
@@ -30,9 +37,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
_config = config;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs this instance.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public Task RunAsync()
|
||||
{
|
||||
if (!_appHost.CanLaunchWebBrowser)
|
||||
@@ -57,9 +62,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -10,30 +10,36 @@ using Microsoft.Extensions.Logging;
|
||||
namespace Emby.Server.Implementations.EntryPoints
|
||||
{
|
||||
/// <summary>
|
||||
/// Class UdpServerEntryPoint
|
||||
/// Class UdpServerEntryPoint.
|
||||
/// </summary>
|
||||
public class UdpServerEntryPoint : IServerEntryPoint
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the UDP server.
|
||||
/// The port of the UDP server.
|
||||
/// </summary>
|
||||
/// <value>The UDP server.</value>
|
||||
private UdpServer UdpServer { get; set; }
|
||||
public const int PortNumber = 7359;
|
||||
|
||||
/// <summary>
|
||||
/// The _logger
|
||||
/// The logger.
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
private readonly ISocketFactory _socketFactory;
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
private readonly IJsonSerializer _json;
|
||||
|
||||
public const int PortNumber = 7359;
|
||||
/// <summary>
|
||||
/// The UDP server.
|
||||
/// </summary>
|
||||
private UdpServer _udpServer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UdpServerEntryPoint" /> class.
|
||||
/// </summary>
|
||||
public UdpServerEntryPoint(ILogger logger, IServerApplicationHost appHost, IJsonSerializer json, ISocketFactory socketFactory)
|
||||
public UdpServerEntryPoint(
|
||||
ILogger logger,
|
||||
IServerApplicationHost appHost,
|
||||
IJsonSerializer json,
|
||||
ISocketFactory socketFactory)
|
||||
{
|
||||
_logger = logger;
|
||||
_appHost = appHost;
|
||||
@@ -41,9 +47,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
_socketFactory = socketFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs this instance.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public Task RunAsync()
|
||||
{
|
||||
var udpServer = new UdpServer(_logger, _appHost, _json, _socketFactory);
|
||||
@@ -52,7 +56,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
{
|
||||
udpServer.Start(PortNumber);
|
||||
|
||||
UdpServer = udpServer;
|
||||
_udpServer = udpServer;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -62,12 +66,11 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -78,9 +81,9 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
{
|
||||
if (dispose)
|
||||
{
|
||||
if (UdpServer != null)
|
||||
if (_udpServer != null)
|
||||
{
|
||||
UdpServer.Dispose();
|
||||
_udpServer.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
@@ -282,6 +282,7 @@ namespace Emby.Server.Implementations.HttpClientManager
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<HttpResponseInfo> Post(HttpRequestOptions options)
|
||||
=> SendAsync(options, HttpMethod.Post);
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
@@ -5,12 +7,10 @@ using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Net;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using Emby.Server.Implementations.Services;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
@@ -24,12 +24,12 @@ using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
|
||||
namespace Emby.Server.Implementations.HttpServer
|
||||
{
|
||||
/// <summary>
|
||||
/// Class HttpResultFactory
|
||||
/// Class HttpResultFactory.
|
||||
/// </summary>
|
||||
public class HttpResultFactory : IHttpResultFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The _logger
|
||||
/// The logger.
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
@@ -8,11 +8,17 @@ using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Emby.Server.Implementations.HttpServer
|
||||
{
|
||||
/// <summary>
|
||||
/// Class ResponseFilter.
|
||||
/// </summary>
|
||||
public class ResponseFilter
|
||||
{
|
||||
private static readonly CultureInfo _usCulture = CultureInfo.ReadOnly(new CultureInfo("en-US"));
|
||||
private readonly ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ResponseFilter"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public ResponseFilter(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
@@ -37,7 +43,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
|
||||
if (!string.IsNullOrEmpty(exception.Message))
|
||||
{
|
||||
var error = exception.Message.Replace(Environment.NewLine, " ");
|
||||
var error = exception.Message.Replace(Environment.NewLine, " ", StringComparison.Ordinal);
|
||||
error = RemoveControlCharacters(error);
|
||||
|
||||
res.Headers.Add("X-Application-Error-Code", error);
|
||||
@@ -55,7 +61,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
if (hasHeaders.Headers.TryGetValue(HeaderNames.ContentLength, out string contentLength)
|
||||
&& !string.IsNullOrEmpty(contentLength))
|
||||
{
|
||||
var length = long.Parse(contentLength, _usCulture);
|
||||
var length = long.Parse(contentLength, CultureInfo.InvariantCulture);
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Emby.Server.Implementations.SocketSharp;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
|
||||
@@ -10,37 +10,20 @@ using Microsoft.Net.Http.Headers;
|
||||
namespace Emby.Server.Implementations.HttpServer
|
||||
{
|
||||
/// <summary>
|
||||
/// Class StreamWriter
|
||||
/// Class StreamWriter.
|
||||
/// </summary>
|
||||
public class StreamWriter : IAsyncStreamWriter, IHasHeaders
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the source stream.
|
||||
/// </summary>
|
||||
/// <value>The source stream.</value>
|
||||
private Stream SourceStream { get; set; }
|
||||
|
||||
private byte[] SourceBytes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The _options
|
||||
/// The options.
|
||||
/// </summary>
|
||||
private readonly IDictionary<string, string> _options = new Dictionary<string, string>();
|
||||
/// <summary>
|
||||
/// Gets the options.
|
||||
/// </summary>
|
||||
/// <value>The options.</value>
|
||||
public IDictionary<string, string> Headers => _options;
|
||||
|
||||
public Action OnComplete { get; set; }
|
||||
public Action OnError { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StreamWriter" /> class.
|
||||
/// </summary>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="contentType">Type of the content.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public StreamWriter(Stream source, string contentType)
|
||||
{
|
||||
if (string.IsNullOrEmpty(contentType))
|
||||
@@ -65,6 +48,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
/// </summary>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="contentType">Type of the content.</param>
|
||||
/// <param name="contentLength">The content length.</param>
|
||||
public StreamWriter(byte[] source, string contentType, int contentLength)
|
||||
{
|
||||
if (string.IsNullOrEmpty(contentType))
|
||||
@@ -78,6 +62,31 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
Headers[HeaderNames.ContentType] = contentType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the source stream.
|
||||
/// </summary>
|
||||
/// <value>The source stream.</value>
|
||||
private Stream SourceStream { get; set; }
|
||||
|
||||
private byte[] SourceBytes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the options.
|
||||
/// </summary>
|
||||
/// <value>The options.</value>
|
||||
public IDictionary<string, string> Headers => _options;
|
||||
|
||||
/// <summary>
|
||||
/// Fires when complete.
|
||||
/// </summary>
|
||||
public Action OnComplete { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Fires when an error occours.
|
||||
/// </summary>
|
||||
public Action OnError { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task WriteToAsync(Stream responseStream, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
@@ -98,19 +107,13 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (OnError != null)
|
||||
{
|
||||
OnError();
|
||||
}
|
||||
OnError?.Invoke();
|
||||
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (OnComplete != null)
|
||||
{
|
||||
OnComplete();
|
||||
}
|
||||
OnComplete?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ using Emby.Server.Implementations.Net;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Model.Net;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Model.Services;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using UtfUnknown;
|
||||
@@ -15,32 +14,74 @@ using UtfUnknown;
|
||||
namespace Emby.Server.Implementations.HttpServer
|
||||
{
|
||||
/// <summary>
|
||||
/// Class WebSocketConnection
|
||||
/// Class WebSocketConnection.
|
||||
/// </summary>
|
||||
public class WebSocketConnection : IWebSocketConnection
|
||||
{
|
||||
public event EventHandler<EventArgs> Closed;
|
||||
|
||||
/// <summary>
|
||||
/// The _socket
|
||||
/// </summary>
|
||||
private readonly IWebSocket _socket;
|
||||
|
||||
/// <summary>
|
||||
/// The _remote end point
|
||||
/// </summary>
|
||||
public string RemoteEndPoint { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The logger
|
||||
/// The logger.
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// The _json serializer
|
||||
/// The json serializer.
|
||||
/// </summary>
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
|
||||
/// <summary>
|
||||
/// The socket.
|
||||
/// </summary>
|
||||
private readonly IWebSocket _socket;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebSocketConnection" /> class.
|
||||
/// </summary>
|
||||
/// <param name="socket">The socket.</param>
|
||||
/// <param name="remoteEndPoint">The remote end point.</param>
|
||||
/// <param name="jsonSerializer">The json serializer.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <exception cref="ArgumentNullException">socket</exception>
|
||||
public WebSocketConnection(IWebSocket socket, string remoteEndPoint, IJsonSerializer jsonSerializer, ILogger logger)
|
||||
{
|
||||
if (socket == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(socket));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(remoteEndPoint))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(remoteEndPoint));
|
||||
}
|
||||
|
||||
if (jsonSerializer == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(jsonSerializer));
|
||||
}
|
||||
|
||||
if (logger == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
Id = Guid.NewGuid();
|
||||
_jsonSerializer = jsonSerializer;
|
||||
_socket = socket;
|
||||
_socket.OnReceiveBytes = OnReceiveInternal;
|
||||
|
||||
RemoteEndPoint = remoteEndPoint;
|
||||
_logger = logger;
|
||||
|
||||
socket.Closed += OnSocketClosed;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler<EventArgs> Closed;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the remote end point.
|
||||
/// </summary>
|
||||
public string RemoteEndPoint { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the receive action.
|
||||
/// </summary>
|
||||
@@ -64,6 +105,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
/// </summary>
|
||||
/// <value>The URL.</value>
|
||||
public string Url { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the query string.
|
||||
/// </summary>
|
||||
@@ -71,44 +113,12 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
public IQueryCollection QueryString { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebSocketConnection" /> class.
|
||||
/// Gets the state.
|
||||
/// </summary>
|
||||
/// <param name="socket">The socket.</param>
|
||||
/// <param name="remoteEndPoint">The remote end point.</param>
|
||||
/// <param name="jsonSerializer">The json serializer.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <exception cref="ArgumentNullException">socket</exception>
|
||||
public WebSocketConnection(IWebSocket socket, string remoteEndPoint, IJsonSerializer jsonSerializer, ILogger logger)
|
||||
{
|
||||
if (socket == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(socket));
|
||||
}
|
||||
if (string.IsNullOrEmpty(remoteEndPoint))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(remoteEndPoint));
|
||||
}
|
||||
if (jsonSerializer == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(jsonSerializer));
|
||||
}
|
||||
if (logger == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
/// <value>The state.</value>
|
||||
public WebSocketState State => _socket.State;
|
||||
|
||||
Id = Guid.NewGuid();
|
||||
_jsonSerializer = jsonSerializer;
|
||||
_socket = socket;
|
||||
_socket.OnReceiveBytes = OnReceiveInternal;
|
||||
|
||||
RemoteEndPoint = remoteEndPoint;
|
||||
_logger = logger;
|
||||
|
||||
socket.Closed += socket_Closed;
|
||||
}
|
||||
|
||||
void socket_Closed(object sender, EventArgs e)
|
||||
void OnSocketClosed(object sender, EventArgs e)
|
||||
{
|
||||
Closed?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
@@ -210,6 +220,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
return _socket.SendAsync(buffer, true, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task SendAsync(string text, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text))
|
||||
@@ -222,18 +233,11 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
return _socket.SendAsync(text, true, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the state.
|
||||
/// </summary>
|
||||
/// <value>The state.</value>
|
||||
public WebSocketState State => _socket.State;
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
namespace Emby.Server.Implementations.IO
|
||||
{
|
||||
public class ExtendedFileSystemInfo
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@@ -16,22 +18,22 @@ namespace Emby.Server.Implementations.IO
|
||||
public class LibraryMonitor : ILibraryMonitor
|
||||
{
|
||||
/// <summary>
|
||||
/// The file system watchers
|
||||
/// The file system watchers.
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<string, FileSystemWatcher> _fileSystemWatchers = new ConcurrentDictionary<string, FileSystemWatcher>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// The affected paths
|
||||
/// The affected paths.
|
||||
/// </summary>
|
||||
private readonly List<FileRefresher> _activeRefreshers = new List<FileRefresher>();
|
||||
|
||||
/// <summary>
|
||||
/// A dynamic list of paths that should be ignored. Added to during our own file sytem modifications.
|
||||
/// A dynamic list of paths that should be ignored. Added to during our own file system modifications.
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<string, string> _tempIgnoredPaths = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Any file name ending in any of these will be ignored by the watchers
|
||||
/// Any file name ending in any of these will be ignored by the watchers.
|
||||
/// </summary>
|
||||
private static readonly HashSet<string> _alwaysIgnoreFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
@@ -107,7 +109,7 @@ namespace Emby.Server.Implementations.IO
|
||||
}
|
||||
try
|
||||
{
|
||||
return Path.Combine(Path.GetFullPath(folderPath), filePath);
|
||||
return Path.GetFullPath(Path.Combine(folderPath, filePath));
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using MediaBrowser.Model.IO;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
@@ -42,6 +42,10 @@ namespace Emby.Server.Implementations.Library
|
||||
".grab",
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CoreResolutionIgnoreRule"/> class.
|
||||
/// </summary>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
public CoreResolutionIgnoreRule(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
|
||||
@@ -10,10 +10,17 @@ using MediaBrowser.Model.Cryptography;
|
||||
|
||||
namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
/// <summary>
|
||||
/// The default authentication provider.
|
||||
/// </summary>
|
||||
public class DefaultAuthenticationProvider : IAuthenticationProvider, IRequiresResolvedUser
|
||||
{
|
||||
private readonly ICryptoProvider _cryptographyProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DefaultAuthenticationProvider"/> class.
|
||||
/// </summary>
|
||||
/// <param name="cryptographyProvider">The cryptography provider.</param>
|
||||
public DefaultAuthenticationProvider(ICryptoProvider cryptographyProvider)
|
||||
{
|
||||
_cryptographyProvider = cryptographyProvider;
|
||||
@@ -38,12 +45,13 @@ namespace Emby.Server.Implementations.Library
|
||||
// This is the version that we need to use for local users. Because reasons.
|
||||
public Task<ProviderAuthenticationResult> Authenticate(string username, string password, User resolvedUser)
|
||||
{
|
||||
bool success = false;
|
||||
if (resolvedUser == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(resolvedUser));
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
|
||||
// As long as jellyfin supports passwordless users, we need this little block here to accommodate
|
||||
if (!HasPassword(resolvedUser) && string.IsNullOrEmpty(password))
|
||||
{
|
||||
|
||||
@@ -12,6 +12,9 @@ using MediaBrowser.Model.Users;
|
||||
|
||||
namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
/// <summary>
|
||||
/// The default password reset provider.
|
||||
/// </summary>
|
||||
public class DefaultPasswordResetProvider : IPasswordResetProvider
|
||||
{
|
||||
private const string BaseResetFileName = "passwordreset";
|
||||
@@ -22,6 +25,12 @@ namespace Emby.Server.Implementations.Library
|
||||
private readonly string _passwordResetFileBase;
|
||||
private readonly string _passwordResetFileBaseDir;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DefaultPasswordResetProvider"/> class.
|
||||
/// </summary>
|
||||
/// <param name="configurationManager">The configuration manager.</param>
|
||||
/// <param name="jsonSerializer">The JSON serializer.</param>
|
||||
/// <param name="userManager">The user manager.</param>
|
||||
public DefaultPasswordResetProvider(
|
||||
IServerConfigurationManager configurationManager,
|
||||
IJsonSerializer jsonSerializer,
|
||||
@@ -56,8 +65,8 @@ namespace Emby.Server.Implementations.Library
|
||||
File.Delete(resetfile);
|
||||
}
|
||||
else if (string.Equals(
|
||||
spr.Pin.Replace("-", string.Empty),
|
||||
pin.Replace("-", string.Empty),
|
||||
spr.Pin.Replace("-", string.Empty, StringComparison.Ordinal),
|
||||
pin.Replace("-", string.Empty, StringComparison.Ordinal),
|
||||
StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
var resetUser = _userManager.GetUserByName(spr.UserName);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
|
||||
@@ -4,37 +4,48 @@ using MediaBrowser.Controller.Entities;
|
||||
|
||||
namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
/// <summary>
|
||||
/// An invalid authentication provider.
|
||||
/// </summary>
|
||||
public class InvalidAuthProvider : IAuthenticationProvider
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public string Name => "InvalidOrMissingAuthenticationProvider";
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEnabled => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<ProviderAuthenticationResult> Authenticate(string username, string password)
|
||||
{
|
||||
throw new AuthenticationException("User Account cannot login with this provider. The Normal provider for this user cannot be found");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool HasPassword(User user)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task ChangePassword(User user, string newPassword)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ChangeEasyPassword(User user, string newPassword, string newPasswordHash)
|
||||
{
|
||||
// Nothing here
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetPasswordHash(User user)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetEasyPasswordHash(User user)
|
||||
{
|
||||
return string.Empty;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@@ -390,9 +392,9 @@ namespace Emby.Server.Implementations.Library
|
||||
// Add this flag to GetDeletePaths if required in the future
|
||||
var isRequiredForDelete = true;
|
||||
|
||||
foreach (var fileSystemInfo in item.GetDeletePaths().ToList())
|
||||
foreach (var fileSystemInfo in item.GetDeletePaths())
|
||||
{
|
||||
if (File.Exists(fileSystemInfo.FullName))
|
||||
if (Directory.Exists(fileSystemInfo.FullName) || File.Exists(fileSystemInfo.FullName))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -829,7 +831,7 @@ namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
Path = path,
|
||||
IsFolder = isFolder,
|
||||
OrderBy = new[] { ItemSortBy.DateCreated }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(),
|
||||
OrderBy = new[] { (ItemSortBy.DateCreated, SortOrder.Descending) },
|
||||
Limit = 1,
|
||||
DtoOptions = new DtoOptions(true)
|
||||
};
|
||||
@@ -1257,7 +1259,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
public List<BaseItem> GetItemList(InternalItemsQuery query, bool allowExternalContent)
|
||||
{
|
||||
if (query.Recursive && !query.ParentId.Equals(Guid.Empty))
|
||||
if (query.Recursive && query.ParentId != Guid.Empty)
|
||||
{
|
||||
var parent = GetItemById(query.ParentId);
|
||||
if (parent != null)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
@@ -128,6 +130,21 @@ namespace Emby.Server.Implementations.Library
|
||||
return streams;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<MediaAttachment> GetMediaAttachments(MediaAttachmentQuery query)
|
||||
{
|
||||
return _itemRepo.GetMediaAttachments(query);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<MediaAttachment> GetMediaAttachments(Guid itemId)
|
||||
{
|
||||
return GetMediaAttachments(new MediaAttachmentQuery
|
||||
{
|
||||
ItemId = itemId
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<List<MediaSourceInfo>> GetPlaybackMediaSources(BaseItem item, User user, bool allowMediaProbe, bool enablePathSubstitution, CancellationToken cancellationToken)
|
||||
{
|
||||
var mediaSources = GetStaticMediaSources(item, enablePathSubstitution, user);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -89,10 +91,9 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
Limit = 200,
|
||||
|
||||
OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending) },
|
||||
OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) },
|
||||
|
||||
DtoOptions = dtoOptions
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@ using System.Text.RegularExpressions;
|
||||
|
||||
namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
/// <summary>
|
||||
/// Class providing extension methods for working with paths.
|
||||
/// </summary>
|
||||
public static class PathExtensions
|
||||
{
|
||||
/// <summary>
|
||||
@@ -32,6 +35,7 @@ namespace Emby.Server.Implementations.Library
|
||||
int end = str.IndexOf(']', start);
|
||||
return str.Substring(start, end - start);
|
||||
}
|
||||
|
||||
// for imdbid we also accept pattern matching
|
||||
if (string.Equals(attrib, "imdbid", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -13,7 +15,7 @@ using MediaBrowser.Model.IO;
|
||||
namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
{
|
||||
/// <summary>
|
||||
/// Class AudioResolver
|
||||
/// Class AudioResolver.
|
||||
/// </summary>
|
||||
public class AudioResolver : ItemResolver<MediaBrowser.Controller.Entities.Audio.Audio>, IMultiItemResolver
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ using Microsoft.Extensions.Logging;
|
||||
namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
{
|
||||
/// <summary>
|
||||
/// Class MusicAlbumResolver
|
||||
/// Class MusicAlbumResolver.
|
||||
/// </summary>
|
||||
public class MusicAlbumResolver : ItemResolver<MusicAlbum>
|
||||
{
|
||||
@@ -21,6 +21,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MusicAlbumResolver"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="fileSystem">The file system.</param>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
public MusicAlbumResolver(ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager)
|
||||
{
|
||||
_logger = logger;
|
||||
@@ -50,16 +56,25 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!args.IsDirectory) return null;
|
||||
if (!args.IsDirectory)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Avoid mis-identifying top folders
|
||||
if (args.HasParent<MusicAlbum>()) return null;
|
||||
if (args.Parent.IsRoot) return null;
|
||||
if (args.HasParent<MusicAlbum>())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (args.Parent.IsRoot)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return IsMusicAlbum(args) ? new MusicAlbum() : null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the supplied file data points to a music album
|
||||
/// </summary>
|
||||
@@ -78,8 +93,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
// Args points to an album if parent is an Artist folder or it directly contains music
|
||||
if (args.IsDirectory)
|
||||
{
|
||||
//if (args.Parent is MusicArtist) return true; //saves us from testing children twice
|
||||
if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService, _logger, _fileSystem, args.GetLibraryOptions(), _libraryManager)) return true;
|
||||
// if (args.Parent is MusicArtist) return true; //saves us from testing children twice
|
||||
if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService, _logger, _fileSystem, args.GetLibraryOptions(), _libraryManager))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -88,7 +106,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
/// <summary>
|
||||
/// Determine if the supplied list contains what we should consider music
|
||||
/// </summary>
|
||||
private bool ContainsMusic(IEnumerable<FileSystemMetadata> list,
|
||||
private bool ContainsMusic(
|
||||
IEnumerable<FileSystemMetadata> list,
|
||||
bool allowSubfolders,
|
||||
IDirectoryService directoryService,
|
||||
ILogger logger,
|
||||
|
||||
@@ -11,7 +11,7 @@ using Microsoft.Extensions.Logging;
|
||||
namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
{
|
||||
/// <summary>
|
||||
/// Class MusicArtistResolver
|
||||
/// Class MusicArtistResolver.
|
||||
/// </summary>
|
||||
public class MusicArtistResolver : ItemResolver<MusicArtist>
|
||||
{
|
||||
@@ -20,6 +20,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IServerConfigurationManager _config;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MusicArtistResolver"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="fileSystem">The file system.</param>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
/// <param name="config">The configuration manager.</param>
|
||||
public MusicArtistResolver(ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager, IServerConfigurationManager config)
|
||||
{
|
||||
_logger = logger;
|
||||
@@ -41,7 +48,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
/// <returns>MusicArtist.</returns>
|
||||
protected override MusicArtist Resolve(ItemResolveArgs args)
|
||||
{
|
||||
if (!args.IsDirectory) return null;
|
||||
if (!args.IsDirectory)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Don't allow nested artists
|
||||
if (args.HasParent<MusicArtist>() || args.HasParent<MusicAlbum>())
|
||||
@@ -79,6 +89,5 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
// If we contain an album assume we are an artist folder
|
||||
return args.FileSystemChildren.Where(i => i.IsDirectory).Any(i => albumResolver.IsMusicAlbum(i.FullName, directoryService, args.GetLibraryOptions())) ? new MusicArtist() : null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -10,7 +12,7 @@ using MediaBrowser.Model.Entities;
|
||||
namespace Emby.Server.Implementations.Library.Resolvers
|
||||
{
|
||||
/// <summary>
|
||||
/// Resolves a Path into a Video or Video subclass
|
||||
/// Resolves a Path into a Video or Video subclass.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract class BaseVideoResolver<T> : MediaBrowser.Controller.Resolvers.ItemResolver<T>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -7,18 +9,10 @@ using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace Emby.Server.Implementations.Library.Resolvers.Books
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class BookResolver : MediaBrowser.Controller.Resolvers.ItemResolver<Book>
|
||||
{
|
||||
private readonly string[] _validExtensions = { ".pdf", ".epub", ".mobi", ".cbr", ".cbz", ".azw3" };
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
protected override Book Resolve(ItemResolveArgs args)
|
||||
{
|
||||
var collectionType = args.GetCollectionType();
|
||||
@@ -47,11 +41,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
private Book GetBook(ItemResolveArgs args)
|
||||
{
|
||||
var bookFiles = args.FileSystemChildren.Where(f =>
|
||||
|
||||
@@ -5,7 +5,7 @@ using MediaBrowser.Controller.Resolvers;
|
||||
namespace Emby.Server.Implementations.Library.Resolvers
|
||||
{
|
||||
/// <summary>
|
||||
/// Class FolderResolver
|
||||
/// Class FolderResolver.
|
||||
/// </summary>
|
||||
public class FolderResolver : FolderResolver<Folder>
|
||||
{
|
||||
@@ -32,7 +32,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class FolderResolver
|
||||
/// Class FolderResolver.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItemType">The type of the T item type.</typeparam>
|
||||
public abstract class FolderResolver<TItemType> : ItemResolver<TItemType>
|
||||
|
||||
@@ -5,7 +5,7 @@ using MediaBrowser.Controller.Resolvers;
|
||||
namespace Emby.Server.Implementations.Library.Resolvers
|
||||
{
|
||||
/// <summary>
|
||||
/// Class ItemResolver
|
||||
/// Class ItemResolver.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract class ItemResolver<T> : IItemResolver
|
||||
|
||||
@@ -4,12 +4,11 @@ using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
|
||||
namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
{
|
||||
/// <summary>
|
||||
/// Class BoxSetResolver
|
||||
/// Class BoxSetResolver.
|
||||
/// </summary>
|
||||
public class BoxSetResolver : FolderResolver<BoxSet>
|
||||
{
|
||||
@@ -63,7 +62,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
/// <param name="item">The item.</param>
|
||||
private static void SetProviderIdFromPath(BaseItem item)
|
||||
{
|
||||
//we need to only look at the name of this actual item (not parents)
|
||||
// we need to only look at the name of this actual item (not parents)
|
||||
var justName = Path.GetFileName(item.Path);
|
||||
|
||||
var id = justName.GetAttributeValue("tmdbid");
|
||||
|
||||
@@ -17,7 +17,7 @@ using MediaBrowser.Model.IO;
|
||||
namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
{
|
||||
/// <summary>
|
||||
/// Class MovieResolver
|
||||
/// Class MovieResolver.
|
||||
/// </summary>
|
||||
public class MovieResolver : BaseVideoResolver<Video>, IMultiItemResolver
|
||||
{
|
||||
@@ -27,6 +27,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
/// <value>The priority.</value>
|
||||
public override ResolverPriority Priority => ResolverPriority.Third;
|
||||
|
||||
/// <inheritdoc />
|
||||
public MultiItemResolverResult ResolveMultiple(
|
||||
Folder parent,
|
||||
List<FileSystemMetadata> files,
|
||||
@@ -522,7 +523,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
CollectionType.MusicVideos,
|
||||
CollectionType.Movies,
|
||||
CollectionType.Photos
|
||||
};
|
||||
};
|
||||
|
||||
private bool IsInvalid(Folder parent, string collectionType)
|
||||
{
|
||||
@@ -544,6 +545,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
|
||||
private IImageProcessor _imageProcessor;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MovieResolver"/> class.
|
||||
/// </summary>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
/// <param name="imageProcessor">The image processor.</param>
|
||||
public MovieResolver(ILibraryManager libraryManager, IImageProcessor imageProcessor)
|
||||
: base(libraryManager)
|
||||
{
|
||||
|
||||
@@ -7,11 +7,19 @@ using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace Emby.Server.Implementations.Library.Resolvers
|
||||
{
|
||||
/// <summary>
|
||||
/// Class PhotoAlbumResolver.
|
||||
/// </summary>
|
||||
public class PhotoAlbumResolver : FolderResolver<PhotoAlbum>
|
||||
{
|
||||
private readonly IImageProcessor _imageProcessor;
|
||||
private ILibraryManager _libraryManager;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PhotoAlbumResolver"/> class.
|
||||
/// </summary>
|
||||
/// <param name="imageProcessor">The image processor.</param>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
public PhotoAlbumResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager)
|
||||
{
|
||||
_imageProcessor = imageProcessor;
|
||||
@@ -74,9 +82,11 @@ namespace Emby.Server.Implementations.Library.Resolvers
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ResolverPriority Priority => ResolverPriority.Second;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Playlists;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
|
||||
namespace Emby.Server.Implementations.Library.Resolvers
|
||||
{
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
@@ -7,7 +7,7 @@ using MediaBrowser.Model.Entities;
|
||||
namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
{
|
||||
/// <summary>
|
||||
/// Class EpisodeResolver
|
||||
/// Class EpisodeResolver.
|
||||
/// </summary>
|
||||
public class EpisodeResolver : BaseVideoResolver<Episode>
|
||||
{
|
||||
@@ -26,6 +26,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
}
|
||||
|
||||
var season = parent as Season;
|
||||
|
||||
// Just in case the user decided to nest episodes.
|
||||
// Not officially supported but in some cases we can handle it.
|
||||
if (season == null)
|
||||
@@ -73,6 +74,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EpisodeResolver"/> class.
|
||||
/// </summary>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
public EpisodeResolver(ILibraryManager libraryManager)
|
||||
: base(libraryManager)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -14,7 +16,7 @@ using Microsoft.Extensions.Logging;
|
||||
namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
{
|
||||
/// <summary>
|
||||
/// Class SeriesResolver
|
||||
/// Class SeriesResolver.
|
||||
/// </summary>
|
||||
public class SeriesResolver : FolderResolver<Series>
|
||||
{
|
||||
@@ -22,6 +24,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
private readonly ILogger _logger;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SeriesResolver"/> class.
|
||||
/// </summary>
|
||||
/// <param name="fileSystem">The file system.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
public SeriesResolver(IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -13,8 +15,6 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
public class SearchEngine : ISearchEngine
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
@@ -162,7 +162,7 @@ namespace Emby.Server.Implementations.Library
|
||||
Limit = query.Limit,
|
||||
IncludeItemsByName = string.IsNullOrEmpty(query.ParentId),
|
||||
ParentId = string.IsNullOrEmpty(query.ParentId) ? Guid.Empty : new Guid(query.ParentId),
|
||||
OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending) },
|
||||
OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) },
|
||||
Recursive = true,
|
||||
|
||||
IsKids = query.IsKids,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@@ -15,7 +17,7 @@ using Microsoft.Extensions.Logging;
|
||||
namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
/// <summary>
|
||||
/// Class UserDataManager
|
||||
/// Class UserDataManager.
|
||||
/// </summary>
|
||||
public class UserDataManager : IUserDataManager
|
||||
{
|
||||
@@ -55,6 +57,7 @@ namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
throw new ArgumentNullException(nameof(userData));
|
||||
}
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
@@ -160,11 +163,6 @@ namespace Emby.Server.Implementations.Library
|
||||
return GetUserData(user, item.Id, item.GetUserDataKeys());
|
||||
}
|
||||
|
||||
public UserItemData GetUserData(string userId, BaseItem item)
|
||||
{
|
||||
return GetUserData(new Guid(userId), item);
|
||||
}
|
||||
|
||||
public UserItemData GetUserData(Guid userId, BaseItem item)
|
||||
{
|
||||
return GetUserData(userId, item.Id, item.GetUserDataKeys());
|
||||
@@ -228,24 +226,21 @@ namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
var pctIn = decimal.Divide(positionTicks, runtimeTicks) * 100;
|
||||
|
||||
// Don't track in very beginning
|
||||
if (pctIn < _config.Configuration.MinResumePct)
|
||||
{
|
||||
// ignore progress during the beginning
|
||||
positionTicks = 0;
|
||||
}
|
||||
|
||||
// If we're at the end, assume completed
|
||||
else if (pctIn > _config.Configuration.MaxResumePct || positionTicks >= runtimeTicks)
|
||||
{
|
||||
// mark as completed close to the end
|
||||
positionTicks = 0;
|
||||
data.Played = playedToCompletion = true;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// Enforce MinResumeDuration
|
||||
var durationSeconds = TimeSpan.FromTicks(runtimeTicks).TotalSeconds;
|
||||
|
||||
if (durationSeconds < _config.Configuration.MinResumeDurationSeconds)
|
||||
{
|
||||
positionTicks = 0;
|
||||
@@ -265,6 +260,7 @@ namespace Emby.Server.Implementations.Library
|
||||
positionTicks = 0;
|
||||
data.Played = false;
|
||||
}
|
||||
|
||||
if (!item.SupportsPositionTicksResume)
|
||||
{
|
||||
positionTicks = 0;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@@ -36,19 +38,19 @@ using Microsoft.Extensions.Logging;
|
||||
namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
/// <summary>
|
||||
/// Class UserManager
|
||||
/// Class UserManager.
|
||||
/// </summary>
|
||||
public class UserManager : IUserManager
|
||||
{
|
||||
private readonly object _policySyncLock = new object();
|
||||
private readonly object _configSyncLock = new object();
|
||||
/// <summary>
|
||||
/// The _logger
|
||||
/// The logger.
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
|
||||
private readonly object _policySyncLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the active user repository
|
||||
/// Gets the active user repository.
|
||||
/// </summary>
|
||||
/// <value>The user repository.</value>
|
||||
private readonly IUserRepository _userRepository;
|
||||
@@ -194,10 +196,6 @@ namespace Emby.Server.Implementations.Library
|
||||
return user;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public User GetUserById(string id)
|
||||
=> GetUserById(new Guid(id));
|
||||
|
||||
public User GetUserByName(string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
@@ -257,7 +255,12 @@ namespace Emby.Server.Implementations.Library
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
public async Task<User> AuthenticateUser(string username, string password, string hashedPassword, string remoteEndPoint, bool isUserSession)
|
||||
public async Task<User> AuthenticateUser(
|
||||
string username,
|
||||
string password,
|
||||
string hashedPassword,
|
||||
string remoteEndPoint,
|
||||
bool isUserSession)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(username))
|
||||
{
|
||||
@@ -358,6 +361,8 @@ namespace Emby.Server.Implementations.Library
|
||||
return success ? user : null;
|
||||
}
|
||||
|
||||
#nullable enable
|
||||
|
||||
private static string GetAuthenticationProviderId(IAuthenticationProvider provider)
|
||||
{
|
||||
return provider.GetType().FullName;
|
||||
@@ -378,7 +383,7 @@ namespace Emby.Server.Implementations.Library
|
||||
return GetPasswordResetProviders(user)[0];
|
||||
}
|
||||
|
||||
private IAuthenticationProvider[] GetAuthenticationProviders(User user)
|
||||
private IAuthenticationProvider[] GetAuthenticationProviders(User? user)
|
||||
{
|
||||
var authenticationProviderId = user?.Policy.AuthenticationProviderId;
|
||||
|
||||
@@ -392,14 +397,14 @@ namespace Emby.Server.Implementations.Library
|
||||
if (providers.Length == 0)
|
||||
{
|
||||
// Assign the user to the InvalidAuthProvider since no configured auth provider was valid/found
|
||||
_logger.LogWarning("User {UserName} was found with invalid/missing Authentication Provider {AuthenticationProviderId}. Assigning user to InvalidAuthProvider until this is corrected", user.Name, user.Policy.AuthenticationProviderId);
|
||||
_logger.LogWarning("User {UserName} was found with invalid/missing Authentication Provider {AuthenticationProviderId}. Assigning user to InvalidAuthProvider until this is corrected", user?.Name, user?.Policy.AuthenticationProviderId);
|
||||
providers = new IAuthenticationProvider[] { _invalidAuthProvider };
|
||||
}
|
||||
|
||||
return providers;
|
||||
}
|
||||
|
||||
private IPasswordResetProvider[] GetPasswordResetProviders(User user)
|
||||
private IPasswordResetProvider[] GetPasswordResetProviders(User? user)
|
||||
{
|
||||
var passwordResetProviderId = user?.Policy.PasswordResetProviderId;
|
||||
|
||||
@@ -418,7 +423,11 @@ namespace Emby.Server.Implementations.Library
|
||||
return providers;
|
||||
}
|
||||
|
||||
private async Task<(string username, bool success)> AuthenticateWithProvider(IAuthenticationProvider provider, string username, string password, User resolvedUser)
|
||||
private async Task<(string username, bool success)> AuthenticateWithProvider(
|
||||
IAuthenticationProvider provider,
|
||||
string username,
|
||||
string password,
|
||||
User? resolvedUser)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -442,15 +451,15 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<(IAuthenticationProvider authenticationProvider, string username, bool success)> AuthenticateLocalUser(
|
||||
private async Task<(IAuthenticationProvider? authenticationProvider, string username, bool success)> AuthenticateLocalUser(
|
||||
string username,
|
||||
string password,
|
||||
string hashedPassword,
|
||||
User user,
|
||||
User? user,
|
||||
string remoteEndPoint)
|
||||
{
|
||||
bool success = false;
|
||||
IAuthenticationProvider authenticationProvider = null;
|
||||
IAuthenticationProvider? authenticationProvider = null;
|
||||
|
||||
foreach (var provider in GetAuthenticationProviders(user))
|
||||
{
|
||||
@@ -468,7 +477,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
if (!success
|
||||
&& _networkManager.IsInLocalNetwork(remoteEndPoint)
|
||||
&& user.Configuration.EnableLocalPassword
|
||||
&& user?.Configuration.EnableLocalPassword == true
|
||||
&& !string.IsNullOrEmpty(user.EasyPassword))
|
||||
{
|
||||
// Check easy password
|
||||
@@ -547,6 +556,8 @@ namespace Emby.Server.Implementations.Library
|
||||
_users[user.Id] = user;
|
||||
}
|
||||
|
||||
#nullable restore
|
||||
|
||||
public UserDto GetUserDto(User user, string remoteEndPoint = null)
|
||||
{
|
||||
if (user == null)
|
||||
@@ -748,13 +759,10 @@ namespace Emby.Server.Implementations.Library
|
||||
return user;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the user.
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns>Task.</returns>
|
||||
/// <exception cref="ArgumentNullException">user</exception>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="ArgumentNullException">The <c>user</c> is <c>null</c>.</exception>
|
||||
/// <exception cref="ArgumentException">The <c>user</c> doesn't exist, or is the last administrator.</exception>
|
||||
/// <exception cref="InvalidOperationException">The <c>user</c> can't be deleted; there are no other users.</exception>
|
||||
public void DeleteUser(User user)
|
||||
{
|
||||
if (user == null)
|
||||
@@ -773,7 +781,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
if (_users.Count == 1)
|
||||
{
|
||||
throw new ArgumentException(string.Format(
|
||||
throw new InvalidOperationException(string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"The user '{0}' cannot be deleted because there must be at least one user in the system.",
|
||||
user.Name));
|
||||
@@ -794,16 +802,19 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
_userRepository.DeleteUser(user);
|
||||
|
||||
try
|
||||
// Delete user config dir
|
||||
lock (_configSyncLock)
|
||||
lock (_policySyncLock)
|
||||
{
|
||||
_fileSystem.DeleteFile(configPath);
|
||||
try
|
||||
{
|
||||
Directory.Delete(user.ConfigurationDirectoryPath, true);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error deleting user config dir: {Path}", user.ConfigurationDirectoryPath);
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error deleting file {path}", configPath);
|
||||
}
|
||||
|
||||
DeleteUserPolicy(user);
|
||||
|
||||
_users.TryRemove(user.Id, out _);
|
||||
|
||||
@@ -912,10 +923,9 @@ namespace Emby.Server.Implementations.Library
|
||||
public UserPolicy GetUserPolicy(User user)
|
||||
{
|
||||
var path = GetPolicyFilePath(user);
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
return GetDefaultPolicy(user);
|
||||
return GetDefaultPolicy();
|
||||
}
|
||||
|
||||
try
|
||||
@@ -925,19 +935,15 @@ namespace Emby.Server.Implementations.Library
|
||||
return (UserPolicy)_xmlSerializer.DeserializeFromFile(typeof(UserPolicy), path);
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return GetDefaultPolicy(user);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error reading policy file: {path}", path);
|
||||
_logger.LogError(ex, "Error reading policy file: {Path}", path);
|
||||
|
||||
return GetDefaultPolicy(user);
|
||||
return GetDefaultPolicy();
|
||||
}
|
||||
}
|
||||
|
||||
private static UserPolicy GetDefaultPolicy(User user)
|
||||
private static UserPolicy GetDefaultPolicy()
|
||||
{
|
||||
return new UserPolicy
|
||||
{
|
||||
@@ -977,27 +983,6 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteUserPolicy(User user)
|
||||
{
|
||||
var path = GetPolicyFilePath(user);
|
||||
|
||||
try
|
||||
{
|
||||
lock (_policySyncLock)
|
||||
{
|
||||
_fileSystem.DeleteFile(path);
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error deleting policy file");
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetPolicyFilePath(User user)
|
||||
{
|
||||
return Path.Combine(user.ConfigurationDirectoryPath, "policy.xml");
|
||||
@@ -1024,19 +1009,14 @@ namespace Emby.Server.Implementations.Library
|
||||
return (UserConfiguration)_xmlSerializer.DeserializeFromFile(typeof(UserConfiguration), path);
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return new UserConfiguration();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error reading policy file: {path}", path);
|
||||
_logger.LogError(ex, "Error reading policy file: {Path}", path);
|
||||
|
||||
return new UserConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly object _configSyncLock = new object();
|
||||
public void UpdateConfiguration(Guid userId, UserConfiguration config)
|
||||
{
|
||||
var user = GetUserById(userId);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
@@ -340,7 +342,7 @@ namespace Emby.Server.Implementations.Library
|
||||
var query = new InternalItemsQuery(user)
|
||||
{
|
||||
IncludeItemTypes = includeItemTypes,
|
||||
OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.DateCreated, SortOrder.Descending) },
|
||||
OrderBy = new[] { (ItemSortBy.DateCreated, SortOrder.Descending) },
|
||||
IsFolder = includeItemTypes.Length == 0 ? false : (bool?)null,
|
||||
ExcludeItemTypes = excludeItemTypes,
|
||||
IsVirtualItem = false,
|
||||
|
||||
@@ -8,12 +8,12 @@ using Microsoft.Extensions.Logging;
|
||||
namespace Emby.Server.Implementations.Library.Validators
|
||||
{
|
||||
/// <summary>
|
||||
/// Class ArtistsPostScanTask
|
||||
/// Class ArtistsPostScanTask.
|
||||
/// </summary>
|
||||
public class ArtistsPostScanTask : ILibraryPostScanTask
|
||||
{
|
||||
/// <summary>
|
||||
/// The _library manager
|
||||
/// The _library manager.
|
||||
/// </summary>
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly ILogger _logger;
|
||||
@@ -23,6 +23,8 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||
/// Initializes a new instance of the <see cref="ArtistsPostScanTask" /> class.
|
||||
/// </summary>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="itemRepo">The item repository.</param>
|
||||
public ArtistsPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
|
||||
@@ -12,17 +12,17 @@ using Microsoft.Extensions.Logging;
|
||||
namespace Emby.Server.Implementations.Library.Validators
|
||||
{
|
||||
/// <summary>
|
||||
/// Class ArtistsValidator
|
||||
/// Class ArtistsValidator.
|
||||
/// </summary>
|
||||
public class ArtistsValidator
|
||||
{
|
||||
/// <summary>
|
||||
/// The _library manager
|
||||
/// The library manager.
|
||||
/// </summary>
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
/// <summary>
|
||||
/// The _logger
|
||||
/// The logger.
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
private readonly IItemRepository _itemRepo;
|
||||
|
||||
@@ -7,6 +7,9 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Emby.Server.Implementations.Library.Validators
|
||||
{
|
||||
/// <summary>
|
||||
/// Class GenresPostScanTask.
|
||||
/// </summary>
|
||||
public class GenresPostScanTask : ILibraryPostScanTask
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -7,19 +7,28 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Emby.Server.Implementations.Library.Validators
|
||||
{
|
||||
class GenresValidator
|
||||
/// <summary>
|
||||
/// Class GenresValidator.
|
||||
/// </summary>
|
||||
public class GenresValidator
|
||||
{
|
||||
/// <summary>
|
||||
/// The _library manager
|
||||
/// The library manager.
|
||||
/// </summary>
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IItemRepository _itemRepo;
|
||||
|
||||
/// <summary>
|
||||
/// The _logger
|
||||
/// The logger.
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GenresValidator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="itemRepo">The item repository.</param>
|
||||
public GenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
|
||||
@@ -8,12 +8,12 @@ using Microsoft.Extensions.Logging;
|
||||
namespace Emby.Server.Implementations.Library.Validators
|
||||
{
|
||||
/// <summary>
|
||||
/// Class MusicGenresPostScanTask
|
||||
/// Class MusicGenresPostScanTask.
|
||||
/// </summary>
|
||||
public class MusicGenresPostScanTask : ILibraryPostScanTask
|
||||
{
|
||||
/// <summary>
|
||||
/// The _library manager
|
||||
/// The library manager.
|
||||
/// </summary>
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
@@ -7,19 +7,28 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Emby.Server.Implementations.Library.Validators
|
||||
{
|
||||
class MusicGenresValidator
|
||||
/// <summary>
|
||||
/// Class MusicGenresValidator.
|
||||
/// </summary>
|
||||
public class MusicGenresValidator
|
||||
{
|
||||
/// <summary>
|
||||
/// The _library manager
|
||||
/// The library manager.
|
||||
/// </summary>
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
/// <summary>
|
||||
/// The _logger
|
||||
/// The logger.
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
private readonly IItemRepository _itemRepo;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MusicGenresValidator" /> class.
|
||||
/// </summary>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="itemRepo">The item repository.</param>
|
||||
public MusicGenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||
/// </summary>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="fileSystem">The file system.</param>
|
||||
public PeopleValidator(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
|
||||
@@ -8,12 +8,12 @@ using Microsoft.Extensions.Logging;
|
||||
namespace Emby.Server.Implementations.Library.Validators
|
||||
{
|
||||
/// <summary>
|
||||
/// Class MusicGenresPostScanTask
|
||||
/// Class MusicGenresPostScanTask.
|
||||
/// </summary>
|
||||
public class StudiosPostScanTask : ILibraryPostScanTask
|
||||
{
|
||||
/// <summary>
|
||||
/// The _library manager
|
||||
/// The _library manager.
|
||||
/// </summary>
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||
/// </summary>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="itemRepo">Th item repository.</param>
|
||||
/// <param name="itemRepo">The item repository.</param>
|
||||
public StudiosPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user