diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 8daaae4d94..42242c51a0 100644 --- a/CONTRIBUTORS.md +++ b/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) diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index e586205c32..bccb4107ff 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -1300,8 +1300,15 @@ namespace MediaBrowser.Controller.Entities /// /// Adds the children to list. /// - private void AddChildren(User user, bool includeLinkedChildren, Dictionary result, bool recursive, InternalItemsQuery query) + private void AddChildren(User user, bool includeLinkedChildren, Dictionary result, bool recursive, InternalItemsQuery query, HashSet visitedFolders = null) { + // Prevent infinite recursion of nested folders + visitedFolders ??= new HashSet(); + 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 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 children, User user, bool includeLinkedChildren, Dictionary result, bool recursive, InternalItemsQuery query, HashSet 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); } } }