Merge branch 'namingtests' of https://github.com/Bond-009/jellyfin into namingtests

This commit is contained in:
Bond-009 2019-12-18 11:53:41 +01:00
commit a1ca50fd5a
228 changed files with 2276 additions and 4480 deletions

View File

@ -30,6 +30,7 @@
- [Khinenw](https://github.com/HelloWorld017) - [Khinenw](https://github.com/HelloWorld017)
- [fhriley](https://github.com/fhriley) - [fhriley](https://github.com/fhriley)
- [nevado](https://github.com/nevado) - [nevado](https://github.com/nevado)
- [mark-monteiro](https://github.com/mark-monteiro)
# Emby Contributors # Emby Contributors

View File

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

View File

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

View File

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

View File

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

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
@ -39,6 +41,19 @@ namespace Emby.Server.Implementations.Activity
private readonly IServerApplicationHost _appHost; private readonly IServerApplicationHost _appHost;
private readonly IDeviceManager _deviceManager; 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( public ActivityLogEntryPoint(
ILogger<ActivityLogEntryPoint> logger, ILogger<ActivityLogEntryPoint> logger,
ISessionManager sessionManager, ISessionManager sessionManager,

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Linq; using System.Linq;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;

View File

@ -133,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) public virtual void AddParts(IEnumerable<IConfigurationFactory> factories)
{ {
_configurationFactories = factories.ToArray(); _configurationFactories = factories.ToArray();
@ -247,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) protected void EnsureWriteAccess(string path)
{ {
var file = Path.Combine(path, Guid.NewGuid().ToString()); var file = Path.Combine(path, Guid.NewGuid().ToString());
@ -259,6 +267,7 @@ namespace Emby.Server.Implementations.AppBase
return Path.Combine(CommonApplicationPaths.ConfigurationDirectoryPath, key.ToLowerInvariant() + ".xml"); return Path.Combine(CommonApplicationPaths.ConfigurationDirectoryPath, key.ToLowerInvariant() + ".xml");
} }
/// <inheritdoc />
public object GetConfiguration(string key) public object GetConfiguration(string key)
{ {
return _configurations.GetOrAdd(key, k => return _configurations.GetOrAdd(key, k =>
@ -305,6 +314,7 @@ namespace Emby.Server.Implementations.AppBase
} }
} }
/// <inheritdoc />
public void SaveConfiguration(string key, object configuration) public void SaveConfiguration(string key, object configuration)
{ {
var configurationStore = GetConfigurationStore(key); var configurationStore = GetConfigurationStore(key);
@ -341,6 +351,11 @@ namespace Emby.Server.Implementations.AppBase
OnNamedConfigurationUpdated(key, configuration); 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) protected virtual void OnNamedConfigurationUpdated(string key, object configuration)
{ {
NamedConfigurationUpdated?.Invoke(this, new ConfigurationUpdateEventArgs NamedConfigurationUpdated?.Invoke(this, new ConfigurationUpdateEventArgs
@ -350,6 +365,7 @@ namespace Emby.Server.Implementations.AppBase
}); });
} }
/// <inheritdoc />
public Type GetConfigurationType(string key) public Type GetConfigurationType(string key)
{ {
return GetConfigurationStore(key) return GetConfigurationStore(key)

View File

@ -10,15 +10,10 @@ using SharpCompress.Readers.Zip;
namespace Emby.Server.Implementations.Archiving namespace Emby.Server.Implementations.Archiving
{ {
/// <summary> /// <summary>
/// Class DotNetZipClient /// Class DotNetZipClient.
/// </summary> /// </summary>
public class ZipClient : IZipClient public class ZipClient : IZipClient
{ {
public ZipClient()
{
}
/// <summary> /// <summary>
/// Extracts all. /// Extracts all.
/// </summary> /// </summary>
@ -144,7 +139,6 @@ namespace Emby.Server.Implementations.Archiving
} }
} }
/// <summary> /// <summary>
/// Extracts all from tar. /// Extracts all from tar.
/// </summary> /// </summary>

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System.Collections.Generic; using System.Collections.Generic;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.Branding; using MediaBrowser.Model.Branding;

View File

@ -4,7 +4,7 @@ using MediaBrowser.Controller;
namespace Emby.Server.Implementations.Browser namespace Emby.Server.Implementations.Browser
{ {
/// <summary> /// <summary>
/// Class BrowserLauncher /// Class BrowserLauncher.
/// </summary> /// </summary>
public static class BrowserLauncher public static class BrowserLauncher
{ {
@ -32,6 +32,7 @@ namespace Emby.Server.Implementations.Browser
/// <summary> /// <summary>
/// Opens the URL. /// Opens the URL.
/// </summary> /// </summary>
/// <param name="appHost">The application host instance.</param>
/// <param name="url">The URL.</param> /// <param name="url">The URL.</param>
private static void OpenUrl(IServerApplicationHost appHost, string url) private static void OpenUrl(IServerApplicationHost appHost, string url)
{ {

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
@ -13,11 +15,16 @@ namespace Emby.Server.Implementations.Channels
{ {
private readonly ChannelManager _channelManager; 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) public ChannelDynamicMediaSourceProvider(IChannelManager channelManager)
{ {
_channelManager = (ChannelManager)channelManager; _channelManager = (ChannelManager)channelManager;
} }
/// <inheritdoc />
public Task<IEnumerable<MediaSourceInfo>> GetMediaSources(BaseItem item, CancellationToken cancellationToken) public Task<IEnumerable<MediaSourceInfo>> GetMediaSources(BaseItem item, CancellationToken cancellationToken)
{ {
if (item.SourceType == SourceType.Channel) if (item.SourceType == SourceType.Channel)
@ -28,6 +35,7 @@ namespace Emby.Server.Implementations.Channels
return Task.FromResult<IEnumerable<MediaSourceInfo>>(new List<MediaSourceInfo>()); return Task.FromResult<IEnumerable<MediaSourceInfo>>(new List<MediaSourceInfo>());
} }
/// <inheritdoc />
public Task<ILiveStream> OpenMediaSource(string openToken, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken) public Task<ILiveStream> OpenMediaSource(string openToken, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken)
{ {
throw new NotImplementedException(); throw new NotImplementedException();

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
@ -510,7 +512,7 @@ namespace Emby.Server.Implementations.Channels
return _libraryManager.GetItemIds(new InternalItemsQuery return _libraryManager.GetItemIds(new InternalItemsQuery
{ {
IncludeItemTypes = new[] { typeof(Channel).Name }, 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(); }).Select(i => GetChannelFeatures(i.ToString("N", CultureInfo.InvariantCulture))).ToArray();
} }
@ -618,16 +620,16 @@ namespace Emby.Server.Implementations.Channels
{ {
query.OrderBy = new[] query.OrderBy = new[]
{ {
new ValueTuple<string, SortOrder>(ItemSortBy.PremiereDate, SortOrder.Descending), (ItemSortBy.PremiereDate, SortOrder.Descending),
new ValueTuple<string, SortOrder>(ItemSortBy.ProductionYear, SortOrder.Descending), (ItemSortBy.ProductionYear, SortOrder.Descending),
new ValueTuple<string, SortOrder>(ItemSortBy.DateCreated, SortOrder.Descending) (ItemSortBy.DateCreated, SortOrder.Descending)
}; };
} }
else else
{ {
query.OrderBy = new[] query.OrderBy = new[]
{ {
new ValueTuple<string, SortOrder>(ItemSortBy.DateCreated, SortOrder.Descending) (ItemSortBy.DateCreated, SortOrder.Descending)
}; };
} }

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -76,7 +78,6 @@ namespace Emby.Server.Implementations.Collections
.Where(i => i != null) .Where(i => i != null)
.GroupBy(x => x.Id) .GroupBy(x => x.Id)
.Select(x => x.First()) .Select(x => x.First())
.OrderBy(i => Guid.NewGuid())
.ToList(); .ToList();
} }

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;

View File

@ -1,4 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO; using System.IO;
using Emby.Server.Implementations.AppBase; using Emby.Server.Implementations.AppBase;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
@ -17,7 +19,6 @@ namespace Emby.Server.Implementations.Configuration
/// </summary> /// </summary>
public class ServerConfigurationManager : BaseConfigurationManager, IServerConfigurationManager public class ServerConfigurationManager : BaseConfigurationManager, IServerConfigurationManager
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ServerConfigurationManager" /> class. /// Initializes a new instance of the <see cref="ServerConfigurationManager" /> class.
/// </summary> /// </summary>
@ -31,6 +32,9 @@ namespace Emby.Server.Implementations.Configuration
UpdateMetadataPath(); UpdateMetadataPath();
} }
/// <summary>
/// Configuration updating event.
/// </summary>
public event EventHandler<GenericEventArgs<ServerConfiguration>> ConfigurationUpdating; public event EventHandler<GenericEventArgs<ServerConfiguration>> ConfigurationUpdating;
/// <summary> /// <summary>
@ -97,7 +101,7 @@ namespace Emby.Server.Implementations.Configuration
/// Validates the SSL certificate. /// Validates the SSL certificate.
/// </summary> /// </summary>
/// <param name="newConfig">The new configuration.</param> /// <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) private void ValidateSslCertificate(BaseApplicationConfiguration newConfig)
{ {
var serverConfig = (ServerConfiguration)newConfig; var serverConfig = (ServerConfiguration)newConfig;
@ -105,12 +109,16 @@ namespace Emby.Server.Implementations.Configuration
var newPath = serverConfig.CertificatePath; var newPath = serverConfig.CertificatePath;
if (!string.IsNullOrWhiteSpace(newPath) if (!string.IsNullOrWhiteSpace(newPath)
&& !string.Equals(Configuration.CertificatePath ?? string.Empty, newPath)) && !string.Equals(Configuration.CertificatePath, newPath, StringComparison.Ordinal))
{ {
// Validate // Validate
if (!File.Exists(newPath)) 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. /// Validates the metadata path.
/// </summary> /// </summary>
/// <param name="newConfig">The new configuration.</param> /// <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) private void ValidateMetadataPath(ServerConfiguration newConfig)
{ {
var newPath = newConfig.MetadataPath; var newPath = newConfig.MetadataPath;
if (!string.IsNullOrWhiteSpace(newPath) if (!string.IsNullOrWhiteSpace(newPath)
&& !string.Equals(Configuration.MetadataPath ?? string.Empty, newPath)) && !string.Equals(Configuration.MetadataPath, newPath, StringComparison.Ordinal))
{ {
// Validate // Validate
if (!Directory.Exists(newPath)) 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); EnsureWriteAccess(newPath);
} }
} }
/// <summary>
/// Sets all configuration values to their optimal values.
/// </summary>
/// <returns>If the configuration changed.</returns>
public bool SetOptimalValues() public bool SetOptimalValues()
{ {
var config = Configuration; var config = Configuration;

View File

@ -6,6 +6,9 @@ using static MediaBrowser.Common.Cryptography.Constants;
namespace Emby.Server.Implementations.Cryptography namespace Emby.Server.Implementations.Cryptography
{ {
/// <summary>
/// Class providing abstractions over cryptographic functions.
/// </summary>
public class CryptographyProvider : ICryptoProvider, IDisposable public class CryptographyProvider : ICryptoProvider, IDisposable
{ {
private static readonly HashSet<string> _supportedHashMethods = new HashSet<string>() private static readonly HashSet<string> _supportedHashMethods = new HashSet<string>()
@ -42,8 +45,10 @@ namespace Emby.Server.Implementations.Cryptography
_randomNumberGenerator = RandomNumberGenerator.Create(); _randomNumberGenerator = RandomNumberGenerator.Create();
} }
/// <inheritdoc />
public string DefaultHashMethod => "PBKDF2"; public string DefaultHashMethod => "PBKDF2";
/// <inheritdoc />
public IEnumerable<string> GetSupportedHashMethods() public IEnumerable<string> GetSupportedHashMethods()
=> _supportedHashMethods; => _supportedHashMethods;
@ -62,6 +67,7 @@ namespace Emby.Server.Implementations.Cryptography
throw new CryptographicException($"Cannot currently use PBKDF2 with requested hash method: {method}"); throw new CryptographicException($"Cannot currently use PBKDF2 with requested hash method: {method}");
} }
/// <inheritdoc />
public byte[] ComputeHash(string hashMethod, byte[] bytes, byte[] salt) public byte[] ComputeHash(string hashMethod, byte[] bytes, byte[] salt)
{ {
if (hashMethod == DefaultHashMethod) if (hashMethod == DefaultHashMethod)
@ -89,12 +95,15 @@ namespace Emby.Server.Implementations.Cryptography
throw new CryptographicException($"Requested hash method is not supported: {hashMethod}"); throw new CryptographicException($"Requested hash method is not supported: {hashMethod}");
} }
/// <inheritdoc />
public byte[] ComputeHashWithDefaultMethod(byte[] bytes, byte[] salt) public byte[] ComputeHashWithDefaultMethod(byte[] bytes, byte[] salt)
=> PBKDF2(DefaultHashMethod, bytes, salt, DefaultIterations); => PBKDF2(DefaultHashMethod, bytes, salt, DefaultIterations);
/// <inheritdoc />
public byte[] GenerateSalt() public byte[] GenerateSalt()
=> GenerateSalt(DefaultSaltLength); => GenerateSalt(DefaultSaltLength);
/// <inheritdoc />
public byte[] GenerateSalt(int length) public byte[] GenerateSalt(int length)
{ {
byte[] salt = new byte[length]; byte[] salt = new byte[length];
@ -109,6 +118,10 @@ namespace Emby.Server.Implementations.Cryptography
GC.SuppressFinalize(this); 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) protected virtual void Dispose(bool disposing)
{ {
if (_disposed) if (_disposed)

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -11,6 +13,10 @@ namespace Emby.Server.Implementations.Data
{ {
private bool _disposed = false; 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) protected BaseSqliteRepository(ILogger logger)
{ {
Logger = logger; Logger = logger;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;

View File

@ -7,6 +7,7 @@ using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Threading; using System.Threading;
using Emby.Server.Implementations.Playlists; using Emby.Server.Implementations.Playlists;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Json; using MediaBrowser.Common.Json;
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Channels;
@ -2881,14 +2882,14 @@ namespace Emby.Server.Implementations.Data
private string GetOrderByText(InternalItemsQuery query) private string GetOrderByText(InternalItemsQuery query)
{ {
var orderBy = query.OrderBy;
if (string.IsNullOrEmpty(query.SearchTerm)) if (string.IsNullOrEmpty(query.SearchTerm))
{ {
int oldLen = query.OrderBy.Length; int oldLen = orderBy.Count;
if (oldLen == 0 && query.SimilarTo != null)
if (query.SimilarTo != null && oldLen == 0)
{ {
var arr = new (string, SortOrder)[oldLen + 2]; var arr = new (string, SortOrder)[oldLen + 2];
query.OrderBy.CopyTo(arr, 0); orderBy.CopyTo(arr, 0);
arr[oldLen] = ("SimilarityScore", SortOrder.Descending); arr[oldLen] = ("SimilarityScore", SortOrder.Descending);
arr[oldLen + 1] = (ItemSortBy.Random, SortOrder.Ascending); arr[oldLen + 1] = (ItemSortBy.Random, SortOrder.Ascending);
query.OrderBy = arr; 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; return string.Empty;
} }
@ -2913,14 +2913,8 @@ namespace Emby.Server.Implementations.Data
return " ORDER BY " + string.Join(",", orderBy.Select(i => return " ORDER BY " + string.Join(",", orderBy.Select(i =>
{ {
var columnMap = MapOrderByField(i.Item1, query); 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; return columnMap.Item1 + " " + sortOrder;
})); }));

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;

View File

@ -5,25 +5,22 @@ using System.Linq;
namespace Emby.Server.Implementations.Data namespace Emby.Server.Implementations.Data
{ {
/// <summary> /// <summary>
/// Class TypeMapper /// Class TypeMapper.
/// </summary> /// </summary>
public class TypeMapper public class TypeMapper
{ {
/// <summary> /// <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> /// </summary>
private readonly ConcurrentDictionary<string, Type> _typeMap = new ConcurrentDictionary<string, Type>(); private readonly ConcurrentDictionary<string, Type> _typeMap = new ConcurrentDictionary<string, Type>();
public TypeMapper()
{
}
/// <summary> /// <summary>
/// Gets the type. /// Gets the type.
/// </summary> /// </summary>
/// <param name="typeName">Name of the type.</param> /// <param name="typeName">Name of the type.</param>
/// <returns>Type.</returns> /// <returns>Type.</returns>
/// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentNullException"><c>typeName</c> is null.</exception>
public Type GetType(string typeName) public Type GetType(string typeName)
{ {
if (string.IsNullOrEmpty(typeName)) if (string.IsNullOrEmpty(typeName))

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Diagnostics;
namespace Emby.Server.Implementations.Diagnostics namespace Emby.Server.Implementations.Diagnostics

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;

View File

@ -15,12 +15,12 @@
<ProjectReference Include="..\MediaBrowser.LocalMetadata\MediaBrowser.LocalMetadata.csproj" /> <ProjectReference Include="..\MediaBrowser.LocalMetadata\MediaBrowser.LocalMetadata.csproj" />
<ProjectReference Include="..\Emby.Photos\Emby.Photos.csproj" /> <ProjectReference Include="..\Emby.Photos\Emby.Photos.csproj" />
<ProjectReference Include="..\Emby.Drawing\Emby.Drawing.csproj" /> <ProjectReference Include="..\Emby.Drawing\Emby.Drawing.csproj" />
<ProjectReference Include="..\Emby.XmlTv\Emby.XmlTv\Emby.XmlTv.csproj" />
<ProjectReference Include="..\MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj" /> <ProjectReference Include="..\MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="IPNetwork2" Version="2.4.0.126" /> <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" Version="2.2.7" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" Version="2.2.0" />

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
@ -12,32 +11,19 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints namespace Emby.Server.Implementations.EntryPoints
{ {
/// <summary> /// <summary>
/// Class RefreshUsersMetadata /// Class RefreshUsersMetadata.
/// </summary> /// </summary>
public class RefreshUsersMetadata : IScheduledTask, IConfigurableScheduledTask public class RefreshUsersMetadata : IScheduledTask, IConfigurableScheduledTask
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
/// <summary> /// <summary>
/// The _user manager /// The user manager.
/// </summary> /// </summary>
private readonly IUserManager _userManager; private readonly IUserManager _userManager;
private IFileSystem _fileSystem; 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> /// <summary>
/// Initializes a new instance of the <see cref="RefreshUsersMetadata" /> class. /// Initializes a new instance of the <see cref="RefreshUsersMetadata" /> class.
/// </summary> /// </summary>
@ -48,6 +34,28 @@ namespace Emby.Server.Implementations.EntryPoints
_fileSystem = fileSystem; _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) public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
{ {
foreach (var user in _userManager.Users) foreach (var user in _userManager.Users)
@ -58,9 +66,10 @@ namespace Emby.Server.Implementations.EntryPoints
} }
} }
/// <inheritdoc />
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers() public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
{ {
return new List<TaskTriggerInfo> return new[]
{ {
new TaskTriggerInfo new TaskTriggerInfo
{ {

View File

@ -16,33 +16,46 @@ using MediaBrowser.Model.Tasks;
namespace Emby.Server.Implementations.EntryPoints namespace Emby.Server.Implementations.EntryPoints
{ {
/// <summary> /// <summary>
/// Class WebSocketEvents /// Class WebSocketEvents.
/// </summary> /// </summary>
public class ServerEventNotifier : IServerEntryPoint public class ServerEventNotifier : IServerEntryPoint
{ {
/// <summary> /// <summary>
/// The _user manager /// The user manager.
/// </summary> /// </summary>
private readonly IUserManager _userManager; private readonly IUserManager _userManager;
/// <summary> /// <summary>
/// The _installation manager /// The installation manager.
/// </summary> /// </summary>
private readonly IInstallationManager _installationManager; private readonly IInstallationManager _installationManager;
/// <summary> /// <summary>
/// The _kernel /// The kernel.
/// </summary> /// </summary>
private readonly IServerApplicationHost _appHost; private readonly IServerApplicationHost _appHost;
/// <summary> /// <summary>
/// The _task manager /// The task manager.
/// </summary> /// </summary>
private readonly ITaskManager _taskManager; private readonly ITaskManager _taskManager;
private readonly ISessionManager _sessionManager; 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; _userManager = userManager;
_installationManager = installationManager; _installationManager = installationManager;
@ -51,47 +64,48 @@ namespace Emby.Server.Implementations.EntryPoints
_sessionManager = sessionManager; _sessionManager = sessionManager;
} }
/// <inheritdoc />
public Task RunAsync() public Task RunAsync()
{ {
_userManager.UserDeleted += userManager_UserDeleted; _userManager.UserDeleted += OnUserDeleted;
_userManager.UserUpdated += userManager_UserUpdated; _userManager.UserUpdated += OnUserUpdated;
_userManager.UserPolicyUpdated += _userManager_UserPolicyUpdated; _userManager.UserPolicyUpdated += OnUserPolicyUpdated;
_userManager.UserConfigurationUpdated += _userManager_UserConfigurationUpdated; _userManager.UserConfigurationUpdated += OnUserConfigurationUpdated;
_appHost.HasPendingRestartChanged += kernel_HasPendingRestartChanged; _appHost.HasPendingRestartChanged += OnHasPendingRestartChanged;
_installationManager.PluginUninstalled += InstallationManager_PluginUninstalled; _installationManager.PluginUninstalled += OnPluginUninstalled;
_installationManager.PackageInstalling += _installationManager_PackageInstalling; _installationManager.PackageInstalling += OnPackageInstalling;
_installationManager.PackageInstallationCancelled += _installationManager_PackageInstallationCancelled; _installationManager.PackageInstallationCancelled += OnPackageInstallationCancelled;
_installationManager.PackageInstallationCompleted += _installationManager_PackageInstallationCompleted; _installationManager.PackageInstallationCompleted += OnPackageInstallationCompleted;
_installationManager.PackageInstallationFailed += _installationManager_PackageInstallationFailed; _installationManager.PackageInstallationFailed += OnPackageInstallationFailed;
_taskManager.TaskCompleted += _taskManager_TaskCompleted; _taskManager.TaskCompleted += OnTaskCompleted;
return Task.CompletedTask; return Task.CompletedTask;
} }
void _installationManager_PackageInstalling(object sender, InstallationEventArgs e) private void OnPackageInstalling(object sender, InstallationEventArgs e)
{ {
SendMessageToAdminSessions("PackageInstalling", e.InstallationInfo); SendMessageToAdminSessions("PackageInstalling", e.InstallationInfo);
} }
void _installationManager_PackageInstallationCancelled(object sender, InstallationEventArgs e) private void OnPackageInstallationCancelled(object sender, InstallationEventArgs e)
{ {
SendMessageToAdminSessions("PackageInstallationCancelled", e.InstallationInfo); SendMessageToAdminSessions("PackageInstallationCancelled", e.InstallationInfo);
} }
void _installationManager_PackageInstallationCompleted(object sender, InstallationEventArgs e) private void OnPackageInstallationCompleted(object sender, InstallationEventArgs e)
{ {
SendMessageToAdminSessions("PackageInstallationCompleted", e.InstallationInfo); SendMessageToAdminSessions("PackageInstallationCompleted", e.InstallationInfo);
} }
void _installationManager_PackageInstallationFailed(object sender, InstallationFailedEventArgs e) private void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e)
{ {
SendMessageToAdminSessions("PackageInstallationFailed", e.InstallationInfo); SendMessageToAdminSessions("PackageInstallationFailed", e.InstallationInfo);
} }
void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e) private void OnTaskCompleted(object sender, TaskCompletionEventArgs e)
{ {
SendMessageToAdminSessions("ScheduledTaskEnded", e.Result); SendMessageToAdminSessions("ScheduledTaskEnded", e.Result);
} }
@ -101,7 +115,7 @@ namespace Emby.Server.Implementations.EntryPoints
/// </summary> /// </summary>
/// <param name="sender">The sender.</param> /// <param name="sender">The sender.</param>
/// <param name="e">The e.</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()); SendMessageToAdminSessions("PluginUninstalled", e.Argument.GetPluginInfo());
} }
@ -111,7 +125,7 @@ namespace Emby.Server.Implementations.EntryPoints
/// </summary> /// </summary>
/// <param name="sender">The source of the event.</param> /// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</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); _sessionManager.SendRestartRequiredNotification(CancellationToken.None);
} }
@ -121,7 +135,7 @@ namespace Emby.Server.Implementations.EntryPoints
/// </summary> /// </summary>
/// <param name="sender">The sender.</param> /// <param name="sender">The sender.</param>
/// <param name="e">The e.</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); var dto = _userManager.GetUserDto(e.Argument);
@ -133,19 +147,19 @@ namespace Emby.Server.Implementations.EntryPoints
/// </summary> /// </summary>
/// <param name="sender">The sender.</param> /// <param name="sender">The sender.</param>
/// <param name="e">The e.</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)); 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); var dto = _userManager.GetUserDto(e.Argument);
SendMessageToUserSession(e.Argument, "UserPolicyUpdated", dto); 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); var dto = _userManager.GetUserDto(e.Argument);
@ -168,7 +182,11 @@ namespace Emby.Server.Implementations.EntryPoints
{ {
try 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) catch (Exception)
{ {
@ -176,12 +194,11 @@ namespace Emby.Server.Implementations.EntryPoints
} }
} }
/// <summary> /// <inheritdoc />
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose() public void Dispose()
{ {
Dispose(true); Dispose(true);
GC.SuppressFinalize(this);
} }
/// <summary> /// <summary>
@ -192,18 +209,20 @@ namespace Emby.Server.Implementations.EntryPoints
{ {
if (dispose) if (dispose)
{ {
_userManager.UserDeleted -= userManager_UserDeleted; _userManager.UserDeleted -= OnUserDeleted;
_userManager.UserUpdated -= userManager_UserUpdated; _userManager.UserUpdated -= OnUserUpdated;
_userManager.UserPolicyUpdated -= _userManager_UserPolicyUpdated; _userManager.UserPolicyUpdated -= OnUserPolicyUpdated;
_userManager.UserConfigurationUpdated -= _userManager_UserConfigurationUpdated; _userManager.UserConfigurationUpdated -= OnUserConfigurationUpdated;
_installationManager.PluginUninstalled -= InstallationManager_PluginUninstalled; _installationManager.PluginUninstalled -= OnPluginUninstalled;
_installationManager.PackageInstalling -= _installationManager_PackageInstalling; _installationManager.PackageInstalling -= OnPackageInstalling;
_installationManager.PackageInstallationCancelled -= _installationManager_PackageInstallationCancelled; _installationManager.PackageInstallationCancelled -= OnPackageInstallationCancelled;
_installationManager.PackageInstallationCompleted -= _installationManager_PackageInstallationCompleted; _installationManager.PackageInstallationCompleted -= OnPackageInstallationCompleted;
_installationManager.PackageInstallationFailed -= _installationManager_PackageInstallationFailed; _installationManager.PackageInstallationFailed -= OnPackageInstallationFailed;
_appHost.HasPendingRestartChanged -= kernel_HasPendingRestartChanged; _appHost.HasPendingRestartChanged -= OnHasPendingRestartChanged;
_taskManager.TaskCompleted -= OnTaskCompleted;
} }
} }
} }

View File

@ -8,21 +8,28 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints namespace Emby.Server.Implementations.EntryPoints
{ {
/// <summary> /// <summary>
/// Class StartupWizard /// Class StartupWizard.
/// </summary> /// </summary>
public class StartupWizard : IServerEntryPoint public class StartupWizard : IServerEntryPoint
{ {
/// <summary> /// <summary>
/// The _app host /// The app host.
/// </summary> /// </summary>
private readonly IServerApplicationHost _appHost; private readonly IServerApplicationHost _appHost;
/// <summary> /// <summary>
/// The _user manager /// The user manager.
/// </summary> /// </summary>
private readonly ILogger _logger; private readonly ILogger _logger;
private IServerConfigurationManager _config; 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) public StartupWizard(IServerApplicationHost appHost, ILogger logger, IServerConfigurationManager config)
{ {
_appHost = appHost; _appHost = appHost;
@ -30,9 +37,7 @@ namespace Emby.Server.Implementations.EntryPoints
_config = config; _config = config;
} }
/// <summary> /// <inheritdoc />
/// Runs this instance.
/// </summary>
public Task RunAsync() public Task RunAsync()
{ {
if (!_appHost.CanLaunchWebBrowser) if (!_appHost.CanLaunchWebBrowser)
@ -57,9 +62,7 @@ namespace Emby.Server.Implementations.EntryPoints
return Task.CompletedTask; return Task.CompletedTask;
} }
/// <summary> /// <inheritdoc />
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose() public void Dispose()
{ {
} }

View File

@ -10,30 +10,36 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints namespace Emby.Server.Implementations.EntryPoints
{ {
/// <summary> /// <summary>
/// Class UdpServerEntryPoint /// Class UdpServerEntryPoint.
/// </summary> /// </summary>
public class UdpServerEntryPoint : IServerEntryPoint public class UdpServerEntryPoint : IServerEntryPoint
{ {
/// <summary> /// <summary>
/// Gets or sets the UDP server. /// The port of the UDP server.
/// </summary> /// </summary>
/// <value>The UDP server.</value> public const int PortNumber = 7359;
private UdpServer UdpServer { get; set; }
/// <summary> /// <summary>
/// The _logger /// The logger.
/// </summary> /// </summary>
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly ISocketFactory _socketFactory; private readonly ISocketFactory _socketFactory;
private readonly IServerApplicationHost _appHost; private readonly IServerApplicationHost _appHost;
private readonly IJsonSerializer _json; private readonly IJsonSerializer _json;
public const int PortNumber = 7359; /// <summary>
/// The UDP server.
/// </summary>
private UdpServer _udpServer;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="UdpServerEntryPoint" /> class. /// Initializes a new instance of the <see cref="UdpServerEntryPoint" /> class.
/// </summary> /// </summary>
public UdpServerEntryPoint(ILogger logger, IServerApplicationHost appHost, IJsonSerializer json, ISocketFactory socketFactory) public UdpServerEntryPoint(
ILogger logger,
IServerApplicationHost appHost,
IJsonSerializer json,
ISocketFactory socketFactory)
{ {
_logger = logger; _logger = logger;
_appHost = appHost; _appHost = appHost;
@ -41,9 +47,7 @@ namespace Emby.Server.Implementations.EntryPoints
_socketFactory = socketFactory; _socketFactory = socketFactory;
} }
/// <summary> /// <inheritdoc />
/// Runs this instance.
/// </summary>
public Task RunAsync() public Task RunAsync()
{ {
var udpServer = new UdpServer(_logger, _appHost, _json, _socketFactory); var udpServer = new UdpServer(_logger, _appHost, _json, _socketFactory);
@ -52,7 +56,7 @@ namespace Emby.Server.Implementations.EntryPoints
{ {
udpServer.Start(PortNumber); udpServer.Start(PortNumber);
UdpServer = udpServer; _udpServer = udpServer;
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -62,12 +66,11 @@ namespace Emby.Server.Implementations.EntryPoints
return Task.CompletedTask; return Task.CompletedTask;
} }
/// <summary> /// <inheritdoc />
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose() public void Dispose()
{ {
Dispose(true); Dispose(true);
GC.SuppressFinalize(this);
} }
/// <summary> /// <summary>
@ -78,9 +81,9 @@ namespace Emby.Server.Implementations.EntryPoints
{ {
if (dispose) if (dispose)
{ {
if (UdpServer != null) if (_udpServer != null)
{ {
UdpServer.Dispose(); _udpServer.Dispose();
} }
} }
} }

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;

View File

@ -282,6 +282,7 @@ namespace Emby.Server.Implementations.HttpClientManager
}; };
} }
/// <inheritdoc />
public Task<HttpResponseInfo> Post(HttpRequestOptions options) public Task<HttpResponseInfo> Post(HttpRequestOptions options)
=> SendAsync(options, HttpMethod.Post); => SendAsync(options, HttpMethod.Post);

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
@ -5,12 +7,10 @@ using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Net; using System.Net;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml; using System.Xml;
using Emby.Server.Implementations.Services; using Emby.Server.Implementations.Services;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
@ -24,12 +24,12 @@ using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
namespace Emby.Server.Implementations.HttpServer namespace Emby.Server.Implementations.HttpServer
{ {
/// <summary> /// <summary>
/// Class HttpResultFactory /// Class HttpResultFactory.
/// </summary> /// </summary>
public class HttpResultFactory : IHttpResultFactory public class HttpResultFactory : IHttpResultFactory
{ {
/// <summary> /// <summary>
/// The _logger /// The logger.
/// </summary> /// </summary>
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;

View File

@ -8,11 +8,17 @@ using Microsoft.Net.Http.Headers;
namespace Emby.Server.Implementations.HttpServer namespace Emby.Server.Implementations.HttpServer
{ {
/// <summary>
/// Class ResponseFilter.
/// </summary>
public class ResponseFilter public class ResponseFilter
{ {
private static readonly CultureInfo _usCulture = CultureInfo.ReadOnly(new CultureInfo("en-US"));
private readonly ILogger _logger; 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) public ResponseFilter(ILogger logger)
{ {
_logger = logger; _logger = logger;
@ -37,7 +43,7 @@ namespace Emby.Server.Implementations.HttpServer
if (!string.IsNullOrEmpty(exception.Message)) if (!string.IsNullOrEmpty(exception.Message))
{ {
var error = exception.Message.Replace(Environment.NewLine, " "); var error = exception.Message.Replace(Environment.NewLine, " ", StringComparison.Ordinal);
error = RemoveControlCharacters(error); error = RemoveControlCharacters(error);
res.Headers.Add("X-Application-Error-Code", 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) if (hasHeaders.Headers.TryGetValue(HeaderNames.ContentLength, out string contentLength)
&& !string.IsNullOrEmpty(contentLength)) && !string.IsNullOrEmpty(contentLength))
{ {
var length = long.Parse(contentLength, _usCulture); var length = long.Parse(contentLength, CultureInfo.InvariantCulture);
if (length > 0) if (length > 0)
{ {

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Linq; using System.Linq;
using Emby.Server.Implementations.SocketSharp; using Emby.Server.Implementations.SocketSharp;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;

View File

@ -10,37 +10,20 @@ using Microsoft.Net.Http.Headers;
namespace Emby.Server.Implementations.HttpServer namespace Emby.Server.Implementations.HttpServer
{ {
/// <summary> /// <summary>
/// Class StreamWriter /// Class StreamWriter.
/// </summary> /// </summary>
public class StreamWriter : IAsyncStreamWriter, IHasHeaders public class StreamWriter : IAsyncStreamWriter, IHasHeaders
{ {
/// <summary> /// <summary>
/// Gets or sets the source stream. /// The options.
/// </summary>
/// <value>The source stream.</value>
private Stream SourceStream { get; set; }
private byte[] SourceBytes { get; set; }
/// <summary>
/// The _options
/// </summary> /// </summary>
private readonly IDictionary<string, string> _options = new Dictionary<string, string>(); 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> /// <summary>
/// Initializes a new instance of the <see cref="StreamWriter" /> class. /// Initializes a new instance of the <see cref="StreamWriter" /> class.
/// </summary> /// </summary>
/// <param name="source">The source.</param> /// <param name="source">The source.</param>
/// <param name="contentType">Type of the content.</param> /// <param name="contentType">Type of the content.</param>
/// <param name="logger">The logger.</param>
public StreamWriter(Stream source, string contentType) public StreamWriter(Stream source, string contentType)
{ {
if (string.IsNullOrEmpty(contentType)) if (string.IsNullOrEmpty(contentType))
@ -65,6 +48,7 @@ namespace Emby.Server.Implementations.HttpServer
/// </summary> /// </summary>
/// <param name="source">The source.</param> /// <param name="source">The source.</param>
/// <param name="contentType">Type of the content.</param> /// <param name="contentType">Type of the content.</param>
/// <param name="contentLength">The content length.</param>
public StreamWriter(byte[] source, string contentType, int contentLength) public StreamWriter(byte[] source, string contentType, int contentLength)
{ {
if (string.IsNullOrEmpty(contentType)) if (string.IsNullOrEmpty(contentType))
@ -78,6 +62,31 @@ namespace Emby.Server.Implementations.HttpServer
Headers[HeaderNames.ContentType] = contentType; 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) public async Task WriteToAsync(Stream responseStream, CancellationToken cancellationToken)
{ {
try try
@ -98,19 +107,13 @@ namespace Emby.Server.Implementations.HttpServer
} }
catch catch
{ {
if (OnError != null) OnError?.Invoke();
{
OnError();
}
throw; throw;
} }
finally finally
{ {
if (OnComplete != null) OnComplete?.Invoke();
{
OnComplete();
}
} }
} }
} }

View File

@ -7,7 +7,6 @@ using Emby.Server.Implementations.Net;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Services;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using UtfUnknown; using UtfUnknown;
@ -15,32 +14,74 @@ using UtfUnknown;
namespace Emby.Server.Implementations.HttpServer namespace Emby.Server.Implementations.HttpServer
{ {
/// <summary> /// <summary>
/// Class WebSocketConnection /// Class WebSocketConnection.
/// </summary> /// </summary>
public class WebSocketConnection : IWebSocketConnection public class WebSocketConnection : IWebSocketConnection
{ {
public event EventHandler<EventArgs> Closed;
/// <summary> /// <summary>
/// The _socket /// The logger.
/// </summary>
private readonly IWebSocket _socket;
/// <summary>
/// The _remote end point
/// </summary>
public string RemoteEndPoint { get; private set; }
/// <summary>
/// The logger
/// </summary> /// </summary>
private readonly ILogger _logger; private readonly ILogger _logger;
/// <summary> /// <summary>
/// The _json serializer /// The json serializer.
/// </summary> /// </summary>
private readonly IJsonSerializer _jsonSerializer; 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> /// <summary>
/// Gets or sets the receive action. /// Gets or sets the receive action.
/// </summary> /// </summary>
@ -64,6 +105,7 @@ namespace Emby.Server.Implementations.HttpServer
/// </summary> /// </summary>
/// <value>The URL.</value> /// <value>The URL.</value>
public string Url { get; set; } public string Url { get; set; }
/// <summary> /// <summary>
/// Gets or sets the query string. /// Gets or sets the query string.
/// </summary> /// </summary>
@ -71,44 +113,12 @@ namespace Emby.Server.Implementations.HttpServer
public IQueryCollection QueryString { get; set; } public IQueryCollection QueryString { get; set; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="WebSocketConnection" /> class. /// Gets the state.
/// </summary> /// </summary>
/// <param name="socket">The socket.</param> /// <value>The state.</value>
/// <param name="remoteEndPoint">The remote end point.</param> public WebSocketState State => _socket.State;
/// <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(); void OnSocketClosed(object sender, EventArgs e)
_jsonSerializer = jsonSerializer;
_socket = socket;
_socket.OnReceiveBytes = OnReceiveInternal;
RemoteEndPoint = remoteEndPoint;
_logger = logger;
socket.Closed += socket_Closed;
}
void socket_Closed(object sender, EventArgs e)
{ {
Closed?.Invoke(this, EventArgs.Empty); Closed?.Invoke(this, EventArgs.Empty);
} }
@ -210,6 +220,7 @@ namespace Emby.Server.Implementations.HttpServer
return _socket.SendAsync(buffer, true, cancellationToken); return _socket.SendAsync(buffer, true, cancellationToken);
} }
/// <inheritdoc />
public Task SendAsync(string text, CancellationToken cancellationToken) public Task SendAsync(string text, CancellationToken cancellationToken)
{ {
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
@ -222,18 +233,11 @@ namespace Emby.Server.Implementations.HttpServer
return _socket.SendAsync(text, true, cancellationToken); return _socket.SendAsync(text, true, cancellationToken);
} }
/// <summary> /// <inheritdoc />
/// 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>
public void Dispose() public void Dispose()
{ {
Dispose(true); Dispose(true);
GC.SuppressFinalize(this);
} }
/// <summary> /// <summary>

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
namespace Emby.Server.Implementations.IO namespace Emby.Server.Implementations.IO
{ {
public class ExtendedFileSystemInfo public class ExtendedFileSystemInfo

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
@ -16,22 +18,22 @@ namespace Emby.Server.Implementations.IO
public class LibraryMonitor : ILibraryMonitor public class LibraryMonitor : ILibraryMonitor
{ {
/// <summary> /// <summary>
/// The file system watchers /// The file system watchers.
/// </summary> /// </summary>
private readonly ConcurrentDictionary<string, FileSystemWatcher> _fileSystemWatchers = new ConcurrentDictionary<string, FileSystemWatcher>(StringComparer.OrdinalIgnoreCase); private readonly ConcurrentDictionary<string, FileSystemWatcher> _fileSystemWatchers = new ConcurrentDictionary<string, FileSystemWatcher>(StringComparer.OrdinalIgnoreCase);
/// <summary> /// <summary>
/// The affected paths /// The affected paths.
/// </summary> /// </summary>
private readonly List<FileRefresher> _activeRefreshers = new List<FileRefresher>(); private readonly List<FileRefresher> _activeRefreshers = new List<FileRefresher>();
/// <summary> /// <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> /// </summary>
private readonly ConcurrentDictionary<string, string> _tempIgnoredPaths = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase); private readonly ConcurrentDictionary<string, string> _tempIgnoredPaths = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
/// <summary> /// <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> /// </summary>
private static readonly HashSet<string> _alwaysIgnoreFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase) private static readonly HashSet<string> _alwaysIgnoreFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{ {

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.IO; using System.IO;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Buffers; using System.Buffers;
using System.IO; using System.IO;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;

View File

@ -42,6 +42,10 @@ namespace Emby.Server.Implementations.Library
".grab", ".grab",
}; };
/// <summary>
/// Initializes a new instance of the <see cref="CoreResolutionIgnoreRule"/> class.
/// </summary>
/// <param name="libraryManager">The library manager.</param>
public CoreResolutionIgnoreRule(ILibraryManager libraryManager) public CoreResolutionIgnoreRule(ILibraryManager libraryManager)
{ {
_libraryManager = libraryManager; _libraryManager = libraryManager;

View File

@ -10,10 +10,17 @@ using MediaBrowser.Model.Cryptography;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library
{ {
/// <summary>
/// The default authentication provider.
/// </summary>
public class DefaultAuthenticationProvider : IAuthenticationProvider, IRequiresResolvedUser public class DefaultAuthenticationProvider : IAuthenticationProvider, IRequiresResolvedUser
{ {
private readonly ICryptoProvider _cryptographyProvider; 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) public DefaultAuthenticationProvider(ICryptoProvider cryptographyProvider)
{ {
_cryptographyProvider = 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. // This is the version that we need to use for local users. Because reasons.
public Task<ProviderAuthenticationResult> Authenticate(string username, string password, User resolvedUser) public Task<ProviderAuthenticationResult> Authenticate(string username, string password, User resolvedUser)
{ {
bool success = false;
if (resolvedUser == null) if (resolvedUser == null)
{ {
throw new ArgumentNullException(nameof(resolvedUser)); throw new ArgumentNullException(nameof(resolvedUser));
} }
bool success = false;
// As long as jellyfin supports passwordless users, we need this little block here to accommodate // As long as jellyfin supports passwordless users, we need this little block here to accommodate
if (!HasPassword(resolvedUser) && string.IsNullOrEmpty(password)) if (!HasPassword(resolvedUser) && string.IsNullOrEmpty(password))
{ {

View File

@ -12,6 +12,9 @@ using MediaBrowser.Model.Users;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library
{ {
/// <summary>
/// The default password reset provider.
/// </summary>
public class DefaultPasswordResetProvider : IPasswordResetProvider public class DefaultPasswordResetProvider : IPasswordResetProvider
{ {
private const string BaseResetFileName = "passwordreset"; private const string BaseResetFileName = "passwordreset";
@ -22,6 +25,12 @@ namespace Emby.Server.Implementations.Library
private readonly string _passwordResetFileBase; private readonly string _passwordResetFileBase;
private readonly string _passwordResetFileBaseDir; 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( public DefaultPasswordResetProvider(
IServerConfigurationManager configurationManager, IServerConfigurationManager configurationManager,
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
@ -56,8 +65,8 @@ namespace Emby.Server.Implementations.Library
File.Delete(resetfile); File.Delete(resetfile);
} }
else if (string.Equals( else if (string.Equals(
spr.Pin.Replace("-", string.Empty), spr.Pin.Replace("-", string.Empty, StringComparison.Ordinal),
pin.Replace("-", string.Empty), pin.Replace("-", string.Empty, StringComparison.Ordinal),
StringComparison.InvariantCultureIgnoreCase)) StringComparison.InvariantCultureIgnoreCase))
{ {
var resetUser = _userManager.GetUserByName(spr.UserName); var resetUser = _userManager.GetUserByName(spr.UserName);

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Globalization; using System.Globalization;
using System.Threading; using System.Threading;

View File

@ -4,37 +4,48 @@ using MediaBrowser.Controller.Entities;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library
{ {
/// <summary>
/// An invalid authentication provider.
/// </summary>
public class InvalidAuthProvider : IAuthenticationProvider public class InvalidAuthProvider : IAuthenticationProvider
{ {
/// <inheritdoc />
public string Name => "InvalidOrMissingAuthenticationProvider"; public string Name => "InvalidOrMissingAuthenticationProvider";
/// <inheritdoc />
public bool IsEnabled => true; public bool IsEnabled => true;
/// <inheritdoc />
public Task<ProviderAuthenticationResult> Authenticate(string username, string password) 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"); 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) public bool HasPassword(User user)
{ {
return true; return true;
} }
/// <inheritdoc />
public Task ChangePassword(User user, string newPassword) public Task ChangePassword(User user, string newPassword)
{ {
return Task.CompletedTask; return Task.CompletedTask;
} }
/// <inheritdoc />
public void ChangeEasyPassword(User user, string newPassword, string newPasswordHash) public void ChangeEasyPassword(User user, string newPassword, string newPasswordHash)
{ {
// Nothing here // Nothing here
} }
/// <inheritdoc />
public string GetPasswordHash(User user) public string GetPasswordHash(User user)
{ {
return string.Empty; return string.Empty;
} }
/// <inheritdoc />
public string GetEasyPasswordHash(User user) public string GetEasyPasswordHash(User user)
{ {
return string.Empty; return string.Empty;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
@ -829,7 +831,7 @@ namespace Emby.Server.Implementations.Library
{ {
Path = path, Path = path,
IsFolder = isFolder, IsFolder = isFolder,
OrderBy = new[] { ItemSortBy.DateCreated }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(), OrderBy = new[] { (ItemSortBy.DateCreated, SortOrder.Descending) },
Limit = 1, Limit = 1,
DtoOptions = new DtoOptions(true) DtoOptions = new DtoOptions(true)
}; };
@ -1257,7 +1259,7 @@ namespace Emby.Server.Implementations.Library
public List<BaseItem> GetItemList(InternalItemsQuery query, bool allowExternalContent) 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); var parent = GetItemById(query.ParentId);
if (parent != null) if (parent != null)

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -89,10 +91,9 @@ namespace Emby.Server.Implementations.Library
Limit = 200, Limit = 200,
OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending) }, OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) },
DtoOptions = dtoOptions DtoOptions = dtoOptions
}); });
} }

View File

@ -3,6 +3,9 @@ using System.Text.RegularExpressions;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library
{ {
/// <summary>
/// Class providing extension methods for working with paths.
/// </summary>
public static class PathExtensions public static class PathExtensions
{ {
/// <summary> /// <summary>
@ -32,6 +35,7 @@ namespace Emby.Server.Implementations.Library
int end = str.IndexOf(']', start); int end = str.IndexOf(']', start);
return str.Substring(start, end - start); return str.Substring(start, end - start);
} }
// for imdbid we also accept pattern matching // for imdbid we also accept pattern matching
if (string.Equals(attrib, "imdbid", StringComparison.OrdinalIgnoreCase)) if (string.Equals(attrib, "imdbid", StringComparison.OrdinalIgnoreCase))
{ {

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -13,7 +15,7 @@ using MediaBrowser.Model.IO;
namespace Emby.Server.Implementations.Library.Resolvers.Audio namespace Emby.Server.Implementations.Library.Resolvers.Audio
{ {
/// <summary> /// <summary>
/// Class AudioResolver /// Class AudioResolver.
/// </summary> /// </summary>
public class AudioResolver : ItemResolver<MediaBrowser.Controller.Entities.Audio.Audio>, IMultiItemResolver public class AudioResolver : ItemResolver<MediaBrowser.Controller.Entities.Audio.Audio>, IMultiItemResolver
{ {

View File

@ -13,7 +13,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Resolvers.Audio namespace Emby.Server.Implementations.Library.Resolvers.Audio
{ {
/// <summary> /// <summary>
/// Class MusicAlbumResolver /// Class MusicAlbumResolver.
/// </summary> /// </summary>
public class MusicAlbumResolver : ItemResolver<MusicAlbum> public class MusicAlbumResolver : ItemResolver<MusicAlbum>
{ {
@ -21,6 +21,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly ILibraryManager _libraryManager; 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) public MusicAlbumResolver(ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager)
{ {
_logger = logger; _logger = logger;
@ -50,16 +56,25 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
return null; return null;
} }
if (!args.IsDirectory) return null; if (!args.IsDirectory)
{
return null;
}
// Avoid mis-identifying top folders // Avoid mis-identifying top folders
if (args.HasParent<MusicAlbum>()) return null; if (args.HasParent<MusicAlbum>())
if (args.Parent.IsRoot) return null; {
return null;
}
if (args.Parent.IsRoot)
{
return null;
}
return IsMusicAlbum(args) ? new MusicAlbum() : null; return IsMusicAlbum(args) ? new MusicAlbum() : null;
} }
/// <summary> /// <summary>
/// Determine if the supplied file data points to a music album /// Determine if the supplied file data points to a music album
/// </summary> /// </summary>
@ -79,7 +94,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
if (args.IsDirectory) if (args.IsDirectory)
{ {
// if (args.Parent is MusicArtist) return true; //saves us from testing children twice // 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; return false;
@ -88,7 +106,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
/// <summary> /// <summary>
/// Determine if the supplied list contains what we should consider music /// Determine if the supplied list contains what we should consider music
/// </summary> /// </summary>
private bool ContainsMusic(IEnumerable<FileSystemMetadata> list, private bool ContainsMusic(
IEnumerable<FileSystemMetadata> list,
bool allowSubfolders, bool allowSubfolders,
IDirectoryService directoryService, IDirectoryService directoryService,
ILogger logger, ILogger logger,

View File

@ -11,7 +11,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Resolvers.Audio namespace Emby.Server.Implementations.Library.Resolvers.Audio
{ {
/// <summary> /// <summary>
/// Class MusicArtistResolver /// Class MusicArtistResolver.
/// </summary> /// </summary>
public class MusicArtistResolver : ItemResolver<MusicArtist> public class MusicArtistResolver : ItemResolver<MusicArtist>
{ {
@ -20,6 +20,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IServerConfigurationManager _config; 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) public MusicArtistResolver(ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager, IServerConfigurationManager config)
{ {
_logger = logger; _logger = logger;
@ -41,7 +48,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
/// <returns>MusicArtist.</returns> /// <returns>MusicArtist.</returns>
protected override MusicArtist Resolve(ItemResolveArgs args) protected override MusicArtist Resolve(ItemResolveArgs args)
{ {
if (!args.IsDirectory) return null; if (!args.IsDirectory)
{
return null;
}
// Don't allow nested artists // Don't allow nested artists
if (args.HasParent<MusicArtist>() || args.HasParent<MusicAlbum>()) 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 // 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; return args.FileSystemChildren.Where(i => i.IsDirectory).Any(i => albumResolver.IsMusicAlbum(i.FullName, directoryService, args.GetLibraryOptions())) ? new MusicArtist() : null;
} }
} }
} }

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -10,7 +12,7 @@ using MediaBrowser.Model.Entities;
namespace Emby.Server.Implementations.Library.Resolvers namespace Emby.Server.Implementations.Library.Resolvers
{ {
/// <summary> /// <summary>
/// Resolves a Path into a Video or Video subclass /// Resolves a Path into a Video or Video subclass.
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
public abstract class BaseVideoResolver<T> : MediaBrowser.Controller.Resolvers.ItemResolver<T> public abstract class BaseVideoResolver<T> : MediaBrowser.Controller.Resolvers.ItemResolver<T>

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -7,18 +9,10 @@ using MediaBrowser.Model.Entities;
namespace Emby.Server.Implementations.Library.Resolvers.Books namespace Emby.Server.Implementations.Library.Resolvers.Books
{ {
/// <summary>
///
/// </summary>
public class BookResolver : MediaBrowser.Controller.Resolvers.ItemResolver<Book> public class BookResolver : MediaBrowser.Controller.Resolvers.ItemResolver<Book>
{ {
private readonly string[] _validExtensions = { ".pdf", ".epub", ".mobi", ".cbr", ".cbz", ".azw3" }; private readonly string[] _validExtensions = { ".pdf", ".epub", ".mobi", ".cbr", ".cbz", ".azw3" };
/// <summary>
///
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
protected override Book Resolve(ItemResolveArgs args) protected override Book Resolve(ItemResolveArgs args)
{ {
var collectionType = args.GetCollectionType(); var collectionType = args.GetCollectionType();
@ -47,11 +41,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books
return null; return null;
} }
/// <summary>
///
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private Book GetBook(ItemResolveArgs args) private Book GetBook(ItemResolveArgs args)
{ {
var bookFiles = args.FileSystemChildren.Where(f => var bookFiles = args.FileSystemChildren.Where(f =>

View File

@ -5,7 +5,7 @@ using MediaBrowser.Controller.Resolvers;
namespace Emby.Server.Implementations.Library.Resolvers namespace Emby.Server.Implementations.Library.Resolvers
{ {
/// <summary> /// <summary>
/// Class FolderResolver /// Class FolderResolver.
/// </summary> /// </summary>
public class FolderResolver : FolderResolver<Folder> public class FolderResolver : FolderResolver<Folder>
{ {
@ -32,7 +32,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
} }
/// <summary> /// <summary>
/// Class FolderResolver /// Class FolderResolver.
/// </summary> /// </summary>
/// <typeparam name="TItemType">The type of the T item type.</typeparam> /// <typeparam name="TItemType">The type of the T item type.</typeparam>
public abstract class FolderResolver<TItemType> : ItemResolver<TItemType> public abstract class FolderResolver<TItemType> : ItemResolver<TItemType>

View File

@ -5,7 +5,7 @@ using MediaBrowser.Controller.Resolvers;
namespace Emby.Server.Implementations.Library.Resolvers namespace Emby.Server.Implementations.Library.Resolvers
{ {
/// <summary> /// <summary>
/// Class ItemResolver /// Class ItemResolver.
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
public abstract class ItemResolver<T> : IItemResolver public abstract class ItemResolver<T> : IItemResolver

View File

@ -4,12 +4,11 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Extensions;
namespace Emby.Server.Implementations.Library.Resolvers.Movies namespace Emby.Server.Implementations.Library.Resolvers.Movies
{ {
/// <summary> /// <summary>
/// Class BoxSetResolver /// Class BoxSetResolver.
/// </summary> /// </summary>
public class BoxSetResolver : FolderResolver<BoxSet> public class BoxSetResolver : FolderResolver<BoxSet>
{ {

View File

@ -17,7 +17,7 @@ using MediaBrowser.Model.IO;
namespace Emby.Server.Implementations.Library.Resolvers.Movies namespace Emby.Server.Implementations.Library.Resolvers.Movies
{ {
/// <summary> /// <summary>
/// Class MovieResolver /// Class MovieResolver.
/// </summary> /// </summary>
public class MovieResolver : BaseVideoResolver<Video>, IMultiItemResolver public class MovieResolver : BaseVideoResolver<Video>, IMultiItemResolver
{ {
@ -27,6 +27,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
/// <value>The priority.</value> /// <value>The priority.</value>
public override ResolverPriority Priority => ResolverPriority.Third; public override ResolverPriority Priority => ResolverPriority.Third;
/// <inheritdoc />
public MultiItemResolverResult ResolveMultiple( public MultiItemResolverResult ResolveMultiple(
Folder parent, Folder parent,
List<FileSystemMetadata> files, List<FileSystemMetadata> files,
@ -544,6 +545,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
private IImageProcessor _imageProcessor; 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) public MovieResolver(ILibraryManager libraryManager, IImageProcessor imageProcessor)
: base(libraryManager) : base(libraryManager)
{ {

View File

@ -7,11 +7,19 @@ using MediaBrowser.Model.Entities;
namespace Emby.Server.Implementations.Library.Resolvers namespace Emby.Server.Implementations.Library.Resolvers
{ {
/// <summary>
/// Class PhotoAlbumResolver.
/// </summary>
public class PhotoAlbumResolver : FolderResolver<PhotoAlbum> public class PhotoAlbumResolver : FolderResolver<PhotoAlbum>
{ {
private readonly IImageProcessor _imageProcessor; private readonly IImageProcessor _imageProcessor;
private ILibraryManager _libraryManager; 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) public PhotoAlbumResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager)
{ {
_imageProcessor = imageProcessor; _imageProcessor = imageProcessor;
@ -74,9 +82,11 @@ namespace Emby.Server.Implementations.Library.Resolvers
} }
} }
} }
return false; return false;
} }
/// <inheritdoc />
public override ResolverPriority Priority => ResolverPriority.Second; public override ResolverPriority Priority => ResolverPriority.Second;
} }
} }

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;

View File

@ -1,10 +1,11 @@
#pragma warning disable CS1591
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.Playlists;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Extensions;
namespace Emby.Server.Implementations.Library.Resolvers namespace Emby.Server.Implementations.Library.Resolvers
{ {

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;

View File

@ -7,7 +7,7 @@ using MediaBrowser.Model.Entities;
namespace Emby.Server.Implementations.Library.Resolvers.TV namespace Emby.Server.Implementations.Library.Resolvers.TV
{ {
/// <summary> /// <summary>
/// Class EpisodeResolver /// Class EpisodeResolver.
/// </summary> /// </summary>
public class EpisodeResolver : BaseVideoResolver<Episode> public class EpisodeResolver : BaseVideoResolver<Episode>
{ {
@ -26,6 +26,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
} }
var season = parent as Season; var season = parent as Season;
// Just in case the user decided to nest episodes. // Just in case the user decided to nest episodes.
// Not officially supported but in some cases we can handle it. // Not officially supported but in some cases we can handle it.
if (season == null) if (season == null)
@ -73,6 +74,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
return null; 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) public EpisodeResolver(ILibraryManager libraryManager)
: base(libraryManager) : base(libraryManager)
{ {

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -14,7 +16,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Resolvers.TV namespace Emby.Server.Implementations.Library.Resolvers.TV
{ {
/// <summary> /// <summary>
/// Class SeriesResolver /// Class SeriesResolver.
/// </summary> /// </summary>
public class SeriesResolver : FolderResolver<Series> public class SeriesResolver : FolderResolver<Series>
{ {
@ -22,6 +24,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly ILibraryManager _libraryManager; 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) public SeriesResolver(IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -13,8 +15,6 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library
{ {
/// <summary>
/// </summary>
public class SearchEngine : ISearchEngine public class SearchEngine : ISearchEngine
{ {
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
@ -162,7 +162,7 @@ namespace Emby.Server.Implementations.Library
Limit = query.Limit, Limit = query.Limit,
IncludeItemsByName = string.IsNullOrEmpty(query.ParentId), IncludeItemsByName = string.IsNullOrEmpty(query.ParentId),
ParentId = string.IsNullOrEmpty(query.ParentId) ? Guid.Empty : new Guid(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, Recursive = true,
IsKids = query.IsKids, IsKids = query.IsKids,

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
@ -15,7 +17,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library
{ {
/// <summary> /// <summary>
/// Class UserDataManager /// Class UserDataManager.
/// </summary> /// </summary>
public class UserDataManager : IUserDataManager public class UserDataManager : IUserDataManager
{ {
@ -55,6 +57,7 @@ namespace Emby.Server.Implementations.Library
{ {
throw new ArgumentNullException(nameof(userData)); throw new ArgumentNullException(nameof(userData));
} }
if (item == null) if (item == null)
{ {
throw new ArgumentNullException(nameof(item)); throw new ArgumentNullException(nameof(item));
@ -160,11 +163,6 @@ namespace Emby.Server.Implementations.Library
return GetUserData(user, item.Id, item.GetUserDataKeys()); 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) public UserItemData GetUserData(Guid userId, BaseItem item)
{ {
return GetUserData(userId, item.Id, item.GetUserDataKeys()); return GetUserData(userId, item.Id, item.GetUserDataKeys());
@ -228,24 +226,21 @@ namespace Emby.Server.Implementations.Library
{ {
var pctIn = decimal.Divide(positionTicks, runtimeTicks) * 100; var pctIn = decimal.Divide(positionTicks, runtimeTicks) * 100;
// Don't track in very beginning
if (pctIn < _config.Configuration.MinResumePct) if (pctIn < _config.Configuration.MinResumePct)
{ {
// ignore progress during the beginning
positionTicks = 0; positionTicks = 0;
} }
// If we're at the end, assume completed
else if (pctIn > _config.Configuration.MaxResumePct || positionTicks >= runtimeTicks) else if (pctIn > _config.Configuration.MaxResumePct || positionTicks >= runtimeTicks)
{ {
// mark as completed close to the end
positionTicks = 0; positionTicks = 0;
data.Played = playedToCompletion = true; data.Played = playedToCompletion = true;
} }
else else
{ {
// Enforce MinResumeDuration // Enforce MinResumeDuration
var durationSeconds = TimeSpan.FromTicks(runtimeTicks).TotalSeconds; var durationSeconds = TimeSpan.FromTicks(runtimeTicks).TotalSeconds;
if (durationSeconds < _config.Configuration.MinResumeDurationSeconds) if (durationSeconds < _config.Configuration.MinResumeDurationSeconds)
{ {
positionTicks = 0; positionTicks = 0;
@ -265,6 +260,7 @@ namespace Emby.Server.Implementations.Library
positionTicks = 0; positionTicks = 0;
data.Played = false; data.Played = false;
} }
if (!item.SupportsPositionTicksResume) if (!item.SupportsPositionTicksResume)
{ {
positionTicks = 0; positionTicks = 0;

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
@ -36,19 +38,19 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library
{ {
/// <summary> /// <summary>
/// Class UserManager /// Class UserManager.
/// </summary> /// </summary>
public class UserManager : IUserManager public class UserManager : IUserManager
{ {
/// <summary> /// <summary>
/// The _logger /// The logger.
/// </summary> /// </summary>
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly object _policySyncLock = new object(); private readonly object _policySyncLock = new object();
/// <summary> /// <summary>
/// Gets the active user repository /// Gets the active user repository.
/// </summary> /// </summary>
/// <value>The user repository.</value> /// <value>The user repository.</value>
private readonly IUserRepository _userRepository; private readonly IUserRepository _userRepository;
@ -194,10 +196,6 @@ namespace Emby.Server.Implementations.Library
return user; return user;
} }
/// <inheritdoc />
public User GetUserById(string id)
=> GetUserById(new Guid(id));
public User GetUserByName(string name) public User GetUserByName(string name)
{ {
if (string.IsNullOrWhiteSpace(name)) if (string.IsNullOrWhiteSpace(name))
@ -358,6 +356,8 @@ namespace Emby.Server.Implementations.Library
return success ? user : null; return success ? user : null;
} }
#nullable enable
private static string GetAuthenticationProviderId(IAuthenticationProvider provider) private static string GetAuthenticationProviderId(IAuthenticationProvider provider)
{ {
return provider.GetType().FullName; return provider.GetType().FullName;
@ -378,7 +378,7 @@ namespace Emby.Server.Implementations.Library
return GetPasswordResetProviders(user)[0]; return GetPasswordResetProviders(user)[0];
} }
private IAuthenticationProvider[] GetAuthenticationProviders(User user) private IAuthenticationProvider[] GetAuthenticationProviders(User? user)
{ {
var authenticationProviderId = user?.Policy.AuthenticationProviderId; var authenticationProviderId = user?.Policy.AuthenticationProviderId;
@ -399,7 +399,7 @@ namespace Emby.Server.Implementations.Library
return providers; return providers;
} }
private IPasswordResetProvider[] GetPasswordResetProviders(User user) private IPasswordResetProvider[] GetPasswordResetProviders(User? user)
{ {
var passwordResetProviderId = user?.Policy.PasswordResetProviderId; var passwordResetProviderId = user?.Policy.PasswordResetProviderId;
@ -418,7 +418,11 @@ namespace Emby.Server.Implementations.Library
return providers; 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 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 username,
string password, string password,
string hashedPassword, string hashedPassword,
User user, User? user,
string remoteEndPoint) string remoteEndPoint)
{ {
bool success = false; bool success = false;
IAuthenticationProvider authenticationProvider = null; IAuthenticationProvider? authenticationProvider = null;
foreach (var provider in GetAuthenticationProviders(user)) foreach (var provider in GetAuthenticationProviders(user))
{ {
@ -547,6 +551,8 @@ namespace Emby.Server.Implementations.Library
_users[user.Id] = user; _users[user.Id] = user;
} }
#nullable restore
public UserDto GetUserDto(User user, string remoteEndPoint = null) public UserDto GetUserDto(User user, string remoteEndPoint = null)
{ {
if (user == null) if (user == null)

View File

@ -1,3 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
@ -340,7 +342,7 @@ namespace Emby.Server.Implementations.Library
var query = new InternalItemsQuery(user) var query = new InternalItemsQuery(user)
{ {
IncludeItemTypes = includeItemTypes, 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, IsFolder = includeItemTypes.Length == 0 ? false : (bool?)null,
ExcludeItemTypes = excludeItemTypes, ExcludeItemTypes = excludeItemTypes,
IsVirtualItem = false, IsVirtualItem = false,

View File

@ -8,12 +8,12 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Validators namespace Emby.Server.Implementations.Library.Validators
{ {
/// <summary> /// <summary>
/// Class ArtistsPostScanTask /// Class ArtistsPostScanTask.
/// </summary> /// </summary>
public class ArtistsPostScanTask : ILibraryPostScanTask public class ArtistsPostScanTask : ILibraryPostScanTask
{ {
/// <summary> /// <summary>
/// The _library manager /// The _library manager.
/// </summary> /// </summary>
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly ILogger _logger; private readonly ILogger _logger;
@ -23,6 +23,8 @@ namespace Emby.Server.Implementations.Library.Validators
/// Initializes a new instance of the <see cref="ArtistsPostScanTask" /> class. /// Initializes a new instance of the <see cref="ArtistsPostScanTask" /> class.
/// </summary> /// </summary>
/// <param name="libraryManager">The library manager.</param> /// <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) public ArtistsPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{ {
_libraryManager = libraryManager; _libraryManager = libraryManager;

View File

@ -12,17 +12,17 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Validators namespace Emby.Server.Implementations.Library.Validators
{ {
/// <summary> /// <summary>
/// Class ArtistsValidator /// Class ArtistsValidator.
/// </summary> /// </summary>
public class ArtistsValidator public class ArtistsValidator
{ {
/// <summary> /// <summary>
/// The _library manager /// The library manager.
/// </summary> /// </summary>
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
/// <summary> /// <summary>
/// The _logger /// The logger.
/// </summary> /// </summary>
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IItemRepository _itemRepo; private readonly IItemRepository _itemRepo;

View File

@ -7,6 +7,9 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Validators namespace Emby.Server.Implementations.Library.Validators
{ {
/// <summary>
/// Class GenresPostScanTask.
/// </summary>
public class GenresPostScanTask : ILibraryPostScanTask public class GenresPostScanTask : ILibraryPostScanTask
{ {
/// <summary> /// <summary>

View File

@ -7,19 +7,28 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Validators namespace Emby.Server.Implementations.Library.Validators
{ {
class GenresValidator /// <summary>
/// Class GenresValidator.
/// </summary>
public class GenresValidator
{ {
/// <summary> /// <summary>
/// The _library manager /// The library manager.
/// </summary> /// </summary>
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IItemRepository _itemRepo; private readonly IItemRepository _itemRepo;
/// <summary> /// <summary>
/// The _logger /// The logger.
/// </summary> /// </summary>
private readonly ILogger _logger; 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) public GenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{ {
_libraryManager = libraryManager; _libraryManager = libraryManager;

View File

@ -8,12 +8,12 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Validators namespace Emby.Server.Implementations.Library.Validators
{ {
/// <summary> /// <summary>
/// Class MusicGenresPostScanTask /// Class MusicGenresPostScanTask.
/// </summary> /// </summary>
public class MusicGenresPostScanTask : ILibraryPostScanTask public class MusicGenresPostScanTask : ILibraryPostScanTask
{ {
/// <summary> /// <summary>
/// The _library manager /// The library manager.
/// </summary> /// </summary>
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly ILogger _logger; private readonly ILogger _logger;

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