gmacFTP 0.0.17
A bugfix release. Folder downloads from an FTP/SFTP server were broken; this also tightens the path-containment guard that caused it.
- Folder downloads work again. Dragging a folder (or using the arrow button) from a remote pane to a local pane no longer failed with
downloaded 0 file(s); skipped N unsafe path(s). The write-boundary containment guard canonicalized the destination folder path, but that folder does not exist until the first file is written — socanonicalizereturnedNotFoundand every file was silently skipped. The guard now resolves the nearest existing ancestor instead, so a not-yet-created destination root is tolerated (single-file downloads were always unaffected). - Folder downloads no longer error-loop on session-limited FTP servers. Each file in a folder download opens its own FTP session, and shared-hosting servers that cap concurrent sessions would answer the next connect with
421 Too many connections— which, across a large folder, cascaded into a rapid storm of errors. Downloads now retry with escalating backoff (up to ~8 s) when the server is briefly over its session limit, so the previous file's slot has time to release. - Arbitrarily large folders stream through a small queue (backpressure). A folder download no longer pre-loads every file into a fixed-size queue — that capped at a few hundred files and failed the rest with
transfer queue full. The folder loop now streams jobs into the transfer engine one at a time, waiting when the queue is full, so a 10 000-file download flows through with bounded memory and nothing is dropped. - No more per-file pane flicker during a folder transfer. The remote/local panes used to re-list (and recalculate folder sizes) after every single file finished. They now refresh once, at the end of the whole batch.
- Transfer UI polish. The compact bottom bar now shows the name of the file currently copying (it used to freeze on the initial label during a fast batch). The transfer panel summary leads with overall progress ("127 / 283 done · …"), the header pill shows done/total with proper padding, and the toolbar Transfers button carries a pending-count badge that opens the panel on click.
- Folders now ask before overwriting. Copying a folder whose name already exists at the destination used to merge silently (only single files prompted). Folders now go through the same overwrite dialog — Overwrite merges into the existing folder, Save-as-new renames, Cancel aborts. (Per-file prompts inside a large folder are intentionally not added — a 300-file folder would mean 300 dialogs.)
- Path-containment guard hardened (defense-in-depth). The same guard now rejects any
..traversal component outright, and the lenient canonicalization no longer silently drops a trailing..(whichPath::file_name()hides). No remote exploit was reachable —sanitize_local_relalready strips..from server-controlled names — but the write-boundary backstop is now self-sufficient rather than relying on the primary defense. - Clippy is now clean under
-D warnings. Factored the three complex static types into aliases, gavetry_enqueuea real error type (QueueFull), made the transfer-thread-local aconstinitializer, and fixed a handful of redundant-closure / unnecessary-ownership lints. The ten wide internal-helper signatures (AppCtx-style argument lists) are explicitly allowed — they are deliberate and noted as known inci.yml. Pure code-quality; no behavior change.
Verified: release build + 29 unit/integration tests + cargo clippy -D warnings + cargo fmt --check all green.