@manturhub/cli 0.9.2 → 0.9.4
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.
- package/lib/archive.js +52 -28
- package/package.json +1 -1
package/lib/archive.js
CHANGED
|
@@ -10,8 +10,9 @@ import {
|
|
|
10
10
|
import { basename, join, posix } from "node:path";
|
|
11
11
|
import { tmpdir } from "node:os";
|
|
12
12
|
|
|
13
|
-
const MAX_FILES =
|
|
13
|
+
const MAX_FILES = 20000;
|
|
14
14
|
const MAX_UNPACKED_BYTES = 500 * 1024 * 1024;
|
|
15
|
+
const ARCHIVE_LIST_MAX_BUFFER = 32 * 1024 * 1024;
|
|
15
16
|
|
|
16
17
|
export function validateSlug(slug, label = "ID") {
|
|
17
18
|
if (!slug || !/^[a-z0-9][a-z0-9._-]*$/i.test(slug)) {
|
|
@@ -20,8 +21,8 @@ export function validateSlug(slug, label = "ID") {
|
|
|
20
21
|
return slug;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
function
|
|
24
|
-
|
|
24
|
+
function archiveTools(zipPath) {
|
|
25
|
+
return [
|
|
25
26
|
{
|
|
26
27
|
command: "unzip",
|
|
27
28
|
list: ["-Z1", zipPath],
|
|
@@ -36,19 +37,16 @@ function listArchive(zipPath) {
|
|
|
36
37
|
extract: (dest) => ["-xf", zipPath, "-C", dest],
|
|
37
38
|
},
|
|
38
39
|
];
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
throw new Error("解压失败(需系统 tar 或 unzip 命令)");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function inspectArchive(tool) {
|
|
43
|
+
const execOptions = { encoding: "utf8", maxBuffer: ARCHIVE_LIST_MAX_BUFFER };
|
|
44
|
+
const output = execFileSync(tool.command, tool.list, execOptions);
|
|
45
|
+
const verbose = execFileSync(tool.command, tool.verbose, execOptions);
|
|
46
|
+
const summary = tool.summary
|
|
47
|
+
? execFileSync(tool.command, tool.summary, execOptions)
|
|
48
|
+
: "";
|
|
49
|
+
return { entries: output.split(/\r?\n/).filter(Boolean), verbose, summary };
|
|
52
50
|
}
|
|
53
51
|
|
|
54
52
|
function declaredUnpackedBytes(tool, verbose, summary) {
|
|
@@ -129,18 +127,44 @@ function rejectDestinationLinks(dir) {
|
|
|
129
127
|
}
|
|
130
128
|
|
|
131
129
|
export function extractZipSafely(zipPath, dest) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
cpSync(join(staging, entry), join(dest, basename(entry)), { recursive: true, force: true });
|
|
130
|
+
let foundExtractor = false;
|
|
131
|
+
for (const tool of archiveTools(zipPath)) {
|
|
132
|
+
let archive;
|
|
133
|
+
try {
|
|
134
|
+
archive = inspectArchive(tool);
|
|
135
|
+
foundExtractor = true;
|
|
136
|
+
} catch (error) {
|
|
137
|
+
if (error?.code !== "ENOENT") foundExtractor = true;
|
|
138
|
+
continue;
|
|
142
139
|
}
|
|
143
|
-
|
|
144
|
-
|
|
140
|
+
validateArchiveEntries(
|
|
141
|
+
archive.entries,
|
|
142
|
+
archive.verbose,
|
|
143
|
+
declaredUnpackedBytes(tool, archive.verbose, archive.summary)
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const staging = mkdtempSync(join(tmpdir(), "manturhub-extract-"));
|
|
147
|
+
try {
|
|
148
|
+
try {
|
|
149
|
+
execFileSync(tool.command, tool.extract(staging), { stdio: ["ignore", "ignore", "ignore"] });
|
|
150
|
+
} catch {
|
|
151
|
+
// Some macOS unzip builds can list legacy-encoded Chinese filenames but fail
|
|
152
|
+
// while creating them. Let the next validated extractor (bsdtar via `tar`) try.
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
inspectExtracted(staging);
|
|
156
|
+
mkdirSync(dest, { recursive: true });
|
|
157
|
+
rejectDestinationLinks(dest);
|
|
158
|
+
for (const entry of readdirSync(staging)) {
|
|
159
|
+
cpSync(join(staging, entry), join(dest, basename(entry)), { recursive: true, force: true });
|
|
160
|
+
}
|
|
161
|
+
return;
|
|
162
|
+
} finally {
|
|
163
|
+
rmSync(staging, { recursive: true, force: true });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (foundExtractor) {
|
|
167
|
+
throw new Error("解压失败:安装包格式无效、已损坏或文件清单过大");
|
|
145
168
|
}
|
|
169
|
+
throw new Error("解压失败(需系统 tar 或 unzip 命令)");
|
|
146
170
|
}
|