Merge pull request #2070 from MediaBrowser/dev

Dev
This commit is contained in:
Luke 2016-08-18 13:27:58 -04:00 committed by GitHub
commit 98dd668751
13 changed files with 174 additions and 84 deletions

View File

@ -149,6 +149,24 @@ namespace MediaBrowser.Api.UserLibrary
item = user == null ? _libraryManager.RootFolder : user.RootFolder; item = user == null ? _libraryManager.RootFolder : user.RootFolder;
} }
if (!string.IsNullOrEmpty(request.Ids))
{
var query = GetItemsQuery(request, user);
var specificItems = _libraryManager.GetItemList(query).ToArray();
if (query.SortBy.Length == 0)
{
var ids = query.ItemIds.ToList();
// Try to preserve order
specificItems = specificItems.OrderBy(i => ids.IndexOf(i.Id.ToString("N"))).ToArray();
}
return new QueryResult<BaseItem>
{
Items = specificItems.ToArray(),
TotalRecordCount = specificItems.Length
};
}
// Default list type = children // Default list type = children
var folder = item as Folder; var folder = item as Folder;
@ -157,33 +175,11 @@ namespace MediaBrowser.Api.UserLibrary
folder = user == null ? _libraryManager.RootFolder : _libraryManager.GetUserRootFolder(); folder = user == null ? _libraryManager.RootFolder : _libraryManager.GetUserRootFolder();
} }
if (!string.IsNullOrEmpty(request.Ids)) if (request.Recursive || !string.IsNullOrEmpty(request.Ids) || user == null)
{
request.Recursive = true;
var query = GetItemsQuery(request, user);
var result = await folder.GetItems(query).ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(request.SortBy))
{
var ids = query.ItemIds.ToList();
// Try to preserve order
result.Items = result.Items.OrderBy(i => ids.IndexOf(i.Id.ToString("N"))).ToArray();
}
return result;
}
if (request.Recursive)
{ {
return await folder.GetItems(GetItemsQuery(request, user)).ConfigureAwait(false); return await folder.GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
} }
if (user == null)
{
return await folder.GetItems(GetItemsQuery(request, null)).ConfigureAwait(false);
}
var userRoot = item as UserRootFolder; var userRoot = item as UserRootFolder;
if (userRoot == null) if (userRoot == null)

View File

@ -903,6 +903,14 @@ namespace MediaBrowser.Controller.Entities
if (query.ItemIds.Length > 0) if (query.ItemIds.Length > 0)
{ {
var specificItems = query.ItemIds.Select(LibraryManager.GetItemById).Where(i => i != null).ToList(); var specificItems = query.ItemIds.Select(LibraryManager.GetItemById).Where(i => i != null).ToList();
if (query.SortBy.Length == 0)
{
var ids = query.ItemIds.ToList();
// Try to preserve order
specificItems = specificItems.OrderBy(i => ids.IndexOf(i.Id.ToString("N"))).ToList();
}
return Task.FromResult(PostFilterAndSort(specificItems, query, true, true)); return Task.FromResult(PostFilterAndSort(specificItems, query, true, true));
} }

View File

@ -170,6 +170,10 @@ namespace MediaBrowser.Controller.Persistence
QueryResult<Tuple<BaseItem, ItemCounts>> GetArtists(InternalItemsQuery query); QueryResult<Tuple<BaseItem, ItemCounts>> GetArtists(InternalItemsQuery query);
QueryResult<Tuple<BaseItem, ItemCounts>> GetAlbumArtists(InternalItemsQuery query); QueryResult<Tuple<BaseItem, ItemCounts>> GetAlbumArtists(InternalItemsQuery query);
QueryResult<Tuple<BaseItem, ItemCounts>> GetAllArtists(InternalItemsQuery query); QueryResult<Tuple<BaseItem, ItemCounts>> GetAllArtists(InternalItemsQuery query);
List<string> GetStudioNames();
List<string> GetAllArtistNames();
} }
} }

View File

