Jelajahi Sumber

Merge pull request #2070 from MediaBrowser/dev

Dev
Luke 8 tahun lalu
induk
melakukan
98dd668751

+ 15 - 19
MediaBrowser.Api/UserLibrary/ItemsService.cs

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

+ 8 - 0
MediaBrowser.Controller/Entities/Folder.cs

@@ -903,6 +903,14 @@ namespace MediaBrowser.Controller.Entities
             if (query.ItemIds.Length > 0)
             {
                 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));
             }
 

+ 4 - 0
MediaBrowser.Controller/Persistence/IItemRepository.cs

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

+ 4 - 3
MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs

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

+ 50 - 0
MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs

@@ -331,6 +331,46 @@ namespace MediaBrowser.Server.Implementations.HttpServer
             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>
         /// Overridable method that can be used to implement a custom hnandler
         /// </summary>
@@ -350,6 +390,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer
                 return ;
             }
 
+            if (!ValidateHost(url))
+            {
+                httpRes.StatusCode = 400;
+                httpRes.ContentType = "text/plain";
+                httpRes.Write("Invalid host");
+
+                httpRes.Close();
+                return;
+            }
+
             var operationName = httpReq.OperationName;
             var localPath = url.LocalPath;
 

+ 6 - 1
MediaBrowser.Server.Implementations/Library/LibraryManager.cs

@@ -1465,7 +1465,12 @@ namespace MediaBrowser.Server.Implementations.Library
 
         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
                 {

+ 2 - 1
MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs

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

+ 5 - 2
MediaBrowser.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs

@@ -3,6 +3,7 @@ using MediaBrowser.Model.Logging;
 using System;
 using System.Threading;
 using System.Threading.Tasks;
+using MediaBrowser.Controller.Persistence;
 
 namespace MediaBrowser.Server.Implementations.Library.Validators
 {
@@ -16,15 +17,17 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
         /// </summary>
         private readonly ILibraryManager _libraryManager;
         private readonly ILogger _logger;
+        private readonly IItemRepository _itemRepo;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ArtistsPostScanTask" /> class.
         /// </summary>
         /// <param name="libraryManager">The library manager.</param>
-        public ArtistsPostScanTask(ILibraryManager libraryManager, ILogger logger)
+        public ArtistsPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
         {
             _libraryManager = libraryManager;
             _logger = logger;
+            _itemRepo = itemRepo;
         }
 
         /// <summary>
@@ -35,7 +38,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
         /// <returns>Task.</returns>
         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);
         }
     }
 }

+ 10 - 8
MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs

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

+ 5 - 2
MediaBrowser.Server.Implementations/Library/Validators/StudiosPostScanTask.cs

@@ -3,6 +3,7 @@ using MediaBrowser.Model.Logging;
 using System;
 using System.Threading;
 using System.Threading.Tasks;
+using MediaBrowser.Controller.Persistence;
 
 namespace MediaBrowser.Server.Implementations.Library.Validators
 {
@@ -17,15 +18,17 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
         private readonly ILibraryManager _libraryManager;
 
         private readonly ILogger _logger;
+        private readonly IItemRepository _itemRepo;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ArtistsPostScanTask" /> class.
         /// </summary>
         /// <param name="libraryManager">The library manager.</param>
-        public StudiosPostScanTask(ILibraryManager libraryManager, ILogger logger)
+        public StudiosPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
         {
             _libraryManager = libraryManager;
             _logger = logger;
+            _itemRepo = itemRepo;
         }
 
         /// <summary>
@@ -36,7 +39,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
         /// <returns>Task.</returns>
         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);
         }
     }
 }

+ 10 - 8
MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs

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

+ 49 - 3
MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs

@@ -3152,17 +3152,17 @@ namespace MediaBrowser.Server.Implementations.Persistence
             }
             if (query.ItemIds.Length > 0)
             {
-                var excludeIds = new List<string>();
+                var includeIds = new List<string>();
 
                 var index = 0;
                 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);
                     index++;
                 }
 
-                whereClauses.Add(string.Join(" OR ", excludeIds.ToArray()));
+                whereClauses.Add(string.Join(" OR ", includeIds.ToArray()));
             }
             if (query.ExcludeItemIds.Length > 0)
             {
@@ -3880,6 +3880,52 @@ namespace MediaBrowser.Server.Implementations.Persistence
             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)
         {
             if (query == null)

+ 2 - 33
MediaBrowser.Server.Startup.Common/ApplicationHost.cs

@@ -821,42 +821,11 @@ namespace MediaBrowser.Server.Startup.Common
 
         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()
         {
-            var hosts = ServerConfigurationManager
-                .Configuration
-                .LocalNetworkAddresses
-                .Select(NormalizeConfiguredLocalAddress)
-                .ToList();
+            var hosts = new List<string>();
 
-            if (hosts.Count == 0)
-            {
-                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");
-                }
-            }
+            hosts.Add("+");
 
             return hosts.SelectMany(i =>
             {