Merge branch 'master' into mediaencoding

pull/1941/head
Bond_009 5 years ago
commit 0bf8bfbb0c

@ -200,8 +200,8 @@ jobs:
persistCredentials: true
- task: CmdLine@2
displayName: "Check out web"
condition: and(succeeded(), or(contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
displayName: "Check out web (master, release or tag)"
condition: and(succeeded(), or(contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master'), contains(variables['Build.SourceBranch'], 'tag')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
inputs:
script: 'git clone --single-branch --branch $(Build.SourceBranchName) --depth=1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web'

@ -30,6 +30,7 @@ assignees: ''
- OS: [e.g. Docker, Debian, Windows]
- Browser: [e.g. Firefox, Chrome, Safari]
- Jellyfin Version: [e.g. 10.0.1]
- Installed Plugins: [e.g. none, Fanart, Anime, etc.]
- Reverse proxy: [e.g. no, nginx, apache, etc.]
**Additional context**

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Emby.Dlna.Main;
@ -195,7 +193,7 @@ namespace Emby.Dlna.Api
private ControlResponse PostAsync(Stream requestStream, IUpnpService service)
{
var id = GetPathValue(2);
var id = GetPathValue(2).ToString();
return service.ProcessControlRequest(new ControlRequest
{
@ -206,49 +204,99 @@ namespace Emby.Dlna.Api
});
}
protected string GetPathValue(int index)
// Copied from MediaBrowser.Api/BaseApiService.cs
// TODO: Remove code duplication
/// <summary>
/// Gets the path segment at the specified index.
/// </summary>
/// <param name="index">The index of the path segment.</param>
/// <returns>The path segment at the specified index.</returns>
/// <exception cref="IndexOutOfRangeException" >Path doesn't contain enough segments.</exception>
/// <exception cref="InvalidDataException" >Path doesn't start with the base url.</exception>
protected internal ReadOnlySpan<char> GetPathValue(int index)
{
var pathInfo = Parse(Request.PathInfo);
var first = pathInfo[0];
static void ThrowIndexOutOfRangeException()
=> throw new IndexOutOfRangeException("Path doesn't contain enough segments.");
string baseUrl = _configurationManager.Configuration.BaseUrl;
static void ThrowInvalidDataException()
=> throw new InvalidDataException("Path doesn't start with the base url.");
ReadOnlySpan<char> path = Request.PathInfo;
// backwards compatibility
if (baseUrl.Length == 0
&& (string.Equals(first, "mediabrowser", StringComparison.OrdinalIgnoreCase)
|| string.Equals(first, "emby", StringComparison.OrdinalIgnoreCase)))
// Remove the protocol part from the url
int pos = path.LastIndexOf("://");
if (pos != -1)
{
index++;
path = path.Slice(pos + 3);
}
else if (string.Equals(first, baseUrl.Remove(0, 1)))
{
index++;
var second = pathInfo[1];
if (string.Equals(second, "mediabrowser", StringComparison.OrdinalIgnoreCase)
|| string.Equals(second, "emby", StringComparison.OrdinalIgnoreCase))
// Remove the query string
pos = path.LastIndexOf('?');
if (pos != -1)
{
index++;
path = path.Slice(0, pos);
}
// Remove the domain
pos = path.IndexOf('/');
if (pos != -1)
{
path = path.Slice(pos);
}
return pathInfo[index];
// Remove base url
string baseUrl = _configurationManager.Configuration.BaseUrl;
int baseUrlLen = baseUrl.Length;
if (baseUrlLen != 0)
{
if (path.StartsWith(baseUrl, StringComparison.OrdinalIgnoreCase))
{
path = path.Slice(baseUrlLen);
}
else
{
// The path doesn't start with the base url,
// how did we get here?
ThrowInvalidDataException();
}
}
// Remove leading /
path = path.Slice(1);
private List<string> Parse(string pathUri)
// Backwards compatibility
const string Emby = "emby/";
if (path.StartsWith(Emby, StringComparison.OrdinalIgnoreCase))
{
var actionParts = pathUri.Split(new[] { "://" }, StringSplitOptions.None);
path = path.Slice(Emby.Length);
}
var pathInfo = actionParts[actionParts.Length - 1];
const string MediaBrowser = "mediabrowser/";
if (path.StartsWith(MediaBrowser, StringComparison.OrdinalIgnoreCase))
{
path = path.Slice(MediaBrowser.Length);
}
var optionsPos = pathInfo.LastIndexOf('?');
if (optionsPos != -1)
// Skip segments until we are at the right index
for (int i = 0; i < index; i++)
{
pathInfo = pathInfo.Substring(0, optionsPos);
pos = path.IndexOf('/');
if (pos == -1)
{
ThrowIndexOutOfRangeException();
}
path = path.Slice(pos + 1);
}
var args = pathInfo.Split('/');
// Remove the rest
pos = path.IndexOf('/');
if (pos != -1)
{
path = path.Slice(0, pos);
}
return args.Skip(1).ToList();
return path;
}
public object Get(GetIcon request)

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using Emby.Dlna.Service;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
@ -104,7 +103,7 @@ namespace Emby.Dlna.ContentDirectory
{
if (!string.IsNullOrEmpty(profile.UserId))
{
var user = _userManager.GetUserById(profile.UserId);
var user = _userManager.GetUserById(Guid.Parse(profile.UserId));
if (user != null)
{
@ -116,7 +115,7 @@ namespace Emby.Dlna.ContentDirectory
if (!string.IsNullOrEmpty(userId))
{
var user = _userManager.GetUserById(userId);
var user = _userManager.GetUserById(Guid.Parse(userId));
if (user != null)
{

@ -425,10 +425,10 @@ namespace Emby.Dlna.ContentDirectory
{
var folder = (Folder)item;
var sortOrders = new List<string>();
var sortOrders = new List<(string, SortOrder)>();
if (!folder.IsPreSorted)
{
sortOrders.Add(ItemSortBy.SortName);
sortOrders.Add((ItemSortBy.SortName, sort.SortOrder));
}
var mediaTypes = new List<string>();
@ -464,7 +464,7 @@ namespace Emby.Dlna.ContentDirectory
{
Limit = limit,
StartIndex = startIndex,
OrderBy = sortOrders.Select(i => new ValueTuple<string, SortOrder>(i, sort.SortOrder)).ToArray(),
OrderBy = sortOrders,
User = user,
Recursive = true,
IsMissing = false,
@ -872,10 +872,10 @@ namespace Emby.Dlna.ContentDirectory
query.Parent = parent;
query.SetUser(user);
query.OrderBy = new ValueTuple<string, SortOrder>[]
query.OrderBy = new[]
{
new ValueTuple<string, SortOrder> (ItemSortBy.DatePlayed, SortOrder.Descending),
new ValueTuple<string, SortOrder> (ItemSortBy.SortName, SortOrder.Ascending)
(ItemSortBy.DatePlayed, SortOrder.Descending),
(ItemSortBy.SortName, SortOrder.Ascending)
};
query.IsResumable = true;
@ -1121,7 +1121,7 @@ namespace Emby.Dlna.ContentDirectory
private QueryResult<ServerItem> GetMusicLatest(BaseItem parent, User user, InternalItemsQuery query)
{
query.OrderBy = new ValueTuple<string, SortOrder>[] { };
query.OrderBy = Array.Empty<(string, SortOrder)>();
var items = _userViewManager.GetLatestItems(new LatestItemsQuery
{
@ -1138,7 +1138,7 @@ namespace Emby.Dlna.ContentDirectory
private QueryResult<ServerItem> GetNextUp(BaseItem parent, User user, InternalItemsQuery query)
{
query.OrderBy = new ValueTuple<string, SortOrder>[] { };
query.OrderBy = Array.Empty<(string, SortOrder)>();
var result = _tvSeriesManager.GetNextUp(new NextUpQuery
{
@ -1153,7 +1153,7 @@ namespace Emby.Dlna.ContentDirectory
private QueryResult<ServerItem> GetTvLatest(BaseItem parent, User user, InternalItemsQuery query)
{
query.OrderBy = new ValueTuple<string, SortOrder>[] { };
query.OrderBy = Array.Empty<(string, SortOrder)>();
var items = _userViewManager.GetLatestItems(new LatestItemsQuery
{
@ -1170,7 +1170,7 @@ namespace Emby.Dlna.ContentDirectory
private QueryResult<ServerItem> GetMovieLatest(BaseItem parent, User user, InternalItemsQuery query)
{
query.OrderBy = new ValueTuple<string, SortOrder>[] { };
query.OrderBy = Array.Empty<(string, SortOrder)>();
var items = _userViewManager.GetLatestItems(new LatestItemsQuery
{
@ -1274,13 +1274,14 @@ namespace Emby.Dlna.ContentDirectory
private void SetSorting(InternalItemsQuery query, SortCriteria sort, bool isPreSorted)
{
var sortOrders = new List<string>();
if (!isPreSorted)
if (isPreSorted)
{
sortOrders.Add(ItemSortBy.SortName);
query.OrderBy = Array.Empty<(string, SortOrder)>();
}
else
{
query.OrderBy = new[] { (ItemSortBy.SortName, sort.SortOrder) };
}
query.OrderBy = sortOrders.Select(i => new ValueTuple<string, SortOrder>(i, sort.SortOrder)).ToArray();
}
private QueryResult<ServerItem> ApplyPaging(QueryResult<ServerItem> result, int? startIndex, int? limit)

@ -314,7 +314,7 @@ namespace Emby.Naming.Common
// This isn't a Kodi naming rule, but the expression below causes false positives,
// so we make sure this one gets tested first.
// "Foo Bar 889"
new EpisodeExpression(@".*[\\\/](?![Ee]pisode)(?<seriesname>(\w+\s*?)*)\s(?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*[^\\\/]*$")
new EpisodeExpression(@".*[\\\/](?![Ee]pisode)(?<seriesname>[\w\s]+?)\s(?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*[^\\\/]*$")
{
IsNamed = true
},
@ -337,7 +337,7 @@ namespace Emby.Naming.Common
// *** End Kodi Standard Naming
                // [bar] Foo - 1 [baz]
new EpisodeExpression(@".*?(\[.*?\])+.*?(?<seriesname>(\w+\s*?)+?)[-\s_]+(?<epnumber>\d+).*$")
new EpisodeExpression(@".*?(\[.*?\])+.*?(?<seriesname>[\w\s]+?)[-\s_]+(?<epnumber>\d+).*$")
{
IsNamed = true
},

@ -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)

@ -110,7 +110,7 @@ using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ServiceStack;
using Microsoft.OpenApi.Models;
using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
namespace Emby.Server.Implementations
@ -230,7 +230,25 @@ namespace Emby.Server.Implementations
}
}
protected IServiceProvider _serviceProvider;
/// <summary>
/// Gets or sets the service provider.
/// </summary>
public IServiceProvider ServiceProvider { get; set; }
/// <summary>
/// Gets the http port for the webhost.
/// </summary>
public int HttpPort { get; private set; }
/// <summary>
/// Gets the https port for the webhost.
/// </summary>
public int HttpsPort { get; private set; }
/// <summary>
/// Gets the content root for the webhost.
/// </summary>
public string ContentRoot { get; private set; }
/// <summary>
/// Gets the server configuration manager.
@ -459,7 +477,7 @@ namespace Emby.Server.Implementations
/// <param name="type">The type.</param>
/// <returns>System.Object.</returns>
public object CreateInstance(Type type)
=> ActivatorUtilities.CreateInstance(_serviceProvider, type);
=> ActivatorUtilities.CreateInstance(ServiceProvider, type);
/// <summary>
/// Creates an instance of type and resolves all constructor dependencies.
@ -467,7 +485,7 @@ namespace Emby.Server.Implementations
/// /// <typeparam name="T">The type.</typeparam>
/// <returns>T.</returns>
public T CreateInstance<T>()
=> ActivatorUtilities.CreateInstance<T>(_serviceProvider);
=> ActivatorUtilities.CreateInstance<T>(ServiceProvider);
/// <summary>
/// Creates the instance safe.
@ -479,7 +497,7 @@ namespace Emby.Server.Implementations
try
{
Logger.LogDebug("Creating instance of {Type}", type);
return ActivatorUtilities.CreateInstance(_serviceProvider, type);
return ActivatorUtilities.CreateInstance(ServiceProvider, type);
}
catch (Exception ex)
{
@ -493,7 +511,7 @@ namespace Emby.Server.Implementations
/// </summary>
/// <typeparam name="T">The type</typeparam>
/// <returns>``0.</returns>
public T Resolve<T>() => _serviceProvider.GetService<T>();
public T Resolve<T>() => ServiceProvider.GetService<T>();
/// <summary>
/// Gets the export types.
@ -610,77 +628,14 @@ namespace Emby.Server.Implementations
await RegisterResources(serviceCollection).ConfigureAwait(false);
FindParts();
string contentRoot = ServerConfigurationManager.Configuration.DashboardSourcePath;
if (string.IsNullOrEmpty(contentRoot))
{
contentRoot = ServerConfigurationManager.ApplicationPaths.WebPath;
}
var host = new WebHostBuilder()
.UseKestrel(options =>
{
var addresses = ServerConfigurationManager
.Configuration
.LocalNetworkAddresses
.Select(NormalizeConfiguredLocalAddress)
.Where(i => i != null)
.ToList();
if (addresses.Any())
{
foreach (var address in addresses)
{
Logger.LogInformation("Kestrel listening on {ipaddr}", address);
options.Listen(address, HttpPort);
if (EnableHttps && Certificate != null)
{
options.Listen(address, HttpsPort, listenOptions => listenOptions.UseHttps(Certificate));
}
}
}
else
{
Logger.LogInformation("Kestrel listening on all interfaces");
options.ListenAnyIP(HttpPort);
if (EnableHttps && Certificate != null)
{
options.ListenAnyIP(HttpsPort, listenOptions => listenOptions.UseHttps(Certificate));
}
}
})
.UseContentRoot(contentRoot)
.ConfigureServices(services =>
{
services.AddResponseCompression();
services.AddHttpContextAccessor();
})
.Configure(app =>
{
app.UseWebSockets();
app.UseResponseCompression();
// TODO app.UseMiddleware<WebSocketMiddleware>();
app.Use(ExecuteWebsocketHandlerAsync);
app.Use(ExecuteHttpHandlerAsync);
})
.Build();
try
ContentRoot = ServerConfigurationManager.Configuration.DashboardSourcePath;
if (string.IsNullOrEmpty(ContentRoot))
{
await host.StartAsync().ConfigureAwait(false);
}
catch
{
Logger.LogError("Kestrel failed to start! This is most likely due to an invalid address or port bind - correct your bind configuration in system.xml and try again.");
throw;
ContentRoot = ServerConfigurationManager.ApplicationPaths.WebPath;
}
}
private async Task ExecuteWebsocketHandlerAsync(HttpContext context, Func<Task> next)
public async Task ExecuteWebsocketHandlerAsync(HttpContext context, Func<Task> next)
{
if (!context.WebSockets.IsWebSocketRequest)
{
@ -691,7 +646,7 @@ namespace Emby.Server.Implementations
await HttpServer.ProcessWebSocketRequest(context).ConfigureAwait(false);
}
private async Task ExecuteHttpHandlerAsync(HttpContext context, Func<Task> next)
public async Task ExecuteHttpHandlerAsync(HttpContext context, Func<Task> next)
{
if (context.WebSockets.IsWebSocketRequest)
{
@ -907,7 +862,7 @@ namespace Emby.Server.Implementations
serviceCollection.AddSingleton<IAuthorizationContext>(authContext);
serviceCollection.AddSingleton<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager));
AuthService = new AuthService(authContext, ServerConfigurationManager, SessionManager, NetworkManager);
AuthService = new AuthService(LoggerFactory.CreateLogger<AuthService>(), authContext, ServerConfigurationManager, SessionManager, NetworkManager);
serviceCollection.AddSingleton(AuthService);
SubtitleEncoder = new MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder(
@ -935,8 +890,6 @@ namespace Emby.Server.Implementations
((UserDataManager)UserDataManager).Repository = userDataRepo;
ItemRepository.Initialize(userDataRepo, UserManager);
((LibraryManager)LibraryManager).ItemRepository = ItemRepository;
_serviceProvider = serviceCollection.BuildServiceProvider();
}
public static void LogEnvironmentInfo(ILogger logger, IApplicationPaths appPaths)
@ -1093,9 +1046,9 @@ namespace Emby.Server.Implementations
/// <summary>
/// Finds the parts.
/// </summary>
protected void FindParts()
public void FindParts()
{
InstallationManager = _serviceProvider.GetService<IInstallationManager>();
InstallationManager = ServiceProvider.GetService<IInstallationManager>();
InstallationManager.PluginInstalled += PluginInstalled;
if (!ServerConfigurationManager.Configuration.IsPortAuthorized)
@ -1224,7 +1177,7 @@ namespace Emby.Server.Implementations
private CertificateInfo CertificateInfo { get; set; }
protected X509Certificate2 Certificate { get; private set; }
public X509Certificate2 Certificate { get; private set; }
private IEnumerable<string> GetUrlPrefixes()
{
@ -1609,7 +1562,7 @@ namespace Emby.Server.Implementations
return resultList;
}
private IPAddress NormalizeConfiguredLocalAddress(string address)
public IPAddress NormalizeConfiguredLocalAddress(string address)
{
var index = address.Trim('/').IndexOf('/');
@ -1685,10 +1638,6 @@ namespace Emby.Server.Implementations
? Environment.MachineName
: ServerConfigurationManager.Configuration.ServerName;
public int HttpPort { get; private set; }
public int HttpsPort { get; private set; }
/// <summary>
/// Shuts down.
/// </summary>

@ -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;

@ -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;

@ -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;
@ -2881,14 +2882,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;
@ -2903,9 +2904,8 @@ namespace Emby.Server.Implementations.Data
};
}
var orderBy = query.OrderBy;
if (orderBy.Length == 0)
if (orderBy.Count == 0)
{
return string.Empty;
}
@ -2913,14 +2913,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;
}));

@ -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;

@ -1,8 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\Emby.Naming\Emby.Naming.csproj" />
<ProjectReference Include="..\Emby.Notifications\Emby.Notifications.csproj" />
<ProjectReference Include="..\Jellyfin.Api\Jellyfin.Api.csproj" />
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" />
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
@ -35,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>

@ -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,42 +11,51 @@ 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;
/// <summary>
/// Initializes a new instance of the <see cref="RefreshUsersMetadata" /> class.
/// </summary>
public RefreshUsersMetadata(ILogger logger, IUserManager userManager, IFileSystem fileSystem)
{
_logger = logger;
_userManager = userManager;
_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;
/// <summary>
/// Initializes a new instance of the <see cref="RefreshUsersMetadata" /> class.
/// </summary>
public RefreshUsersMetadata(ILogger logger, IUserManager userManager, IFileSystem fileSystem)
{
_logger = logger;
_userManager = userManager;
_fileSystem = fileSystem;
}
/// <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 -= OnPluginUninstalled;
_installationManager.PackageInstalling -= OnPackageInstalling;
_installationManager.PackageInstallationCancelled -= OnPackageInstallationCancelled;
_installationManager.PackageInstallationCompleted -= OnPackageInstallationCompleted;
_installationManager.PackageInstallationFailed -= OnPackageInstallationFailed;
_installationManager.PluginUninstalled -= InstallationManager_PluginUninstalled;
_installationManager.PackageInstalling -= _installationManager_PackageInstalling;
_installationManager.PackageInstallationCancelled -= _installationManager_PackageInstallationCancelled;
_installationManager.PackageInstallationCompleted -= _installationManager_PackageInstallationCompleted;
_installationManager.PackageInstallationFailed -= _installationManager_PackageInstallationFailed;
_appHost.HasPendingRestartChanged -= OnHasPendingRestartChanged;
_appHost.HasPendingRestartChanged -= kernel_HasPendingRestartChanged;
_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;
@ -18,7 +20,6 @@ using MediaBrowser.Model.Events;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Internal;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
@ -164,7 +165,7 @@ namespace Emby.Server.Implementations.HttpServer
{
OnReceive = ProcessWebSocketMessageReceived,
Url = e.Url,
QueryString = e.QueryString ?? new QueryCollection()
QueryString = e.QueryString
};
connection.Closed += OnConnectionClosed;

@ -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,5 +1,8 @@
#pragma warning disable CS1591
using System;
using System.Linq;
using Emby.Server.Implementations.SocketSharp;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@ -7,22 +10,27 @@ using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.HttpServer.Security
{
public class AuthService : IAuthService
{
private readonly ILogger<AuthService> _logger;
private readonly IAuthorizationContext _authorizationContext;
private readonly ISessionManager _sessionManager;
private readonly IServerConfigurationManager _config;
private readonly INetworkManager _networkManager;
public AuthService(
ILogger<AuthService> logger,
IAuthorizationContext authorizationContext,
IServerConfigurationManager config,
ISessionManager sessionManager,
INetworkManager networkManager)
{
_logger = logger;
_authorizationContext = authorizationContext;
_config = config;
_sessionManager = sessionManager;
@ -34,7 +42,14 @@ namespace Emby.Server.Implementations.HttpServer.Security
ValidateUser(request, authAttribtues);
}
private void ValidateUser(IRequest request, IAuthenticationAttributes authAttribtues)
public User Authenticate(HttpRequest request, IAuthenticationAttributes authAttributes)
{
var req = new WebSocketSharpRequest(request, null, request.Path, _logger);
var user = ValidateUser(req, authAttributes);
return user;
}
private User ValidateUser(IRequest request, IAuthenticationAttributes authAttribtues)
{
// This code is executed before the service
var auth = _authorizationContext.GetAuthorizationInfo(request);
@ -81,6 +96,8 @@ namespace Emby.Server.Implementations.HttpServer.Security
request.RemoteIp,
user);
}
return user;
}
private void ValidateUserAccess(

@ -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,60 +14,24 @@ 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>
/// Gets or sets the receive action.
/// </summary>
/// <value>The receive action.</value>
public Func<WebSocketMessageInfo, Task> OnReceive { get; set; }
/// <summary>
/// Gets the last activity date.
/// </summary>
/// <value>The last activity date.</value>
public DateTime LastActivityDate { get; private set; }
/// <summary>
/// Gets the id.
/// The socket.
/// </summary>
/// <value>The id.</value>
public Guid Id { get; private set; }
/// <summary>
/// Gets or sets the URL.
/// </summary>
/// <value>The URL.</value>
public string Url { get; set; }
/// <summary>
/// Gets or sets the query string.
/// </summary>
/// <value>The query string.</value>
public IQueryCollection QueryString { get; set; }
private readonly IWebSocket _socket;
/// <summary>
/// Initializes a new instance of the <see cref="WebSocketConnection" /> class.
@ -84,14 +47,17 @@ namespace Emby.Server.Implementations.HttpServer
{
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));
@ -105,10 +71,54 @@ namespace Emby.Server.Implementations.HttpServer
RemoteEndPoint = remoteEndPoint;
_logger = logger;
socket.Closed += socket_Closed;
socket.Closed += OnSocketClosed;
}
void socket_Closed(object sender, EventArgs e)
/// <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>
/// <value>The receive action.</value>
public Func<WebSocketMessageInfo, Task> OnReceive { get; set; }
/// <summary>
/// Gets the last activity date.
/// </summary>
/// <value>The last activity date.</value>
public DateTime LastActivityDate { get; private set; }
/// <summary>
/// Gets the id.
/// </summary>
/// <value>The id.</value>
public Guid Id { get; private set; }
/// <summary>
/// Gets or sets the URL.
/// </summary>
/// <value>The URL.</value>
public string Url { get; set; }
/// <summary>
/// Gets or sets the query string.
/// </summary>
/// <value>The query string.</value>
public IQueryCollection QueryString { get; set; }
/// <summary>
/// Gets the state.
/// </summary>
/// <value>The state.</value>
public WebSocketState State => _socket.State;
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;

@ -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;
@ -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;

@ -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,15 +56,24 @@ 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;
}
return IsMusicAlbum(args) ? new MusicAlbum() : 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
@ -79,7 +94,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
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 (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>
{

@ -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,
@ -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());

@ -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
{
/// <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))
@ -358,6 +356,8 @@ namespace Emby.Server.Implementations.Library
return success ? user : null;
}
#nullable enable
private static string GetAuthenticationProviderId(IAuthenticationProvider provider)
{
return provider.GetType().FullName;
@ -378,7 +378,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;
@ -399,7 +399,7 @@ namespace Emby.Server.Implementations.Library
return providers;
}
private IPasswordResetProvider[] GetPasswordResetProviders(User user)
private IPasswordResetProvider[] GetPasswordResetProviders(User? user)
{
var passwordResetProviderId = user?.Policy.PasswordResetProviderId;
@ -418,7 +418,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 +446,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))
{
@ -547,6 +551,8 @@ namespace Emby.Server.Implementations.Library
_users[user.Id] = user;
}
#nullable restore
public UserDto GetUserDto(User user, string remoteEndPoint = null)
{
if (user == null)

@ -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>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save