@ -9,6 +9,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Xml; using System.Xml;
using CommonIO; using CommonIO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.MediaInfo;
@ -793,7 +794,7 @@ namespace MediaBrowser.MediaEncoding.Probing
if (!string.IsNullOrWhiteSpace(artists)) if (!string.IsNullOrWhiteSpace(artists))
{ {
audio.Artists = SplitArtists(artists, new[] { '/', ';' }, false) audio.Artists = SplitArtists(artists, new[] { '/', ';' }, false)
.Distinct(StringComparer.OrdinalIgnoreCase) .DistinctNames()
.ToList(); .ToList();
} }
else else
@ -806,7 +807,7 @@ namespace MediaBrowser.MediaEncoding.Probing
else else
{ {
audio.Artists = SplitArtists(artist, _nameDelimiters, true) audio.Artists = SplitArtists(artist, _nameDelimiters, true)
.Distinct(StringComparer.OrdinalIgnoreCase) .DistinctNames()
.ToList(); .ToList();
} }
} }
@ -828,7 +829,7 @@ namespace MediaBrowser.MediaEncoding.Probing
else else
{ {
audio.AlbumArtists = SplitArtists(albumArtist, _nameDelimiters, true) audio.AlbumArtists = SplitArtists(albumArtist, _nameDelimiters, true)
.Distinct(StringComparer.OrdinalIgnoreCase) .DistinctNames()
.ToList(); .ToList();
} }

View File

@ -331,6 +331,46 @@ namespace MediaBrowser.Server.Implementations.HttpServer
return url; return url;
} }
private string NormalizeConfiguredLocalAddress(string address)
{
var index = address.Trim('/').IndexOf('/');
if (index != -1)
{
address = address.Substring(index + 1);
}
return address.Trim('/');
}
private bool ValidateHost(Uri url)
{
var hosts = _config
.Configuration
.LocalNetworkAddresses
.Select(NormalizeConfiguredLocalAddress)
.ToList();
if (hosts.Count == 0)
{
return true;
}
var host = url.Host ?? string.Empty;
_logger.Debug("Validating host {0}", host);
if (_networkManager.IsInPrivateAddressSpace(host))
{
hosts.Add("localhost");
hosts.Add("127.0.0.1");
return hosts.Any(i => host.IndexOf(i, StringComparison.OrdinalIgnoreCase) != -1);
}
return true;
}
/// <summary> /// <summary>
/// Overridable method that can be used to implement a custom hnandler /// Overridable method that can be used to implement a custom hnandler
/// </summary> /// </summary>
@ -350,6 +390,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer
return ; return ;
} }
if (!ValidateHost(url))
{
httpRes.StatusCode = 400;
httpRes.ContentType = "text/plain";
httpRes.Write("Invalid host");
httpRes.Close();
return;
}
var operationName = httpReq.OperationName; var operationName = httpReq.OperationName;
var localPath = url.LocalPath; var localPath = url.LocalPath;

View File

