modern-tar 0.5.2 → 0.5.3
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/dist/fs/index.js +37 -48
- package/package.json +1 -1
package/dist/fs/index.js
CHANGED
|
@@ -6,6 +6,42 @@ import { PassThrough, Readable, Writable } from "node:stream";
|
|
|
6
6
|
import { createWriteStream } from "node:fs";
|
|
7
7
|
import { pipeline } from "node:stream/promises";
|
|
8
8
|
|
|
9
|
+
//#region src/fs/path.ts
|
|
10
|
+
const unicodeCache = /* @__PURE__ */ new Map();
|
|
11
|
+
const normalizeUnicode = (s) => {
|
|
12
|
+
let result = unicodeCache.get(s);
|
|
13
|
+
if (result !== void 0) unicodeCache.delete(s);
|
|
14
|
+
result = result ?? s.normalize("NFD");
|
|
15
|
+
unicodeCache.set(s, result);
|
|
16
|
+
if (unicodeCache.size > 1e4) unicodeCache.delete(unicodeCache.keys().next().value);
|
|
17
|
+
return result;
|
|
18
|
+
};
|
|
19
|
+
function validateBounds(targetPath, destDir, errorMessage) {
|
|
20
|
+
const target = normalizeUnicode(path.resolve(targetPath));
|
|
21
|
+
const dest = path.resolve(destDir);
|
|
22
|
+
if (target !== dest && !target.startsWith(dest + path.sep)) throw new Error(errorMessage);
|
|
23
|
+
}
|
|
24
|
+
const win32Reserved = {
|
|
25
|
+
":": "",
|
|
26
|
+
"<": "",
|
|
27
|
+
">": "",
|
|
28
|
+
"|": "",
|
|
29
|
+
"?": "",
|
|
30
|
+
"*": "",
|
|
31
|
+
"\"": ""
|
|
32
|
+
};
|
|
33
|
+
function normalizeName(name) {
|
|
34
|
+
const path$1 = name.replace(/\\/g, "/");
|
|
35
|
+
if (path$1.split("/").includes("..") || /^[a-zA-Z]:\.\./.test(path$1)) throw new Error(`${name} points outside extraction directory`);
|
|
36
|
+
let relative = path$1;
|
|
37
|
+
if (/^[a-zA-Z]:/.test(relative)) relative = relative.replace(/^[a-zA-Z]:[/\\]?/, "");
|
|
38
|
+
else if (relative.startsWith("/")) relative = relative.replace(/^\/+/, "");
|
|
39
|
+
if (process.platform === "win32") return relative.replace(/[<>:"|?*]/g, (char) => win32Reserved[char]);
|
|
40
|
+
return relative;
|
|
41
|
+
}
|
|
42
|
+
const normalizeHeaderName = (s) => normalizeUnicode(normalizeName(s.replace(/\/+$/, "")));
|
|
43
|
+
|
|
44
|
+
//#endregion
|
|
9
45
|
//#region src/fs/pack.ts
|
|
10
46
|
const packTarSources = packTar;
|
|
11
47
|
function packTar(sources, options = {}) {
|
|
@@ -96,7 +132,7 @@ function packTar(sources, options = {}) {
|
|
|
96
132
|
};
|
|
97
133
|
const processJob = async (job, index) => {
|
|
98
134
|
let jobResult = null;
|
|
99
|
-
const target = job.target
|
|
135
|
+
const target = normalizeName(job.target);
|
|
100
136
|
try {
|
|
101
137
|
if (job.type === "content" || job.type === "stream") {
|
|
102
138
|
let body$1;
|
|
@@ -206,52 +242,6 @@ function packTar(sources, options = {}) {
|
|
|
206
242
|
return stream;
|
|
207
243
|
}
|
|
208
244
|
|
|
209
|
-
//#endregion
|
|
210
|
-
//#region src/fs/win-path.ts
|
|
211
|
-
const REPLACEMENTS = {
|
|
212
|
-
":": "",
|
|
213
|
-
"<": "",
|
|
214
|
-
">": "",
|
|
215
|
-
"|": "",
|
|
216
|
-
"?": "",
|
|
217
|
-
"*": "",
|
|
218
|
-
"\"": ""
|
|
219
|
-
};
|
|
220
|
-
function normalizeWindowsPath(p) {
|
|
221
|
-
if (!(process.platform === "win32")) return p;
|
|
222
|
-
const normalized = p.replace(/\\/g, "/");
|
|
223
|
-
if (/^[A-Za-z]:\.\./i.test(normalized)) throw new Error(`Entry ${p} points outside extraction directory.`);
|
|
224
|
-
return normalized.replace(/^[A-Za-z]:/, "").replace(/[<>:"|?*]/g, (char) => REPLACEMENTS[char]);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
//#endregion
|
|
228
|
-
//#region src/fs/path.ts
|
|
229
|
-
const unicodeCache = /* @__PURE__ */ new Map();
|
|
230
|
-
const normalizeUnicode = (s) => {
|
|
231
|
-
let result = unicodeCache.get(s);
|
|
232
|
-
if (result !== void 0) unicodeCache.delete(s);
|
|
233
|
-
result = result ?? s.normalize("NFD");
|
|
234
|
-
unicodeCache.set(s, result);
|
|
235
|
-
if (unicodeCache.size > 1e4) unicodeCache.delete(unicodeCache.keys().next().value);
|
|
236
|
-
return result;
|
|
237
|
-
};
|
|
238
|
-
function stripTrailingSlashes(p) {
|
|
239
|
-
let i = p.length - 1;
|
|
240
|
-
if (i === -1 || p[i] !== "/") return p;
|
|
241
|
-
let slashesStart = i;
|
|
242
|
-
while (i > -1 && p[i] === "/") {
|
|
243
|
-
slashesStart = i;
|
|
244
|
-
i--;
|
|
245
|
-
}
|
|
246
|
-
return p.slice(0, slashesStart);
|
|
247
|
-
}
|
|
248
|
-
const normalizeHeaderName = (s) => normalizeUnicode(normalizeWindowsPath(stripTrailingSlashes(s)));
|
|
249
|
-
function validateBounds(targetPath, destDir, errorMessage) {
|
|
250
|
-
const target = normalizeUnicode(path.resolve(targetPath));
|
|
251
|
-
const dest = path.resolve(destDir);
|
|
252
|
-
if (target !== dest && !target.startsWith(dest + path.sep)) throw new Error(errorMessage);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
245
|
//#endregion
|
|
256
246
|
//#region src/fs/unpack.ts
|
|
257
247
|
function unpackTar(directoryPath, options = {}) {
|
|
@@ -389,7 +379,6 @@ function createFSHandler(directoryPath, options) {
|
|
|
389
379
|
try {
|
|
390
380
|
const destDir = await destDirPromise;
|
|
391
381
|
if (maxDepth !== Infinity && name.split("/").length > maxDepth) throw new Error("Tar exceeds max specified depth.");
|
|
392
|
-
if (path.isAbsolute(name)) throw new Error(`Absolute path found in "${transformed.name}".`);
|
|
393
382
|
const outPath = path.join(destDir.symbolic, name);
|
|
394
383
|
validateBounds(outPath, destDir.symbolic, `Entry "${transformed.name}" points outside the extraction directory.`);
|
|
395
384
|
const parentDir = path.dirname(outPath);
|