Description
Let the file browser select a folder and send it recursively, recreating its directory layout on the receiver. Today the browser selects individual files only (dirs just navigate), and each file is sent with a flat basename — so sending a gbc/ folder of ROMs means hand-picking every file and losing the structure.
Plan
- Browser: allow selecting a directory, distinct from entering it (
src/overlay/browser.rs; A currently navigates on is_dir). A selected folder is walked recursively, adding files with their path relative to the folder's parent (e.g. gbc/game.gbc).
- Outbound: carry that relative path in
FileMeta.file_name (src/transfer/outbound.rs:96 uses the basename today) — LocalSend conveys folder layout via fileName.
- Receiver: recreate subdirectories under the save dir. This reverses today's deliberate flattening (
src/transfer/inbound.rs:72) — replace with a subpath-aware, traversal-safe join.
- Selection totals + progress reflect the recursive file set.
Notes
- Path-traversal safety is the crux:
file_name is attacker-controlled network input — sanitize each component, drop ./../empties, reject absolute/drive-relative paths, and keep the dest provably under the save root (keep an assert like the current one).
- Interop: verify structure round-trips with the official LocalSend app both ways.
- Save-routes interaction: per-extension routing (
src/transfer/route.rs) is for loose files; for a folder send, preserving the sent structure under save_dir should win (decide + document).
- Large/deep folders: recursive walk + per-file slot/token setup must stay responsive.
- Empty dirs aren't representable in per-file metadata — they'll be skipped.
Description
Let the file browser select a folder and send it recursively, recreating its directory layout on the receiver. Today the browser selects individual files only (dirs just navigate), and each file is sent with a flat basename — so sending a
gbc/folder of ROMs means hand-picking every file and losing the structure.Plan
src/overlay/browser.rs;Acurrently navigates onis_dir). A selected folder is walked recursively, adding files with their path relative to the folder's parent (e.g.gbc/game.gbc).FileMeta.file_name(src/transfer/outbound.rs:96uses the basename today) — LocalSend conveys folder layout viafileName.src/transfer/inbound.rs:72) — replace with a subpath-aware, traversal-safe join.Notes
file_nameis attacker-controlled network input — sanitize each component, drop./../empties, reject absolute/drive-relative paths, and keep the dest provably under the save root (keep an assert like the current one).src/transfer/route.rs) is for loose files; for a folder send, preserving the sent structure undersave_dirshould win (decide + document).