aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-common/src
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-01 11:47:39 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-01 11:47:39 +0200
commit760ac421b1944cd69a80e3a92127a1a966f15938 (patch)
treec894b655d4f21698ebb91c0865ddf3e04985586d /packages/meshbay-common/src
parent752b160c7c5e671e0db8f402a52fac27bb85ab06 (diff)
downloadmeshbay-760ac421b1944cd69a80e3a92127a1a966f15938.tar.gz
fix: downloads are marked and keep their extension; Explorer files are refused
The desktop app writes the Mark-of-the-Web on each file it saves on Windows, as a browser does. Bidirectional controls are reserved characters in a saved name (portable-name.js and paths.sanitize_for_download, and again in the main process), so a name cannot display one extension and carry another. The node refuses uploads of files Windows Explorer acts on by itself: desktop.ini, .lnk, .url, .scf, .library-ms, .searchConnector-ms (F-19). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-common/src')
-rw-r--r--packages/meshbay-common/src/meshbay_common/paths.py8
1 files changed, 6 insertions, 2 deletions
diff --git a/packages/meshbay-common/src/meshbay_common/paths.py b/packages/meshbay-common/src/meshbay_common/paths.py
index b673649..8be4680 100644
--- a/packages/meshbay-common/src/meshbay_common/paths.py
+++ b/packages/meshbay-common/src/meshbay_common/paths.py
@@ -30,8 +30,12 @@ WINDOWS_RESERVED = frozenset({
*(f"LPT{i}" for i in range(1, 10)),
})
-# Reserved on Windows; `/` is reserved everywhere. Control characters go too.
-_RESERVED_CHARS = set('<>:"/\\|?*') | {chr(c) for c in range(32)}
+# Reserved on Windows; `/` is reserved everywhere. Control characters go too,
+# and so do the bidirectional controls: "invoice\u202efdp.exe" displays as
+# "invoiceexe.pdf", and a saved name must say what the file is.
+BIDI_CONTROLS = frozenset("\u061c\u200e\u200f\u202a\u202b\u202c\u202d\u202e"
+ "\u2066\u2067\u2068\u2069")
+_RESERVED_CHARS = set('<>:"/\\|?*') | {chr(c) for c in range(32)} | BIDI_CONTROLS
# Windows without long-path support. A deep media library reaches this.
MAX_PATH_WINDOWS = 260