From 204fdeb0357ac86aaef6b4e014066b1eb2ca554c Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Tue, 28 Nov 2023 15:21:32 -0700 Subject: [PATCH] Validate codec and container --- Jellyfin.Api/Controllers/AudioController.cs | 18 +++--- .../Controllers/DynamicHlsController.cs | 58 +++++++++---------- .../Controllers/UniversalAudioController.cs | 4 +- Jellyfin.Api/Controllers/VideosController.cs | 18 +++--- .../MediaEncoding/EncodingHelper.cs | 19 +++++- 5 files changed, 66 insertions(+), 51 deletions(-) diff --git a/Jellyfin.Api/Controllers/AudioController.cs b/Jellyfin.Api/Controllers/AudioController.cs index 54ac06276e..0b98d915c2 100644 --- a/Jellyfin.Api/Controllers/AudioController.cs +++ b/Jellyfin.Api/Controllers/AudioController.cs @@ -91,18 +91,18 @@ namespace Jellyfin.Api.Controllers [ProducesAudioFile] public async Task GetAudioStream( [FromRoute, Required] Guid itemId, - [FromQuery] string? container, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, [FromQuery] string? deviceProfileId, [FromQuery] string? playSessionId, - [FromQuery] string? segmentContainer, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? segmentContainer, [FromQuery] int? segmentLength, [FromQuery] int? minSegments, [FromQuery] string? mediaSourceId, [FromQuery] string? deviceId, - [FromQuery] string? audioCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? audioCodec, [FromQuery] bool? enableAutoStreamCopy, [FromQuery] bool? allowVideoStreamCopy, [FromQuery] bool? allowAudioStreamCopy, @@ -132,8 +132,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? cpuCoreLimit, [FromQuery] string? liveStreamId, [FromQuery] bool? enableMpegtsM2TsMode, - [FromQuery] string? videoCodec, - [FromQuery] string? subtitleCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? videoCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? subtitleCodec, [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, @@ -262,12 +262,12 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? tag, [FromQuery] string? deviceProfileId, [FromQuery] string? playSessionId, - [FromQuery] string? segmentContainer, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? segmentContainer, [FromQuery] int? segmentLength, [FromQuery] int? minSegments, [FromQuery] string? mediaSourceId, [FromQuery] string? deviceId, - [FromQuery] string? audioCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? audioCodec, [FromQuery] bool? enableAutoStreamCopy, [FromQuery] bool? allowVideoStreamCopy, [FromQuery] bool? allowAudioStreamCopy, @@ -297,8 +297,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? cpuCoreLimit, [FromQuery] string? liveStreamId, [FromQuery] bool? enableMpegtsM2TsMode, - [FromQuery] string? videoCodec, - [FromQuery] string? subtitleCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? videoCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? subtitleCodec, [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index ffd5f6818f..db1c5c2a65 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -174,18 +174,18 @@ namespace Jellyfin.Api.Controllers [ProducesPlaylistFile] public async Task GetLiveHlsStream( [FromRoute, Required] Guid itemId, - [FromQuery] string? container, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, [FromQuery] string? deviceProfileId, [FromQuery] string? playSessionId, - [FromQuery] string? segmentContainer, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? segmentContainer, [FromQuery] int? segmentLength, [FromQuery] int? minSegments, [FromQuery] string? mediaSourceId, [FromQuery] string? deviceId, - [FromQuery] string? audioCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? audioCodec, [FromQuery] bool? enableAutoStreamCopy, [FromQuery] bool? allowVideoStreamCopy, [FromQuery] bool? allowAudioStreamCopy, @@ -215,8 +215,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? cpuCoreLimit, [FromQuery] string? liveStreamId, [FromQuery] bool? enableMpegtsM2TsMode, - [FromQuery] string? videoCodec, - [FromQuery] string? subtitleCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? videoCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? subtitleCodec, [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, @@ -426,12 +426,12 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? tag, [FromQuery] string? deviceProfileId, [FromQuery] string? playSessionId, - [FromQuery] string? segmentContainer, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? segmentContainer, [FromQuery] int? segmentLength, [FromQuery] int? minSegments, [FromQuery, Required] string mediaSourceId, [FromQuery] string? deviceId, - [FromQuery] string? audioCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? audioCodec, [FromQuery] bool? enableAutoStreamCopy, [FromQuery] bool? allowVideoStreamCopy, [FromQuery] bool? allowAudioStreamCopy, @@ -463,8 +463,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? cpuCoreLimit, [FromQuery] string? liveStreamId, [FromQuery] bool? enableMpegtsM2TsMode, - [FromQuery] string? videoCodec, - [FromQuery] string? subtitleCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? videoCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? subtitleCodec, [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, @@ -596,12 +596,12 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? tag, [FromQuery] string? deviceProfileId, [FromQuery] string? playSessionId, - [FromQuery] string? segmentContainer, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? segmentContainer, [FromQuery] int? segmentLength, [FromQuery] int? minSegments, [FromQuery, Required] string mediaSourceId, [FromQuery] string? deviceId, - [FromQuery] string? audioCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? audioCodec, [FromQuery] bool? enableAutoStreamCopy, [FromQuery] bool? allowVideoStreamCopy, [FromQuery] bool? allowAudioStreamCopy, @@ -632,8 +632,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? cpuCoreLimit, [FromQuery] string? liveStreamId, [FromQuery] bool? enableMpegtsM2TsMode, - [FromQuery] string? videoCodec, - [FromQuery] string? subtitleCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? videoCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? subtitleCodec, [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, @@ -762,12 +762,12 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? tag, [FromQuery] string? deviceProfileId, [FromQuery] string? playSessionId, - [FromQuery] string? segmentContainer, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? segmentContainer, [FromQuery] int? segmentLength, [FromQuery] int? minSegments, [FromQuery] string? mediaSourceId, [FromQuery] string? deviceId, - [FromQuery] string? audioCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? audioCodec, [FromQuery] bool? enableAutoStreamCopy, [FromQuery] bool? allowVideoStreamCopy, [FromQuery] bool? allowAudioStreamCopy, @@ -799,8 +799,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? cpuCoreLimit, [FromQuery] string? liveStreamId, [FromQuery] bool? enableMpegtsM2TsMode, - [FromQuery] string? videoCodec, - [FromQuery] string? subtitleCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? videoCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? subtitleCodec, [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, @@ -930,12 +930,12 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? tag, [FromQuery] string? deviceProfileId, [FromQuery] string? playSessionId, - [FromQuery] string? segmentContainer, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? segmentContainer, [FromQuery] int? segmentLength, [FromQuery] int? minSegments, [FromQuery] string? mediaSourceId, [FromQuery] string? deviceId, - [FromQuery] string? audioCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? audioCodec, [FromQuery] bool? enableAutoStreamCopy, [FromQuery] bool? allowVideoStreamCopy, [FromQuery] bool? allowAudioStreamCopy, @@ -966,8 +966,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? cpuCoreLimit, [FromQuery] string? liveStreamId, [FromQuery] bool? enableMpegtsM2TsMode, - [FromQuery] string? videoCodec, - [FromQuery] string? subtitleCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? videoCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? subtitleCodec, [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, @@ -1107,12 +1107,12 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? tag, [FromQuery] string? deviceProfileId, [FromQuery] string? playSessionId, - [FromQuery] string? segmentContainer, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? segmentContainer, [FromQuery] int? segmentLength, [FromQuery] int? minSegments, [FromQuery] string? mediaSourceId, [FromQuery] string? deviceId, - [FromQuery] string? audioCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? audioCodec, [FromQuery] bool? enableAutoStreamCopy, [FromQuery] bool? allowVideoStreamCopy, [FromQuery] bool? allowAudioStreamCopy, @@ -1144,8 +1144,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? cpuCoreLimit, [FromQuery] string? liveStreamId, [FromQuery] bool? enableMpegtsM2TsMode, - [FromQuery] string? videoCodec, - [FromQuery] string? subtitleCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? videoCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? subtitleCodec, [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, @@ -1288,12 +1288,12 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? tag, [FromQuery] string? deviceProfileId, [FromQuery] string? playSessionId, - [FromQuery] string? segmentContainer, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? segmentContainer, [FromQuery] int? segmentLength, [FromQuery] int? minSegments, [FromQuery] string? mediaSourceId, [FromQuery] string? deviceId, - [FromQuery] string? audioCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? audioCodec, [FromQuery] bool? enableAutoStreamCopy, [FromQuery] bool? allowVideoStreamCopy, [FromQuery] bool? allowAudioStreamCopy, @@ -1324,8 +1324,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? cpuCoreLimit, [FromQuery] string? liveStreamId, [FromQuery] bool? enableMpegtsM2TsMode, - [FromQuery] string? videoCodec, - [FromQuery] string? subtitleCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? videoCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? subtitleCodec, [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index fe8125318b..cde76e31ec 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -102,13 +102,13 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? mediaSourceId, [FromQuery] string? deviceId, [FromQuery] Guid? userId, - [FromQuery] string? audioCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? audioCodec, [FromQuery] int? maxAudioChannels, [FromQuery] int? transcodingAudioChannels, [FromQuery] int? maxStreamingBitrate, [FromQuery] int? audioBitRate, [FromQuery] long? startTimeTicks, - [FromQuery] string? transcodingContainer, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? transcodingContainer, [FromQuery] string? transcodingProtocol, [FromQuery] int? maxAudioSampleRate, [FromQuery] int? maxAudioBitDepth, diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index 4e28959345..de96a6cdc0 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -318,18 +318,18 @@ namespace Jellyfin.Api.Controllers [ProducesVideoFile] public async Task GetVideoStream( [FromRoute, Required] Guid itemId, - [FromQuery] string? container, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, [FromQuery] string? deviceProfileId, [FromQuery] string? playSessionId, - [FromQuery] string? segmentContainer, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? segmentContainer, [FromQuery] int? segmentLength, [FromQuery] int? minSegments, [FromQuery] string? mediaSourceId, [FromQuery] string? deviceId, - [FromQuery] string? audioCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? audioCodec, [FromQuery] bool? enableAutoStreamCopy, [FromQuery] bool? allowVideoStreamCopy, [FromQuery] bool? allowAudioStreamCopy, @@ -361,8 +361,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? cpuCoreLimit, [FromQuery] string? liveStreamId, [FromQuery] bool? enableMpegtsM2TsMode, - [FromQuery] string? videoCodec, - [FromQuery] string? subtitleCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? videoCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? subtitleCodec, [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, @@ -578,12 +578,12 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? tag, [FromQuery] string? deviceProfileId, [FromQuery] string? playSessionId, - [FromQuery] string? segmentContainer, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? segmentContainer, [FromQuery] int? segmentLength, [FromQuery] int? minSegments, [FromQuery] string? mediaSourceId, [FromQuery] string? deviceId, - [FromQuery] string? audioCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? audioCodec, [FromQuery] bool? enableAutoStreamCopy, [FromQuery] bool? allowVideoStreamCopy, [FromQuery] bool? allowAudioStreamCopy, @@ -615,8 +615,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? cpuCoreLimit, [FromQuery] string? liveStreamId, [FromQuery] bool? enableMpegtsM2TsMode, - [FromQuery] string? videoCodec, - [FromQuery] string? subtitleCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? videoCodec, + [FromQuery][RegularExpression(EncodingHelper.ValidationRegex)] string? subtitleCodec, [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index ed758af507..ef6e60220f 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -25,6 +25,11 @@ namespace MediaBrowser.Controller.MediaEncoding { public class EncodingHelper { + /// + /// The codec validation regex. + /// + public const string ValidationRegex = @"^[a-zA-Z0-9\-\._,|]{0,40}$"; + private const string QsvAlias = "qs"; private const string VaapiAlias = "va"; private const string D3d11vaAlias = "dx11"; @@ -36,6 +41,8 @@ namespace MediaBrowser.Controller.MediaEncoding private readonly ISubtitleEncoder _subtitleEncoder; private readonly IConfiguration _config; + private static readonly Regex _validationRegex = new(ValidationRegex, RegexOptions.Compiled); + // i915 hang was fixed by linux 6.2 (3f882f2) private readonly Version _minKerneli915Hang = new Version(5, 18); private readonly Version _maxKerneli915Hang = new Version(6, 1, 3); @@ -253,7 +260,10 @@ namespace MediaBrowser.Controller.MediaEncoding return "libtheora"; } - return codec.ToLowerInvariant(); + if (_validationRegex.IsMatch(codec)) + { + return codec.ToLowerInvariant(); + } } return "copy"; @@ -276,7 +286,7 @@ namespace MediaBrowser.Controller.MediaEncoding public static string GetInputFormat(string container) { - if (string.IsNullOrEmpty(container)) + if (string.IsNullOrEmpty(container) || !_validationRegex.IsMatch(container)) { return null; } @@ -523,6 +533,11 @@ namespace MediaBrowser.Controller.MediaEncoding { var codec = state.OutputAudioCodec; + if (!_validationRegex.IsMatch(codec)) + { + codec = "aac"; + } + if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase)) { // Use libfdk_aac for better audio quality if using custom build of FFmpeg which has fdk_aac support