浏览代码

Fix recursive children lookup of folders (#8678)

Fixes https://github.com/jellyfin/jellyfin/issues/6193
Fixes https://github.com/jellyfin/jellyfin/issues/7226
Egor Bakanov 2 年之前
父节点
当前提交
46e9f5ad2e
共有 2 个文件被更改,包括 27 次插入28 次删除
  1. 1 0
      CONTRIBUTORS.md
  2. 26 28
      MediaBrowser.Controller/Entities/Folder.cs

+ 1 - 0
CONTRIBUTORS.md

@@ -37,6 +37,7 @@
  - [DMouse10462](https://github.com/DMouse10462)
  - [DrPandemic](https://github.com/DrPandemic)
  - [eglia](https://github.com/eglia)
+ - [EgorBakanov](https://github.com/EgorBakanov)
  - [EraYaN](https://github.com/EraYaN)
  - [escabe](https://github.com/escabe)
  - [excelite](https://github.com/excelite)

+ 26 - 28
MediaBrowser.Controller/Entities/Folder.cs

@@ -1300,8 +1300,15 @@ namespace MediaBrowser.Controller.Entities
         /// <summary>
         /// Adds the children to list.
         /// </summary>
-        private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool recursive, InternalItemsQuery query)
+        private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool recursive, InternalItemsQuery query, HashSet<Folder> visitedFolders = null)
         {
+            // Prevent infinite recursion of nested folders
+            visitedFolders ??= new HashSet<Folder>();
+            if (!visitedFolders.Add(this))
+            {
+                return;
+            }
+
             // If Query.AlbumFolders is set, then enforce the format as per the db in that it permits sub-folders in music albums.
             IEnumerable<BaseItem> children = null;
             if ((query?.DisplayAlbumFolders ?? false) && (this is MusicAlbum))
@@ -1316,42 +1323,33 @@ namespace MediaBrowser.Controller.Entities
                 children = GetEligibleChildrenForRecursiveChildren(user);
             }
 
-            foreach (var child in children)
+            AddChildrenFromCollection(children, user, includeLinkedChildren, result, recursive, query, visitedFolders);
+
+            if (includeLinkedChildren)
             {
-                bool? isVisibleToUser = null;
+                AddChildrenFromCollection(GetLinkedChildren(user), user, includeLinkedChildren, result, recursive, query, visitedFolders);
+            }
+        }
 
-                if (query is null || UserViewBuilder.FilterItem(child, query))
+        private void AddChildrenFromCollection(IEnumerable<BaseItem> children, User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool recursive, InternalItemsQuery query, HashSet<Folder> visitedFolders)
+        {
+            foreach (var child in children)
+            {
+                if (!child.IsVisible(user))
                 {
-                    isVisibleToUser = child.IsVisible(user);
-
-                    if (isVisibleToUser.Value)
-                    {
-                        result[child.Id] = child;
-                    }
+                    continue;
                 }
 
-                if (isVisibleToUser ?? child.IsVisible(user))
+                if (query is null || UserViewBuilder.FilterItem(child, query))
                 {
-                    if (recursive && child.IsFolder)
-                    {
-                        var folder = (Folder)child;
-
-                        folder.AddChildren(user, includeLinkedChildren, result, true, query);
-                    }
+                    result[child.Id] = child;
                 }
-            }
 
-            if (includeLinkedChildren)
-            {
-                foreach (var child in GetLinkedChildren(user))
+                if (recursive && child.IsFolder)
                 {
-                    if (query is null || UserViewBuilder.FilterItem(child, query))
-                    {
-                        if (child.IsVisible(user))
-                        {
-                            result[child.Id] = child;
-                        }
-                    }
+                    var folder = (Folder)child;
+
+                    folder.AddChildren(user, includeLinkedChildren, result, true, query, visitedFolders);
                 }
             }
         }