@ -1465,7 +1465,12 @@ namespace MediaBrowser.Server.Implementations.Library
private void AddUserToQuery(InternalItemsQuery query, User user) private void AddUserToQuery(InternalItemsQuery query, User user)
{ {
if (query.AncestorIds.Length == 0 && !query.ParentId.HasValue && query.ChannelIds.Length == 0 && query.TopParentIds.Length == 0 && string.IsNullOrWhiteSpace(query.AncestorWithPresentationUniqueKey)) if (query.AncestorIds.Length == 0 &&
!query.ParentId.HasValue &&
query.ChannelIds.Length == 0 &&
query.TopParentIds.Length == 0 &&
string.IsNullOrWhiteSpace(query.AncestorWithPresentationUniqueKey)
&& query.ItemIds.Length == 0)
{ {
var userViews = _userviewManager().GetUserViews(new UserViewQuery var userViews = _userviewManager().GetUserViews(new UserViewQuery
{ {

View File

@ -50,7 +50,8 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
{ {
return new CollectionFolder return new CollectionFolder
{ {
CollectionType = GetCollectionType(args) CollectionType = GetCollectionType(args),
PhysicalLocationsList = args.PhysicalLocations.ToList()
}; };
} }
} }

View File

@ -3,6 +3,7 @@ using MediaBrowser.Model.Logging;
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Controller.Persistence;
namespace MediaBrowser.Server.Implementations.Library.Validators namespace MediaBrowser.Server.Implementations.Library.Validators
{ {
@ -16,15 +17,17 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// </summary> /// </summary>
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IItemRepository _itemRepo;
/// <summary> /// <summary>
/// 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>
public ArtistsPostScanTask(ILibraryManager libraryManager, ILogger logger) public ArtistsPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{ {
_libraryManager = libraryManager; _libraryManager = libraryManager;
_logger = logger; _logger = logger;
_itemRepo = itemRepo;
} }
/// <summary> /// <summary>
@ -35,7 +38,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// <returns>Task.</returns> /// <returns>Task.</returns>
public Task Run(IProgress<double> progress, CancellationToken cancellationToken) public Task Run(IProgress<double> progress, CancellationToken cancellationToken)
{ {
return new ArtistsValidator(_libraryManager, _logger).Run(progress, cancellationToken); return new ArtistsValidator(_libraryManager, _logger, _itemRepo).Run(progress, cancellationToken);
} }
} }
} }

View File

@ -7,6 +7,7 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Persistence;
namespace MediaBrowser.Server.Implementations.Library.Validators namespace MediaBrowser.Server.Implementations.Library.Validators
{ {
@ -24,16 +25,18 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// The _logger /// The _logger
/// </summary> /// </summary>
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IItemRepository _itemRepo;
/// <summary> /// <summary>
/// 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="logger">The logger.</param>
public ArtistsValidator(ILibraryManager libraryManager, ILogger logger) public ArtistsValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{ {
_libraryManager = libraryManager; _libraryManager = libraryManager;
_logger = logger; _logger = logger;
_itemRepo = itemRepo;
} }
/// <summary> /// <summary>
@ -44,18 +47,17 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// <returns>Task.</returns> /// <returns>Task.</returns>
public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
{ {
var items = _libraryManager.GetAllArtists(new InternalItemsQuery()) var names = _itemRepo.GetAllArtistNames();
.Items
.Select(i => i.Item1)
.ToList();
var numComplete = 0; var numComplete = 0;
var count = items.Count; var count = names.Count;
foreach (var item in items) foreach (var name in names)
{ {
try try
{ {
var item = _libraryManager.GetArtist(name);
await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
} }
catch (OperationCanceledException) catch (OperationCanceledException)
@ -65,7 +67,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.ErrorException("Error refreshing {0}", ex, item.Name); _logger.ErrorException("Error refreshing {0}", ex, name);
} }
numComplete++; numComplete++;

View File

@ -3,6 +3,7 @@ using MediaBrowser.Model.Logging;
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Controller.Persistence;
namespace MediaBrowser.Server.Implementations.Library.Validators namespace MediaBrowser.Server.Implementations.Library.Validators
{ {
@ -17,15 +18,17 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IItemRepository _itemRepo;
/// <summary> /// <summary>
/// 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>
public StudiosPostScanTask(ILibraryManager libraryManager, ILogger logger) public StudiosPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{ {
_libraryManager = libraryManager; _libraryManager = libraryManager;
_logger = logger; _logger = logger;
_itemRepo = itemRepo;
} }
/// <summary> /// <summary>
@ -36,7 +39,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// <returns>Task.</returns> /// <returns>Task.</returns>
public Task Run(IProgress<double> progress, CancellationToken cancellationToken) public Task Run(IProgress<double> progress, CancellationToken cancellationToken)
{ {
return new StudiosValidator(_libraryManager, _logger).Run(progress, cancellationToken); return new StudiosValidator(_libraryManager, _logger, _itemRepo).Run(progress, cancellationToken);
} }
} }
} }

View File

@ -5,6 +5,7 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Persistence;
namespace MediaBrowser.Server.Implementations.Library.Validators namespace MediaBrowser.Server.Implementations.Library.Validators
{ {
@ -15,15 +16,17 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// </summary> /// </summary>
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IItemRepository _itemRepo;
/// <summary> /// <summary>
/// The _logger /// The _logger
/// </summary> /// </summary>
private readonly ILogger _logger; private readonly ILogger _logger;
public StudiosValidator(ILibraryManager libraryManager, ILogger logger) public StudiosValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{ {
_libraryManager = libraryManager; _libraryManager = libraryManager;
_logger = logger; _logger = logger;
_itemRepo = itemRepo;
} }
/// <summary> /// <summary>
@ -34,18 +37,17 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// <returns>Task.</returns> /// <returns>Task.</returns>
public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
{ {
var items = _libraryManager.GetStudios(new InternalItemsQuery()) var names = _itemRepo.GetStudioNames();
.Items
.Select(i => i.Item1)
.ToList();
var numComplete = 0; var numComplete = 0;
var count = items.Count; var count = names.Count;
foreach (var item in items) foreach (var name in names)
{ {
try try
{ {
var item = _libraryManager.GetStudio(name);
await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
} }
catch (OperationCanceledException) catch (OperationCanceledException)
@ -55,7 +57,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.ErrorException("Error refreshing {0}", ex, item.Name); _logger.ErrorException("Error refreshing {0}", ex, name);
} }
numComplete++; numComplete++;

View File

@ -3152,17 +3152,17 @@ namespace MediaBrowser.Server.Implementations.Persistence
} }
if (query.ItemIds.Length > 0) if (query.ItemIds.Length > 0)
{ {
var excludeIds = new List<string>(); var includeIds = new List<string>();
var index = 0; var index = 0;
foreach (var id in query.ItemIds) foreach (var id in query.ItemIds)
{ {
excludeIds.Add("Guid = @IncludeId" + index); includeIds.Add("Guid = @IncludeId" + index);
cmd.Parameters.Add(cmd, "@IncludeId" + index, DbType.Guid).Value = new Guid(id); cmd.Parameters.Add(cmd, "@IncludeId" + index, DbType.Guid).Value = new Guid(id);
index++; index++;
} }
whereClauses.Add(string.Join(" OR ", excludeIds.ToArray())); whereClauses.Add(string.Join(" OR ", includeIds.ToArray()));
} }
if (query.ExcludeItemIds.Length > 0) if (query.ExcludeItemIds.Length > 0)
{ {
@ -3880,6 +3880,52 @@ namespace MediaBrowser.Server.Implementations.Persistence
return GetItemValues(query, new[] { 2 }, typeof(MusicGenre).FullName); return GetItemValues(query, new[] { 2 }, typeof(MusicGenre).FullName);
} }
public List<string> GetStudioNames()
{
return GetItemValueNames(new[] { 3 });
}
public List<string> GetAllArtistNames()
{
return GetItemValueNames(new[] { 0, 1 });
}
private List<string> GetItemValueNames(int[] itemValueTypes)
{
CheckDisposed();
var now = DateTime.UtcNow;
var typeClause = itemValueTypes.Length == 1 ?
("Type=" + itemValueTypes[0].ToString(CultureInfo.InvariantCulture)) :
("Type in (" + string.Join(",", itemValueTypes.Select(i => i.ToString(CultureInfo.InvariantCulture)).ToArray()) + ")");
var list = new List<string>();
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "Select Value From ItemValues where " + typeClause + " Group By CleanValue";
var commandBehavior = CommandBehavior.SequentialAccess | CommandBehavior.SingleResult;
using (var reader = cmd.ExecuteReader(commandBehavior))
{
LogQueryTime("GetItemValueNames", cmd, now);
while (reader.Read())
{
if (!reader.IsDBNull(0))
{
list.Add(reader.GetString(0));
}
}
}
}
return list;
}
private QueryResult<Tuple<BaseItem, ItemCounts>> GetItemValues(InternalItemsQuery query, int[] itemValueTypes, string returnType) private QueryResult<Tuple<BaseItem, ItemCounts>> GetItemValues(InternalItemsQuery query, int[] itemValueTypes, string returnType)
{ {
if (query == null) if (query == null)

View File

@ -821,42 +821,11 @@ namespace MediaBrowser.Server.Startup.Common
private string CertificatePath { get; set; } private string CertificatePath { get; set; }
private string NormalizeConfiguredLocalAddress(string address)
{
var index = address.Trim('/').IndexOf('/');
if (index != -1)
{
address = address.Substring(index + 1);
}
return address.Trim('/');
}
private IEnumerable<string> GetUrlPrefixes() private IEnumerable<string> GetUrlPrefixes()
{ {
var hosts = ServerConfigurationManager var hosts = new List<string>();
.Configuration
.LocalNetworkAddresses
.Select(NormalizeConfiguredLocalAddress)
.ToList();
if (hosts.Count == 0) hosts.Add("+");
{
hosts.Add("+");
}
if (!hosts.Contains("+", StringComparer.OrdinalIgnoreCase))
{
if (!hosts.Contains("localhost", StringComparer.OrdinalIgnoreCase))
{
hosts.Add("localhost");
}
if (!hosts.Contains("127.0.0.1", StringComparer.OrdinalIgnoreCase))
{
hosts.Add("127.0.0.1");
}
}
return hosts.SelectMany(i => return hosts.SelectMany(i =>
{ {