fix(symlink): normalize subpath first component before comparing torrent name prefix
The previous fix compared subPath directly against the sanitized torrent name, which fails when RdName contains characters removed by RemoveInvalidPathChars (e.g. ':' on Windows). Extract and normalize the first component of subPath before comparing so both sides go through the same sanitization. Add tests covering the duplicate-prefix stripping case.
This commit is contained in:
parent
1dd7ab9c8e
commit
6743bd472e
2 changed files with 105 additions and 6 deletions
|
|
@ -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<DebridClientFile> 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<DebridClientFile> 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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue