aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Api/Controllers
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Api/Controllers')
-rw-r--r--Jellyfin.Api/Controllers/FilterController.cs41
-rw-r--r--Jellyfin.Api/Controllers/ImageController.cs8
-rw-r--r--Jellyfin.Api/Controllers/ItemUpdateController.cs39
-rw-r--r--Jellyfin.Api/Controllers/PluginsController.cs1
-rw-r--r--Jellyfin.Api/Controllers/StartupController.cs5
5 files changed, 78 insertions, 16 deletions
diff --git a/Jellyfin.Api/Controllers/FilterController.cs b/Jellyfin.Api/Controllers/FilterController.cs
index cfc8be28ae..b458bd90f3 100644
--- a/Jellyfin.Api/Controllers/FilterController.cs
+++ b/Jellyfin.Api/Controllers/FilterController.cs
@@ -158,13 +158,43 @@ public class FilterController : BaseJellyfinApiController
IsSeries = isSeries
};
+ var streamLanguageQuery = new InternalItemsQuery(user)
+ {
+ // It's possible that different langauges are only available on alternative versions.
+ // To fetch them all, owned items are included.
+ IncludeOwnedItems = true,
+ IncludeItemTypes = includeItemTypes,
+ DtoOptions = new DtoOptions
+ {
+ Fields = Array.Empty<ItemFields>(),
+ EnableImages = false,
+ EnableUserData = false
+ },
+ IsAiring = isAiring,
+ IsMovie = isMovie,
+ IsSports = isSports,
+ IsKids = isKids,
+ IsNews = isNews,
+ IsSeries = isSeries
+ };
+
if ((recursive ?? true) || parentItem is UserView || parentItem is ICollectionFolder)
{
- genreQuery.AncestorIds = parentItem is null ? Array.Empty<Guid>() : new[] { parentItem.Id };
+ var ancestorIds = parentItem is null ? Array.Empty<Guid>() : new[] { parentItem.Id };
+ genreQuery.AncestorIds = ancestorIds;
+ streamLanguageQuery.AncestorIds = ancestorIds;
}
else
{
genreQuery.Parent = parentItem;
+ streamLanguageQuery.Parent = parentItem;
+ }
+
+ if ((includeItemTypes.Contains(BaseItemKind.Series) || includeItemTypes.Contains(BaseItemKind.Season))
+ && !includeItemTypes.Contains(BaseItemKind.Episode))
+ {
+ // streams are joined on epsiodes not shows or seasons
+ streamLanguageQuery.IncludeItemTypes = [.. includeItemTypes, BaseItemKind.Episode];
}
if (includeItemTypes.Length == 1
@@ -188,10 +218,13 @@ public class FilterController : BaseJellyfinApiController
}).ToArray();
}
- if (includeItemTypes.Contains(BaseItemKind.Movie) || includeItemTypes.Contains(BaseItemKind.Series))
+ if (includeItemTypes.Contains(BaseItemKind.Movie)
+ || includeItemTypes.Contains(BaseItemKind.Series)
+ || includeItemTypes.Contains(BaseItemKind.Season)
+ || includeItemTypes.Contains(BaseItemKind.Episode))
{
filters.AudioLanguages = _libraryManager
- .GetMediaStreamLanguages(MediaStreamType.Audio)
+ .GetMediaStreamLanguages(MediaStreamType.Audio, streamLanguageQuery)
.Select(language =>
{
var culture = _localization.FindLanguageInfo(language);
@@ -204,7 +237,7 @@ public class FilterController : BaseJellyfinApiController
.OrderBy(l => l.Name)
.ToArray();
filters.SubtitleLanguages = _libraryManager
- .GetMediaStreamLanguages(MediaStreamType.Subtitle)
+ .GetMediaStreamLanguages(MediaStreamType.Subtitle, streamLanguageQuery)
.Select(language =>
{
var culture = _localization.FindLanguageInfo(language);
diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs
index 52d8b4dad1..d492a2f5ba 100644
--- a/Jellyfin.Api/Controllers/ImageController.cs
+++ b/Jellyfin.Api/Controllers/ImageController.cs
@@ -125,7 +125,13 @@ public class ImageController : BaseJellyfinApiController
{
// Handle image/png; charset=utf-8
var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
- var userDataPath = Path.Combine(_serverConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username);
+ var userConfigurationDirectoryPath = _serverConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath;
+ var userDataPath = Path.Combine(userConfigurationDirectoryPath, user.Username);
+ if (!PathHelper.IsContainedIn(userConfigurationDirectoryPath, userDataPath))
+ {
+ return BadRequest("Invalid user.");
+ }
+
if (user.ProfileImage is not null)
{
await _userManager.ClearProfileImageAsync(user).ConfigureAwait(false);
diff --git a/Jellyfin.Api/Controllers/ItemUpdateController.cs b/Jellyfin.Api/Controllers/ItemUpdateController.cs
index e26264d292..36c82cf461 100644
--- a/Jellyfin.Api/Controllers/ItemUpdateController.cs
+++ b/Jellyfin.Api/Controllers/ItemUpdateController.cs
@@ -236,7 +236,7 @@ public class ItemUpdateController : BaseJellyfinApiController
return NoContent();
}
- private async Task UpdateItem(BaseItemDto request, BaseItem item)
+ internal async Task UpdateItem(BaseItemDto request, BaseItem item)
{
item.Name = request.Name;
item.ForcedSortName = request.ForcedSortName;
@@ -250,7 +250,11 @@ public class ItemUpdateController : BaseJellyfinApiController
item.IndexNumber = request.IndexNumber;
item.ParentIndexNumber = request.ParentIndexNumber;
item.Overview = request.Overview;
- item.Genres = request.Genres.Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
+
+ if (request.Genres is not null)
+ {
+ item.Genres = request.Genres.Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
+ }
if (item is Episode episode)
{
@@ -293,10 +297,20 @@ public class ItemUpdateController : BaseJellyfinApiController
item.CustomRating = request.CustomRating;
var currentTags = item.Tags;
- var newTags = request.Tags.Select(t => t.Trim()).Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
- var removedTags = currentTags.Except(newTags).ToList();
- var addedTags = newTags.Except(currentTags).ToList();
- item.Tags = newTags;
+ List<string> removedTags;
+ List<string> addedTags;
+ if (request.Tags is not null)
+ {
+ var newTags = request.Tags.Select(t => t.Trim()).Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
+ removedTags = currentTags.Except(newTags).ToList();
+ addedTags = newTags.Except(currentTags).ToList();
+ item.Tags = newTags;
+ }
+ else
+ {
+ removedTags = [];
+ addedTags = [];
+ }
if (item is Series rseries)
{
@@ -412,15 +426,18 @@ public class ItemUpdateController : BaseJellyfinApiController
item.RunTimeTicks = request.RunTimeTicks;
}
- foreach (var pair in request.ProviderIds.ToList())
+ if (request.ProviderIds is not null)
{
- if (string.IsNullOrEmpty(pair.Value))
+ foreach (var pair in request.ProviderIds.ToList())
{
- request.ProviderIds.Remove(pair.Key);
+ if (string.IsNullOrEmpty(pair.Value))
+ {
+ request.ProviderIds.Remove(pair.Key);
+ }
}
- }
- item.ProviderIds = request.ProviderIds;
+ item.ProviderIds = request.ProviderIds;
+ }
if (item is Video video)
{
diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs
index 2c84fde972..79b8b60cb7 100644
--- a/Jellyfin.Api/Controllers/PluginsController.cs
+++ b/Jellyfin.Api/Controllers/PluginsController.cs
@@ -6,6 +6,7 @@ using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
+using Jellyfin.Extensions;
using Jellyfin.Extensions.Json;
using MediaBrowser.Common.Api;
using MediaBrowser.Common.Plugins;
diff --git a/Jellyfin.Api/Controllers/StartupController.cs b/Jellyfin.Api/Controllers/StartupController.cs
index fa6d9efe36..47c8f21241 100644
--- a/Jellyfin.Api/Controllers/StartupController.cs
+++ b/Jellyfin.Api/Controllers/StartupController.cs
@@ -140,6 +140,11 @@ public class StartupController : BaseJellyfinApiController
return NotFound();
}
+ if (!string.IsNullOrEmpty(user.Password))
+ {
+ return Forbid();
+ }
+
if (string.IsNullOrWhiteSpace(startupUserDto.Password))
{
return BadRequest("Password must not be empty");