aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Providers/Subtitles/SubtitleManager.cs')
-rw-r--r--MediaBrowser.Providers/Subtitles/SubtitleManager.cs128
1 files changed, 81 insertions, 47 deletions
diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
index 0f7cb3f8fa..0c791a2fee 100644
--- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
+++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
@@ -147,40 +147,14 @@ namespace MediaBrowser.Providers.Subtitles
string subtitleId,
CancellationToken cancellationToken)
{
- var parts = subtitleId.Split(new[] { '_' }, 2);
+ var parts = subtitleId.Split('_', 2);
var provider = GetProvider(parts[0]);
- var saveInMediaFolder = libraryOptions.SaveSubtitlesWithMedia;
-
try
{
var response = await GetRemoteSubtitles(subtitleId, cancellationToken).ConfigureAwait(false);
- using (var stream = response.Stream)
- using (var memoryStream = new MemoryStream())
- {
- await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
- memoryStream.Position = 0;
-
- var savePaths = new List<string>();
- var saveFileName = Path.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLowerInvariant();
-
- if (response.IsForced)
- {
- saveFileName += ".forced";
- }
-
- saveFileName += "." + response.Format.ToLowerInvariant();
-
- if (saveInMediaFolder)
- {
- savePaths.Add(Path.Combine(video.ContainingFolderPath, saveFileName));
- }
-
- savePaths.Add(Path.Combine(video.GetInternalMetadataPath(), saveFileName));
-
- await TrySaveToFiles(memoryStream, savePaths).ConfigureAwait(false);
- }
+ await TrySaveSubtitle(video, libraryOptions, response).ConfigureAwait(false);
}
catch (RateLimitExceededException)
{
@@ -199,9 +173,66 @@ namespace MediaBrowser.Providers.Subtitles
}
}
+ /// <inheritdoc />
+ public Task UploadSubtitle(Video video, SubtitleResponse response)
+ {
+ var libraryOptions = BaseItem.LibraryManager.GetLibraryOptions(video);
+ return TrySaveSubtitle(video, libraryOptions, response);
+ }
+
+ private async Task TrySaveSubtitle(
+ Video video,
+ LibraryOptions libraryOptions,
+ SubtitleResponse response)
+ {
+ var saveInMediaFolder = libraryOptions.SaveSubtitlesWithMedia;
+
+ using var stream = response.Stream;
+ using var memoryStream = new MemoryStream();
+ await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
+ memoryStream.Position = 0;
+
+ var savePaths = new List<string>();
+ var saveFileName = Path.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLowerInvariant();
+
+ if (response.IsForced)
+ {
+ saveFileName += ".forced";
+ }
+
+ saveFileName += "." + response.Format.ToLowerInvariant();
+
+ if (saveInMediaFolder)
+ {
+ 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.");
+ if (mediaFolderPath.StartsWith(video.ContainingFolderPath, StringComparison.Ordinal))
+ {
+ savePaths.Add(mediaFolderPath);
+ }
+ }
+
+ var internalPath = Path.GetFullPath(Path.Combine(video.GetInternalMetadataPath(), saveFileName));
+
+ // TODO: Add some error to the user: return BadRequest("Could not save subtitle, bad path.");
+ if (internalPath.StartsWith(video.GetInternalMetadataPath(), StringComparison.Ordinal))
+ {
+ savePaths.Add(internalPath);
+ }
+
+ if (savePaths.Count > 0)
+ {
+ 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)
{
- Exception exceptionToThrow = null;
+ List<Exception> exs = null;
foreach (var savePath in savePaths)
{
@@ -213,20 +244,23 @@ namespace MediaBrowser.Providers.Subtitles
{
Directory.CreateDirectory(Path.GetDirectoryName(savePath));
- using (var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.Read, FileStreamBufferSize, true))
- {
- await stream.CopyToAsync(fs).ConfigureAwait(false);
- }
+ // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
+ using var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, FileStreamBufferSize, true);
+ await stream.CopyToAsync(fs).ConfigureAwait(false);
return;
}
catch (Exception ex)
{
- if (exceptionToThrow == null)
- {
- exceptionToThrow = ex;
- }
- }
+// Bug in analyzer -- https://github.com/dotnet/roslyn-analyzers/issues/5160
+#pragma warning disable CA1508
+ exs ??= new List<Exception>()
+ {
+ ex
+ };
+#pragma warning restore CA1508
+
+ }
finally
{
_monitor.ReportFileSystemChangeComplete(savePath, false);
@@ -235,9 +269,9 @@ namespace MediaBrowser.Providers.Subtitles
stream.Position = 0;
}
- if (exceptionToThrow != null)
+ if (exs != null)
{
- throw exceptionToThrow;
+ throw new AggregateException(exs);
}
}
@@ -303,7 +337,7 @@ namespace MediaBrowser.Providers.Subtitles
private ISubtitleProvider GetProvider(string id)
{
- return _subtitleProviders.First(i => string.Equals(id, GetProviderId(i.Name)));
+ return _subtitleProviders.First(i => string.Equals(id, GetProviderId(i.Name), StringComparison.Ordinal));
}
/// <inheritdoc />
@@ -314,7 +348,7 @@ namespace MediaBrowser.Providers.Subtitles
Index = index,
ItemId = item.Id,
Type = MediaStreamType.Subtitle
- }).First();
+ })[0];
var path = stream.Path;
_monitor.ReportFileSystemChangeBeginning(path);
@@ -334,24 +368,24 @@ namespace MediaBrowser.Providers.Subtitles
/// <inheritdoc />
public Task<SubtitleResponse> GetRemoteSubtitles(string id, CancellationToken cancellationToken)
{
- var parts = id.Split(new[] { '_' }, 2);
+ var parts = id.Split('_', 2);
var provider = GetProvider(parts[0]);
- id = parts.Last();
+ id = parts[^1];
return provider.GetSubtitles(id, cancellationToken);
}
/// <inheritdoc />
- public SubtitleProviderInfo[] GetSupportedProviders(BaseItem video)
+ public SubtitleProviderInfo[] GetSupportedProviders(BaseItem item)
{
VideoContentType mediaType;
- if (video is Episode)
+ if (item is Episode)
{
mediaType = VideoContentType.Episode;
}
- else if (video is Movie)
+ else if (item is Movie)
{
mediaType = VideoContentType.Movie;
}