diff --git a/server/RdtClient.Service.Test/Helpers/DownloadHelperTest.cs b/server/RdtClient.Service.Test/Helpers/DownloadHelperTest.cs index 1fac48f..90ba064 100644 --- a/server/RdtClient.Service.Test/Helpers/DownloadHelperTest.cs +++ b/server/RdtClient.Service.Test/Helpers/DownloadHelperTest.cs @@ -259,6 +259,95 @@ public class DownloadHelperTest Assert.Equal(expectedPath, path); } + [Fact] + public void GetDownloadPath_WithPath_WhenFilePathStartsWithTorrentName_StripsPrefix() + { + // Arrange + var download = new Download + { + Link = "https://fake.url/file.txt", + FileName = "file.txt" + }; + + String fileRelativePath; + + if (OSHelper.IsLinux) + { + fileRelativePath = "Torrent Name/Saison 1/file.txt"; + } + else + { + fileRelativePath = @"Torrent Name\Saison 1\file.txt"; + } + + IList files = + [ + new() + { + Path = fileRelativePath + } + ]; + + var torrent = new Torrent + { + RdName = "Torrent Name", + RdFiles = JsonSerializer.Serialize(files) + }; + + var fileSystem = new MockFileSystem(); + + // Act + var path = DownloadHelper.GetDownloadPath("/data/downloads", torrent, download, fileSystem); + + // Assert + // The torrent name prefix in the file path should not duplicate the torrent name in the base dir + var expectedPath = Path.Combine("/data/downloads", "Torrent Name", "Saison 1", "file.txt"); + Assert.Equal(expectedPath, path); + } + + [Fact] + public void GetDownloadPath_WithoutPath_WhenFilePathStartsWithTorrentName_StripsPrefix() + { + // Arrange + var download = new Download + { + Link = "https://fake.url/file.txt", + FileName = "file.txt" + }; + + String fileRelativePath; + + if (OSHelper.IsLinux) + { + fileRelativePath = "Torrent Name/Saison 1/file.txt"; + } + else + { + fileRelativePath = @"Torrent Name\Saison 1\file.txt"; + } + + IList files = + [ + new() + { + Path = fileRelativePath + } + ]; + + var torrent = new Torrent + { + RdName = "Torrent Name", + RdFiles = JsonSerializer.Serialize(files) + }; + + // Act + var path = DownloadHelper.GetDownloadPath(torrent, download); + + // Assert + var expectedPath = Path.Combine("Torrent Name", "Saison 1", "file.txt"); + Assert.Equal(expectedPath, path); + } + // This is probably a bug [Fact] public void GetDownloadPath_WithPath_WhenNoUriSegmentsOrFileName_ReturnsTorrentDirectory() diff --git a/server/RdtClient.Service/Helpers/DownloadHelper.cs b/server/RdtClient.Service/Helpers/DownloadHelper.cs index 39f8635..bc5b578 100644 --- a/server/RdtClient.Service/Helpers/DownloadHelper.cs +++ b/server/RdtClient.Service/Helpers/DownloadHelper.cs @@ -130,17 +130,27 @@ public static class DownloadHelper private static String StripTorrentNamePrefix(String subPath, String torrentName) { - var prefix = torrentName.TrimEnd('/', '\\'); + var separatorIndex = subPath.IndexOfAny(['/', '\\']); - if (subPath.Equals(prefix, StringComparison.OrdinalIgnoreCase)) + String firstComponent; + String remainder; + + if (separatorIndex < 0) { - return String.Empty; + firstComponent = subPath; + remainder = String.Empty; + } + else + { + firstComponent = subPath[..separatorIndex]; + remainder = subPath[(separatorIndex + 1)..]; } - if (subPath.StartsWith(prefix + "/", StringComparison.OrdinalIgnoreCase) || - subPath.StartsWith(prefix + "\\", StringComparison.OrdinalIgnoreCase)) + var normalizedFirst = RemoveInvalidPathChars(firstComponent); + + if (normalizedFirst.Equals(torrentName.TrimEnd('/', '\\'), StringComparison.OrdinalIgnoreCase)) { - return subPath[(prefix.Length + 1)..]; + return remainder; } return subPath;