From 760ac421b1944cd69a80e3a92127a1a966f15938 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Thu, 1 Oct 2026 11:47:39 +0200 Subject: 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 --- packages/meshbay-node/tests/test_partial_uploads.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'packages/meshbay-node/tests') diff --git a/packages/meshbay-node/tests/test_partial_uploads.py b/packages/meshbay-node/tests/test_partial_uploads.py index 138ee3b..556b26a 100644 --- a/packages/meshbay-node/tests/test_partial_uploads.py +++ b/packages/meshbay-node/tests/test_partial_uploads.py @@ -22,6 +22,7 @@ import time import types from pathlib import Path +import pytest from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from meshbay_common.crypto import generate_gek from meshbay_common.protocol import ( @@ -552,3 +553,23 @@ def test_without_hard_links_a_file_is_still_not_replaced(tmp_path, monkeypatch): assert (tmp_path / "a.txt").read_bytes() == b"there first" assert (tmp_path / "a (2).txt").read_bytes() == b"uploaded" assert not part.exists() + + +# ── files Explorer acts on by itself ───────────────────────────────────────── + + +@pytest.mark.parametrize("name", ["desktop.ini", "Desktop.INI", "photos.lnk", "site.url", + "x.scf", "Docs.library-ms", "s.searchConnector-ms"]) +async def test_a_file_explorer_acts_on_is_refused(tmp_path, name): + ctx = _group_ctx(tmp_path) + peer = _peer(ctx) + await peer._do_file_upload(sealed_upload(peer, filename=name, data=b"[x]")) + assert [m.get("code") for m in _errors(peer)] == ["file_type_refused"] + assert not any(ctx["roots"].roots[0].path.iterdir()) + + +async def test_an_ordinary_file_with_a_near_name_is_accepted(tmp_path): + ctx = _group_ctx(tmp_path) + peer = _peer(ctx) + await peer._do_file_upload(sealed_upload(peer, filename="url-notes.txt", data=b"x")) + assert _errors(peer) == [] -- cgit v1.2.3