@decentnetwork/lan 0.1.112 → 0.1.113
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/daemon/server.js
CHANGED
|
@@ -33,6 +33,21 @@ function shellQuote(parts) {
|
|
|
33
33
|
.map((p) => "'" + p.replace(/'/g, `'\\''`) + "'")
|
|
34
34
|
.join(" ");
|
|
35
35
|
}
|
|
36
|
+
/** Make an incoming filename safe to write to disk AND friendly to open from a
|
|
37
|
+
* shell. Strips path separators + control chars and normalizes exotic Unicode
|
|
38
|
+
* whitespace (e.g. macOS's U+202F narrow no-break space before "PM" in
|
|
39
|
+
* screenshot/recording names) to a plain space, so files don't need shell
|
|
40
|
+
* escaping. Never empty. */
|
|
41
|
+
function sanitizeFileName(name) {
|
|
42
|
+
const cleaned = (name || "file")
|
|
43
|
+
.replace(/[/\\]/g, "_")
|
|
44
|
+
// eslint-disable-next-line no-control-regex
|
|
45
|
+
.replace(/[\u0000-\u001f\u007f]/g, "")
|
|
46
|
+
.replace(/[\u00a0\u2000-\u200f\u2028\u2029\u202f\u205f\u3000\ufeff]/g, " ")
|
|
47
|
+
.replace(/\s+/g, " ")
|
|
48
|
+
.trim();
|
|
49
|
+
return cleaned || "file";
|
|
50
|
+
}
|
|
36
51
|
import { ConfigLoader, DEFAULT_DORAS } from "../config/loader.js";
|
|
37
52
|
export class DaemonServer {
|
|
38
53
|
config;
|
|
@@ -598,7 +613,7 @@ export class DaemonServer {
|
|
|
598
613
|
const dir = resolve(this.configDir, "downloads");
|
|
599
614
|
const fs = await import("fs/promises");
|
|
600
615
|
await fs.mkdir(dir, { recursive: true });
|
|
601
|
-
const safe = (p.name
|
|
616
|
+
const safe = sanitizeFileName(p.name);
|
|
602
617
|
await fs.writeFile(resolve(dir, safe), Buffer.from(p.data));
|
|
603
618
|
this.logger.info(`Saved file "${p.name}" (${p.size}B) from ${p.friendId.slice(0, 8)} → ${resolve(dir, safe)}`);
|
|
604
619
|
// Record in chat history (as a download chip) and push to the UI.
|
package/dist/ui/server.js
CHANGED
|
@@ -307,9 +307,15 @@ export function startFriendUi(opts) {
|
|
|
307
307
|
res.end("not found");
|
|
308
308
|
return;
|
|
309
309
|
}
|
|
310
|
+
// Content-Disposition must be ASCII — Node throws ERR_INVALID_CHAR on a
|
|
311
|
+
// non-ASCII header value (filenames from macOS contain U+202F before
|
|
312
|
+
// "PM", and others may be Chinese, etc.). Provide an ASCII-only
|
|
313
|
+
// `filename=` fallback plus the RFC 5987 `filename*=UTF-8''…` with the
|
|
314
|
+
// real (percent-encoded) name for clients that support it.
|
|
315
|
+
const asciiName = name.replace(/[^\x20-\x7e]/g, "_").replace(/"/g, "");
|
|
310
316
|
res.writeHead(200, {
|
|
311
317
|
"content-type": "application/octet-stream",
|
|
312
|
-
"content-disposition": `attachment; filename="${
|
|
318
|
+
"content-disposition": `attachment; filename="${asciiName}"; filename*=UTF-8''${encodeURIComponent(name)}`,
|
|
313
319
|
});
|
|
314
320
|
res.end(readFileSync(file));
|
|
315
321
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decentnetwork/lan",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.113",
|
|
4
4
|
"description": "Private virtual LAN for self-hosted services and AI agents, built on Elastos Carrier. NAT-traversal, name service, ACL, all over a peer-to-peer mesh — no public IP required.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|