- FilenameSanitizer class doc previously attributed the bug to "shell
globbing, URI handling, and various download clients"; that was
speculation about the mechanism. The confirmed cause is a failure
inside the Bezzad Downloader NuGet package on Linux. Rewrite the
class doc to describe what we actually know.
- SanitizeFilenameIfEnabled / SanitizePathIfEnabled said "returns it
unchanged" when disabled, which isn't accurate for null input: we
coerce to String.Empty so the return stays non-null. Spell that out.
- SanitizeFilename method summary rewritten to list exactly what it
does rather than "problematic characters".
- Changelog entry said the setting is "on by default" but the default
is OperatingSystem.IsLinux(). Fix the wording.
The underlying bug (debrid-provider filenames with brackets causing
downloads to fail) only reproduces on Linux hosts. Windows, macOS,
and other platforms handle these characters without issue and have
no reason to have their filenames modified. Default the toggle to
OperatingSystem.IsLinux() so Windows users see no behaviour change
while Linux containers still get the fix out of the box. Users on
either platform can override via the setting.
Addresses review feedback on PR #962.
UnpackClient now sanitizes the torrent directory name when building
extractPath, so the post-unpack TorBox move needs to compare against
the sanitized name as well. Without this, extractPath.EndsWith(rdName)
takes the wrong branch for any torrent whose RdName contained brackets
and files end up in the hash subdirectory instead of the torrent
directory.
Reported by @omgbeez.
- Revert GetFileName to return unsanitized name. AllDebridDebridClient.
GetSymlinkPath matches torrent.Files[].Path (original debrid data)
against GetFileName, so sanitizing it broke AllDebrid Symlink lookups
for any torrent with bracketed filenames. Sanitization now happens
inside GetDownloadPath at the point the filesystem path is assembled,
while matching still uses the unsanitized name.
- Make SanitizeFilename / SanitizePath accept String? and return
String.Empty for null/empty input so the declared non-null return
type is honoured.
- SanitizePath splits on both '/' and '\\' regardless of host OS, so
paths arriving from the debrid provider with foreign separators are
still segmented correctly on Linux containers.
- Rewrite the control-character tests to use explicit \u escape
sequences (, , , , ) so the test
inputs are visible in diffs and survive editor/CI round-trips.
Replace the single-row empty [Theory] with a [Fact] and add a null
case. Add tests asserting SanitizeFilenameIfEnabled and
SanitizePathIfEnabled return input unchanged when the toggle is
disabled, and sanitize when enabled.
Downloads fail on Linux containers when filenames contain square
brackets or multiple consecutive spaces. On Linux, .NET's
Path.GetInvalidFileNameChars() only returns NUL and '/', so characters
like [ ] { } that cause issues with shell globbing, URI handling, and
various download clients pass through the existing filter unchanged.
Add FilenameSanitizer that:
- Strips square brackets, curly braces, and control characters
- Collapses multiple consecutive spaces into one
- Trims leading and trailing whitespace
- Preserves parentheses and all other characters
Apply sanitization at filesystem boundaries: DownloadHelper (where the
Real-Debrid filename is turned into a local path), UnpackClient,
Torrent delete / RunOnTorrentComplete, and the qBittorrent / SABnzbd
status paths that *arr reads back. Aria2c and DownloadStation also
sanitize their remote output paths so they match the sanitized local
filePath. Symlink's rclone-mount lookup still uses the original name
since that has to match the real file in the mount.
Add a SanitizeFilenames toggle in DbSettings (default on) so users
can disable the behaviour if they need the exact Real-Debrid name.
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.
torrent.Files[].Path already includes the torrent name as its first
component (e.g. "Hijack/Saison 1/file.mkv"), but GetDownloadPath was
also initialising torrentPath with torrent.RdName, causing the name
to appear twice (e.g. "Hijack/Hijack/Saison 1"). Strip the torrent
name prefix from subPath before combining so the resolved path matches
the actual rclone mount layout.
Add support for the `hashes` query parameter (pipe-separated, case-insensitive)
to match real qBittorrent API behavior. This fixes compatibility with cleanuparr
and *arr apps that rely on hash-based filtering.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Applied to TorBox, can be extended easily to other providers
- Reads response headers commonplace for pre-emptive rate limit throttling and retry-after
- When a rate limit is reached, displays a warning in the UI
- Fix socket leak from direct allocation of HttpClient, replaced with factory which handles pooling and re-use of sockets.
While HttpClient is Disposable, it doesn't gaurantee (and does not) directly release underlying sockets for queries at the time the client is disposed. These sockets will go into a TCP WAIT state often for a very long time. The expected pattern in C# is to always use the HttClientFactory which will correctly handle re-use of the OS sockets in suqsequent queries reducing resource and memory leaks.
- Fixes an issue where progress goes back to 50% as soon as downloads are done
- Prevents copy and update of torrent/nzb list by not updating download stats on every use, most callers don't require this data, notable perf/memory improvement.