diff options
| author | Shadowghost <Shadowghost@users.noreply.github.com> | 2024-05-17 13:51:53 -0400 |
|---|---|---|
| committer | Joshua M. Boniface <joshua@boniface.me> | 2024-05-17 13:51:53 -0400 |
| commit | a2eb4c5e6010dffc38560efa650d94c6c85c1cdd (patch) | |
| tree | 2c79fc4804ad13dc0db4b715d1e1d89dda8b1e9c /MediaBrowser.Providers/Playlists | |
| parent | 0c159cd8b656c36826bab7333e9e5c04277cc592 (diff) | |
Backport pull request #11680 from jellyfin/release-10.9.z
Secure local playlist path handling
Original-merge: 832e27a8fb0e51927cfc80f7f92a28601da29084
Merged-by: joshuaboniface <joshua@boniface.me>
Backported-by: Joshua M. Boniface <joshua@boniface.me>
Diffstat (limited to 'MediaBrowser.Providers/Playlists')
| -rw-r--r-- | MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs | 107 |
1 files changed, 61 insertions, 46 deletions
diff --git a/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs b/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs index bff8fdac5..4eb75b82f 100644 --- a/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs +++ b/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs @@ -8,11 +8,13 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Data.Enums; using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.IO; using Microsoft.Extensions.Logging; using PlaylistsNET.Content; @@ -24,11 +26,16 @@ namespace MediaBrowser.Providers.Playlists IPreRefreshProvider, IHasItemChangeMonitor { + private readonly IFileSystem _fileSystem; + private readonly ILibraryManager _libraryManager; private readonly ILogger<PlaylistItemsProvider> _logger; + private readonly CollectionType[] _ignoredCollections = [CollectionType.livetv, CollectionType.boxsets, CollectionType.playlists]; - public PlaylistItemsProvider(ILogger<PlaylistItemsProvider> logger) + public PlaylistItemsProvider(ILogger<PlaylistItemsProvider> logger, ILibraryManager libraryManager, IFileSystem fileSystem) { _logger = logger; + _libraryManager = libraryManager; + _fileSystem = fileSystem; } public string Name => "Playlist Reader"; @@ -59,109 +66,117 @@ namespace MediaBrowser.Providers.Playlists private IEnumerable<LinkedChild> GetItems(string path, string extension) { + var libraryRoots = _libraryManager.GetUserRootFolder().Children + .OfType<CollectionFolder>() + .Where(f => f.CollectionType.HasValue && !_ignoredCollections.Contains(f.CollectionType.Value)) + .SelectMany(f => f.PhysicalLocations) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); + using (var stream = File.OpenRead(path)) { if (string.Equals(".wpl", extension, StringComparison.OrdinalIgnoreCase)) { - return GetWplItems(stream, path); + return GetWplItems(stream, path, libraryRoots); } if (string.Equals(".zpl", extension, StringComparison.OrdinalIgnoreCase)) { - return GetZplItems(stream, path); + return GetZplItems(stream, path, libraryRoots); } if (string.Equals(".m3u", extension, StringComparison.OrdinalIgnoreCase)) { - return GetM3uItems(stream, path); + return GetM3uItems(stream, path, libraryRoots); } if (string.Equals(".m3u8", extension, StringComparison.OrdinalIgnoreCase)) { - return GetM3u8Items(stream, path); + return GetM3uItems(stream, path, libraryRoots); } if (string.Equals(".pls", extension, StringComparison.OrdinalIgnoreCase)) { - return GetPlsItems(stream, path); + return GetPlsItems(stream, path, libraryRoots); } } return Enumerable.Empty<LinkedChild>(); } - private IEnumerable<LinkedChild> GetPlsItems(Stream stream, string path) + private IEnumerable<LinkedChild> GetPlsItems(Stream stream, string playlistPath, List<string> libraryRoots) { var content = new PlsContent(); var playlist = content.GetFromStream(stream); - return playlist.PlaylistEntries.Select(i => new LinkedChild - { - Path = GetPlaylistItemPath(i.Path, path), - Type = LinkedChildType.Manual - }); + return playlist.PlaylistEntries + .Select(i => GetLinkedChild(i.Path, playlistPath, libraryRoots)) + .Where(i => i is not null); } - private IEnumerable<LinkedChild> GetM3u8Items(Stream stream, string path) + private IEnumerable<LinkedChild> GetM3uItems(Stream stream, string playlistPath, List<string> libraryRoots) { var content = new M3uContent(); var playlist = content.GetFromStream(stream); - return playlist.PlaylistEntries.Select(i => new LinkedChild - { - Path = GetPlaylistItemPath(i.Path, path), - Type = LinkedChildType.Manual - }); + return playlist.PlaylistEntries + .Select(i => GetLinkedChild(i.Path, playlistPath, libraryRoots)) + .Where(i => i is not null); } - private IEnumerable<LinkedChild> GetM3uItems(Stream stream, string path) + private IEnumerable<LinkedChild> GetZplItems(Stream stream, string playlistPath, List<string> libraryRoots) { - var content = new M3uContent(); + var content = new ZplContent(); var playlist = content.GetFromStream(stream); - return playlist.PlaylistEntries.Select(i => new LinkedChild - { - Path = GetPlaylistItemPath(i.Path, path), - Type = LinkedChildType.Manual - }); + return playlist.PlaylistEntries + .Select(i => GetLinkedChild(i.Path, playlistPath, libraryRoots)) + .Where(i => i is not null); } - private IEnumerable<LinkedChild> GetZplItems(Stream stream, string path) + private IEnumerable<LinkedChild> GetWplItems(Stream stream, string playlistPath, List<string> libraryRoots) { - var content = new ZplContent(); + var content = new WplContent(); var playlist = content.GetFromStream(stream); - return playlist.PlaylistEntries.Select(i => new LinkedChild - { - Path = GetPlaylistItemPath(i.Path, path), - Type = LinkedChildType.Manual - }); + return playlist.PlaylistEntries + .Select(i => GetLinkedChild(i.Path, playlistPath, libraryRoots)) + .Where(i => i is not null); } - private IEnumerable<LinkedChild> GetWplItems(Stream stream, string path) + private LinkedChild GetLinkedChild(string itemPath, string playlistPath, List<string> libraryRoots) { - var content = new WplContent(); - var playlist = content.GetFromStream(stream); - - return playlist.PlaylistEntries.Select(i => new LinkedChild + if (TryGetPlaylistItemPath(itemPath, playlistPath, libraryRoots, out var parsedPath)) { - Path = GetPlaylistItemPath(i.Path, path), - Type = LinkedChildType.Manual - }); + return new LinkedChild + { + Path = parsedPath, + Type = LinkedChildType.Manual + }; + } + + return null; } - private string GetPlaylistItemPath(string itemPath, string containingPlaylistFolder) + private bool TryGetPlaylistItemPath(string itemPath, string playlistPath, List<string> libraryPaths, out string path) { - if (!File.Exists(itemPath)) + path = null; + string pathToCheck = _fileSystem.MakeAbsolutePath(Path.GetDirectoryName(playlistPath), itemPath); + if (!File.Exists(pathToCheck)) { - var path = Path.Combine(Path.GetDirectoryName(containingPlaylistFolder), itemPath); - if (File.Exists(path)) + return false; + } + + foreach (var libraryPath in libraryPaths) + { + if (pathToCheck.StartsWith(libraryPath, StringComparison.OrdinalIgnoreCase)) { - return path; + path = pathToCheck; + return true; } } - return itemPath; + return false; } public bool HasChanged(BaseItem item, IDirectoryService directoryService) |
