Fix subtitle saving if file already exists (#11310)

This commit is contained in:
Tim Eisele 2024-05-05 16:22:34 +02:00 committed by GitHub
parent 3ae0fb90cb
commit 4aad655fa8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -117,7 +117,7 @@ namespace MediaBrowser.Providers.Subtitles
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Error downloading subtitles from {0}", i.Name); _logger.LogError(ex, "Error downloading subtitles from {Name}", i.Name);
return Array.Empty<RemoteSubtitleInfo>(); return Array.Empty<RemoteSubtitleInfo>();
} }
}); });
@ -205,72 +205,71 @@ namespace MediaBrowser.Providers.Subtitles
saveFileName += ".sdh"; saveFileName += ".sdh";
} }
saveFileName += "." + response.Format.ToLowerInvariant();
if (saveInMediaFolder) if (saveInMediaFolder)
{ {
var mediaFolderPath = Path.GetFullPath(Path.Combine(video.ContainingFolderPath, saveFileName)); var mediaFolderPath = Path.GetFullPath(Path.Combine(video.ContainingFolderPath, saveFileName));
// TODO: Add some error handling to the API user: return BadRequest("Could not save subtitle, bad path."); savePaths.Add(mediaFolderPath);
if (mediaFolderPath.StartsWith(video.ContainingFolderPath, StringComparison.Ordinal))
{
savePaths.Add(mediaFolderPath);
}
} }
var internalPath = Path.GetFullPath(Path.Combine(video.GetInternalMetadataPath(), saveFileName)); var internalPath = Path.GetFullPath(Path.Combine(video.GetInternalMetadataPath(), saveFileName));
// TODO: Add some error to the user: return BadRequest("Could not save subtitle, bad path."); savePaths.Add(internalPath);
if (internalPath.StartsWith(video.GetInternalMetadataPath(), StringComparison.Ordinal))
{
savePaths.Add(internalPath);
}
if (savePaths.Count > 0) await TrySaveToFiles(memoryStream, savePaths, video, response.Format.ToLowerInvariant()).ConfigureAwait(false);
{
await TrySaveToFiles(memoryStream, savePaths).ConfigureAwait(false);
}
else
{
_logger.LogError("An uploaded subtitle could not be saved because the resulting paths were invalid.");
}
} }
} }
private async Task TrySaveToFiles(Stream stream, List<string> savePaths) private async Task TrySaveToFiles(Stream stream, List<string> savePaths, Video video, string extension)
{ {
List<Exception>? exs = null; List<Exception>? exs = null;
foreach (var savePath in savePaths) foreach (var savePath in savePaths)
{ {
_logger.LogInformation("Saving subtitles to {SavePath}", savePath); var path = savePath + "." + extension;
_monitor.ReportFileSystemChangeBeginning(savePath);
try try
{ {
Directory.CreateDirectory(Path.GetDirectoryName(savePath) ?? throw new InvalidOperationException("Path can't be a root directory.")); if (path.StartsWith(video.ContainingFolderPath, StringComparison.Ordinal)
|| path.StartsWith(video.GetInternalMetadataPath(), StringComparison.Ordinal))
var fileOptions = AsyncFile.WriteOptions;
fileOptions.Mode = FileMode.CreateNew;
fileOptions.PreallocationSize = stream.Length;
var fs = new FileStream(savePath, fileOptions);
await using (fs.ConfigureAwait(false))
{ {
await stream.CopyToAsync(fs).ConfigureAwait(false); var fileExists = File.Exists(path);
} var counter = 0;
return; while (fileExists)
{
path = string.Format(CultureInfo.InvariantCulture, "{0}.{1}.{2}", savePath, counter, extension);
fileExists = File.Exists(path);
counter++;
}
_logger.LogInformation("Saving subtitles to {SavePath}", path);
_monitor.ReportFileSystemChangeBeginning(path);
Directory.CreateDirectory(Path.GetDirectoryName(path) ?? throw new InvalidOperationException("Path can't be a root directory."));
var fileOptions = AsyncFile.WriteOptions;
fileOptions.Mode = FileMode.CreateNew;
fileOptions.PreallocationSize = stream.Length;
var fs = new FileStream(path, fileOptions);
await using (fs.ConfigureAwait(false))
{
await stream.CopyToAsync(fs).ConfigureAwait(false);
}
return;
}
else
{
// TODO: Add some error handling to the API user: return BadRequest("Could not save subtitle, bad path.");
_logger.LogError("An uploaded subtitle could not be saved because the resulting path was invalid.");
}
} }
catch (Exception ex) catch (Exception ex)
{ {
// Bug in analyzer -- https://github.com/dotnet/roslyn-analyzers/issues/5160 (exs ??= []).Add(ex);
#pragma warning disable CA1508
(exs ??= new List<Exception>()).Add(ex);
#pragma warning restore CA1508
} }
finally finally
{ {
_monitor.ReportFileSystemChangeComplete(savePath, false); _monitor.ReportFileSystemChangeComplete(path, false);
} }
stream.Position = 0; stream.Position = 0;