diff options
8 files changed, 42 insertions, 34 deletions
diff --git a/.github/workflows/ci-codeql-analysis.yml b/.github/workflows/ci-codeql-analysis.yml index 55fa65ee2..96c06019b 100644 --- a/.github/workflows/ci-codeql-analysis.yml +++ b/.github/workflows/ci-codeql-analysis.yml @@ -27,11 +27,11 @@ jobs: dotnet-version: '8.0.x' - name: Initialize CodeQL - uses: github/codeql-action/init@8f596b4ae3cb3c588a5c46780b86dd53fef16c52 # v3.25.2 + uses: github/codeql-action/init@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: languages: ${{ matrix.language }} queries: +security-extended - name: Autobuild - uses: github/codeql-action/autobuild@8f596b4ae3cb3c588a5c46780b86dd53fef16c52 # v3.25.2 + uses: github/codeql-action/autobuild@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@8f596b4ae3cb3c588a5c46780b86dd53fef16c52 # v3.25.2 + uses: github/codeql-action/analyze@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 diff --git a/Emby.Server.Implementations/Localization/Core/fr-CA.json b/Emby.Server.Implementations/Localization/Core/fr-CA.json index b816738c2..73bef3af7 100644 --- a/Emby.Server.Implementations/Localization/Core/fr-CA.json +++ b/Emby.Server.Implementations/Localization/Core/fr-CA.json @@ -126,5 +126,7 @@ "External": "Externe", "HearingImpaired": "Malentendants", "TaskRefreshTrickplayImages": "Générer des images Trickplay", - "TaskRefreshTrickplayImagesDescription": "Crée des aperçus Trickplay pour les vidéos dans les médiathèques activées." + "TaskRefreshTrickplayImagesDescription": "Crée des aperçus Trickplay pour les vidéos dans les médiathèques activées.", + "TaskCleanCollectionsAndPlaylists": "Nettoyer les collections et les listes de lecture", + "TaskCleanCollectionsAndPlaylistsDescription": "Supprimer les liens inexistants des collections et des listes de lecture" } diff --git a/Jellyfin.Api/Controllers/DashboardController.cs b/Jellyfin.Api/Controllers/DashboardController.cs index 076084c7a..ee912a9be 100644 --- a/Jellyfin.Api/Controllers/DashboardController.cs +++ b/Jellyfin.Api/Controllers/DashboardController.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Net.Mime; using Jellyfin.Api.Attributes; using Jellyfin.Api.Models; +using MediaBrowser.Common.Api; using MediaBrowser.Common.Plugins; using MediaBrowser.Model.Net; using MediaBrowser.Model.Plugins; @@ -45,9 +46,9 @@ public class DashboardController : BaseJellyfinApiController /// <response code="404">Server still loading.</response> /// <returns>An <see cref="IEnumerable{ConfigurationPageInfo}"/> with infos about the plugins.</returns> [HttpGet("web/ConfigurationPages")] + [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - [Authorize] public ActionResult<IEnumerable<ConfigurationPageInfo>> GetConfigurationPages( [FromQuery] bool? enableInMainMenu) { diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 24edd7958..68602c80d 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1481,7 +1481,7 @@ public class DynamicHlsController : BaseJellyfinApiController if (currentTranscodingIndex.HasValue) { - DeleteLastFile(playlistPath, segmentExtension, 0); + await DeleteLastFile(playlistPath, segmentExtension, 0).ConfigureAwait(false); } streamingRequest.StartTimeTicks = streamingRequest.CurrentRuntimeTicks; @@ -2009,17 +2009,19 @@ public class DynamicHlsController : BaseJellyfinApiController } } - private void DeleteLastFile(string playlistPath, string segmentExtension, int retryCount) + private Task DeleteLastFile(string playlistPath, string segmentExtension, int retryCount) { var file = GetLastTranscodingFile(playlistPath, segmentExtension, _fileSystem); - if (file is not null) + if (file is null) { - DeleteFile(file.FullName, retryCount); + return Task.CompletedTask; } + + return DeleteFile(file.FullName, retryCount); } - private void DeleteFile(string path, int retryCount) + private async Task DeleteFile(string path, int retryCount) { if (retryCount >= 5) { @@ -2036,9 +2038,8 @@ public class DynamicHlsController : BaseJellyfinApiController { _logger.LogError(ex, "Error deleting partial stream file(s) {Path}", path); - var task = Task.Delay(100); - task.Wait(); - DeleteFile(path, retryCount + 1); + await Task.Delay(100).ConfigureAwait(false); + await DeleteFile(path, retryCount + 1).ConfigureAwait(false); } catch (Exception ex) { diff --git a/Jellyfin.Api/Controllers/PackageController.cs b/Jellyfin.Api/Controllers/PackageController.cs index c5e940108..274e94ee6 100644 --- a/Jellyfin.Api/Controllers/PackageController.cs +++ b/Jellyfin.Api/Controllers/PackageController.cs @@ -18,7 +18,7 @@ namespace Jellyfin.Api.Controllers; /// Package Controller. /// </summary> [Route("")] -[Authorize] +[Authorize(Policy = Policies.RequiresElevation)] public class PackageController : BaseJellyfinApiController { private readonly IInstallationManager _installationManager; @@ -90,7 +90,6 @@ public class PackageController : BaseJellyfinApiController [HttpPost("Packages/Installed/{name}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - [Authorize(Policy = Policies.RequiresElevation)] public async Task<ActionResult> InstallPackage( [FromRoute, Required] string name, [FromQuery] Guid? assemblyGuid, @@ -128,7 +127,6 @@ public class PackageController : BaseJellyfinApiController /// <response code="204">Installation cancelled.</response> /// <returns>A <see cref="NoContentResult"/> on successfully cancelling a package installation.</returns> [HttpDelete("Packages/Installing/{packageId}")] - [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult CancelPackageInstallation( [FromRoute, Required] Guid packageId) @@ -156,7 +154,6 @@ public class PackageController : BaseJellyfinApiController /// <response code="204">Package repositories saved.</response> /// <returns>A <see cref="NoContentResult"/>.</returns> [HttpPost("Repositories")] - [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult SetRepositories([FromBody, Required] RepositoryInfo[] repositoryInfos) { diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index f63e63927..6abd7a23e 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -22,7 +22,7 @@ namespace Jellyfin.Api.Controllers; /// <summary> /// Plugins controller. /// </summary> -[Authorize] +[Authorize(Policy = Policies.RequiresElevation)] public class PluginsController : BaseJellyfinApiController { private readonly IInstallationManager _installationManager; @@ -66,7 +66,6 @@ public class PluginsController : BaseJellyfinApiController /// <response code="404">Plugin not found.</response> /// <returns>An <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the plugin could not be found.</returns> [HttpPost("{pluginId}/{version}/Enable")] - [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult EnablePlugin([FromRoute, Required] Guid pluginId, [FromRoute, Required] Version version) @@ -90,7 +89,6 @@ public class PluginsController : BaseJellyfinApiController /// <response code="404">Plugin not found.</response> /// <returns>An <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the plugin could not be found.</returns> [HttpPost("{pluginId}/{version}/Disable")] - [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult DisablePlugin([FromRoute, Required] Guid pluginId, [FromRoute, Required] Version version) @@ -114,7 +112,6 @@ public class PluginsController : BaseJellyfinApiController /// <response code="404">Plugin not found.</response> /// <returns>An <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the plugin could not be found.</returns> [HttpDelete("{pluginId}/{version}")] - [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult UninstallPluginByVersion([FromRoute, Required] Guid pluginId, [FromRoute, Required] Version version) @@ -137,7 +134,6 @@ public class PluginsController : BaseJellyfinApiController /// <response code="404">Plugin not found.</response> /// <returns>An <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the plugin could not be found.</returns> [HttpDelete("{pluginId}")] - [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Obsolete("Please use the UninstallPluginByVersion API.")] diff --git a/Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs b/Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs index fed5dab69..31c0be52f 100644 --- a/Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs +++ b/Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs @@ -106,18 +106,11 @@ public class TrickplayManager : ITrickplayManager } var imgTempDir = string.Empty; - var outputDir = GetTrickplayDirectory(video, width); using (await _resourcePool.LockAsync(cancellationToken).ConfigureAwait(false)) { try { - if (!replace && Directory.Exists(outputDir) && (await GetTrickplayResolutions(video.Id).ConfigureAwait(false)).ContainsKey(width)) - { - _logger.LogDebug("Found existing trickplay files for {ItemId}. Exiting.", video.Id); - return; - } - // Extract images // Note: Media sources under parent items exist as their own video/item as well. Only use this video stream for trickplay. var mediaSource = video.GetMediaSources(false).Find(source => Guid.Parse(source.Id).Equals(video.Id)); @@ -128,17 +121,35 @@ public class TrickplayManager : ITrickplayManager return; } + // The width has to be even, otherwise a lot of filters will not be able to sample it + var actualWidth = 2 * (width / 2); + + // Force using the video width when the trickplay setting has a too large width + if (mediaSource.VideoStream.Width is not null && mediaSource.VideoStream.Width < width) + { + _logger.LogWarning("Video width {VideoWidth} is smaller than trickplay setting {TrickPlayWidth}, using video width for thumbnails", mediaSource.VideoStream.Width, width); + actualWidth = 2 * ((int)mediaSource.VideoStream.Width / 2); + } + + var outputDir = GetTrickplayDirectory(video, actualWidth); + + if (!replace && Directory.Exists(outputDir) && (await GetTrickplayResolutions(video.Id).ConfigureAwait(false)).ContainsKey(actualWidth)) + { + _logger.LogDebug("Found existing trickplay files for {ItemId}. Exiting", video.Id); + return; + } + var mediaPath = mediaSource.Path; var mediaStream = mediaSource.VideoStream; var container = mediaSource.Container; - _logger.LogInformation("Creating trickplay files at {Width} width, for {Path} [ID: {ItemId}]", width, mediaPath, video.Id); + _logger.LogInformation("Creating trickplay files at {Width} width, for {Path} [ID: {ItemId}]", actualWidth, mediaPath, video.Id); imgTempDir = await _mediaEncoder.ExtractVideoImagesOnIntervalAccelerated( mediaPath, container, mediaSource, mediaStream, - width, + actualWidth, TimeSpan.FromMilliseconds(options.Interval), options.EnableHwAcceleration, options.EnableHwEncoding, @@ -159,7 +170,7 @@ public class TrickplayManager : ITrickplayManager .ToList(); // Create tiles - var trickplayInfo = CreateTiles(images, width, options, outputDir); + var trickplayInfo = CreateTiles(images, actualWidth, options, outputDir); // Save tiles info try diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 9c087f011..d6907fdf9 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -2984,8 +2984,8 @@ namespace MediaBrowser.Controller.MediaEncoding var scaleW = (double)maximumWidth / outputWidth; var scaleH = (double)maximumHeight / outputHeight; var scale = Math.Min(scaleW, scaleH); - outputWidth = Math.Min(maximumWidth, (int)(outputWidth * scale)); - outputHeight = Math.Min(maximumHeight, (int)(outputHeight * scale)); + outputWidth = Math.Min(maximumWidth, Convert.ToInt32(outputWidth * scale)); + outputHeight = Math.Min(maximumHeight, Convert.ToInt32(outputHeight * scale)); } outputWidth = 2 * (outputWidth / 2); |
