@spzhongwin/skill-logger-plugin 1.0.18 → 1.0.20
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/index.js +2435 -916
- package/openclaw.plugin.json +6 -0
- package/package.json +22 -5
- package/src/free-skill-directory.test.ts +109 -0
- package/src/free-skill-directory.ts +188 -0
- package/src/free-skill-tool.test.ts +68 -0
- package/src/free-skill-tool.ts +99 -0
- package/src/free-skill-workspace.test.ts +109 -0
- package/src/free-skill-workspace.ts +223 -0
- package/src/free-skill-writer.test.ts +105 -0
- package/src/free-skill-writer.ts +591 -0
- package/src/index.ts +5 -0
- package/src/ws-client.test.ts +146 -0
- package/src/ws-client.ts +119 -6
package/dist/index.js
CHANGED
|
@@ -30,28 +30,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
30
|
mod
|
|
31
31
|
));
|
|
32
32
|
|
|
33
|
-
//
|
|
34
|
-
var require_fileSystem = __commonJS({
|
|
35
|
-
"../../node_modules/adm-zip/util/fileSystem.js"(exports) {
|
|
36
|
-
exports.require = function() {
|
|
37
|
-
var fs10 = __require("fs");
|
|
38
|
-
if (process.versions["electron"]) {
|
|
39
|
-
try {
|
|
40
|
-
originalFs = __require("original-fs");
|
|
41
|
-
if (Object.keys(originalFs).length > 0) {
|
|
42
|
-
fs10 = originalFs;
|
|
43
|
-
}
|
|
44
|
-
} catch (e) {
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return fs10;
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
// ../../node_modules/adm-zip/util/constants.js
|
|
33
|
+
// node_modules/adm-zip/util/constants.js
|
|
53
34
|
var require_constants = __commonJS({
|
|
54
|
-
"
|
|
35
|
+
"node_modules/adm-zip/util/constants.js"(exports, module) {
|
|
55
36
|
module.exports = {
|
|
56
37
|
/* The local file header */
|
|
57
38
|
LOCHDR: 30,
|
|
@@ -188,45 +169,54 @@ var require_constants = __commonJS({
|
|
|
188
169
|
// reduced with compression factor 4
|
|
189
170
|
IMPLODED: 6,
|
|
190
171
|
// imploded
|
|
191
|
-
// 7 reserved
|
|
172
|
+
// 7 reserved for Tokenizing compression algorithm
|
|
192
173
|
DEFLATED: 8,
|
|
193
174
|
// deflated
|
|
194
175
|
ENHANCED_DEFLATED: 9,
|
|
195
176
|
// enhanced deflated
|
|
196
177
|
PKWARE: 10,
|
|
197
178
|
// PKWare DCL imploded
|
|
198
|
-
// 11 reserved
|
|
179
|
+
// 11 reserved by PKWARE
|
|
199
180
|
BZIP2: 12,
|
|
200
181
|
// compressed using BZIP2
|
|
201
|
-
// 13 reserved
|
|
182
|
+
// 13 reserved by PKWARE
|
|
202
183
|
LZMA: 14,
|
|
203
184
|
// LZMA
|
|
204
|
-
// 15-17 reserved
|
|
185
|
+
// 15-17 reserved by PKWARE
|
|
205
186
|
IBM_TERSE: 18,
|
|
206
187
|
// compressed using IBM TERSE
|
|
207
188
|
IBM_LZ77: 19,
|
|
208
|
-
//IBM LZ77 z
|
|
189
|
+
// IBM LZ77 z
|
|
190
|
+
AES_ENCRYPT: 99,
|
|
191
|
+
// WinZIP AES encryption method
|
|
209
192
|
/* General purpose bit flag */
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
193
|
+
// values can obtained with expression 2**bitnr
|
|
194
|
+
FLG_ENC: 1,
|
|
195
|
+
// Bit 0: encrypted file
|
|
196
|
+
FLG_COMP1: 2,
|
|
197
|
+
// Bit 1, compression option
|
|
198
|
+
FLG_COMP2: 4,
|
|
199
|
+
// Bit 2, compression option
|
|
200
|
+
FLG_DESC: 8,
|
|
201
|
+
// Bit 3, data descriptor
|
|
202
|
+
FLG_ENH: 16,
|
|
203
|
+
// Bit 4, enhanced deflating
|
|
204
|
+
FLG_PATCH: 32,
|
|
205
|
+
// Bit 5, indicates that the file is compressed patched data.
|
|
206
|
+
FLG_STR: 64,
|
|
207
|
+
// Bit 6, strong encryption (patented)
|
|
208
|
+
// Bits 7-10: Currently unused.
|
|
209
|
+
FLG_EFS: 2048,
|
|
210
|
+
// Bit 11: Language encoding flag (EFS)
|
|
211
|
+
// Bit 12: Reserved by PKWARE for enhanced compression.
|
|
212
|
+
// Bit 13: encrypted the Central Directory (patented).
|
|
213
|
+
// Bits 14-15: Reserved by PKWARE.
|
|
224
214
|
FLG_MSK: 4096,
|
|
225
215
|
// mask header values
|
|
226
216
|
/* Load type */
|
|
227
|
-
FILE:
|
|
217
|
+
FILE: 2,
|
|
228
218
|
BUFFER: 1,
|
|
229
|
-
NONE:
|
|
219
|
+
NONE: 0,
|
|
230
220
|
/* 4.5 Extensible data fields */
|
|
231
221
|
EF_ID: 0,
|
|
232
222
|
EF_SIZE: 2,
|
|
@@ -259,243 +249,370 @@ var require_constants = __commonJS({
|
|
|
259
249
|
}
|
|
260
250
|
});
|
|
261
251
|
|
|
262
|
-
//
|
|
252
|
+
// node_modules/adm-zip/util/errors.js
|
|
263
253
|
var require_errors = __commonJS({
|
|
264
|
-
"
|
|
265
|
-
|
|
254
|
+
"node_modules/adm-zip/util/errors.js"(exports) {
|
|
255
|
+
var errors = {
|
|
266
256
|
/* Header error messages */
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
257
|
+
INVALID_LOC: "Invalid LOC header (bad signature)",
|
|
258
|
+
INVALID_CEN: "Invalid CEN header (bad signature)",
|
|
259
|
+
INVALID_END: "Invalid END header (bad signature)",
|
|
260
|
+
/* Descriptor */
|
|
261
|
+
DESCRIPTOR_NOT_EXIST: "No descriptor present",
|
|
262
|
+
DESCRIPTOR_UNKNOWN: "Unknown descriptor format",
|
|
263
|
+
DESCRIPTOR_FAULTY: "Descriptor data is malformed",
|
|
270
264
|
/* ZipEntry error messages*/
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
265
|
+
NO_DATA: "Nothing to decompress",
|
|
266
|
+
BAD_CRC: "CRC32 checksum failed {0}",
|
|
267
|
+
FILE_IN_THE_WAY: "There is a file in the way: {0}",
|
|
268
|
+
UNKNOWN_METHOD: "Invalid/unsupported compression method",
|
|
275
269
|
/* Inflater error messages */
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
270
|
+
AVAIL_DATA: "inflate::Available inflate data did not terminate",
|
|
271
|
+
INVALID_DISTANCE: "inflate::Invalid literal/length or distance code in fixed or dynamic block",
|
|
272
|
+
TO_MANY_CODES: "inflate::Dynamic block code description: too many length or distance codes",
|
|
273
|
+
INVALID_REPEAT_LEN: "inflate::Dynamic block code description: repeat more than specified lengths",
|
|
274
|
+
INVALID_REPEAT_FIRST: "inflate::Dynamic block code description: repeat lengths with no first length",
|
|
275
|
+
INCOMPLETE_CODES: "inflate::Dynamic block code description: code lengths codes incomplete",
|
|
276
|
+
INVALID_DYN_DISTANCE: "inflate::Dynamic block code description: invalid distance code lengths",
|
|
277
|
+
INVALID_CODES_LEN: "inflate::Dynamic block code description: invalid literal/length code lengths",
|
|
278
|
+
INVALID_STORE_BLOCK: "inflate::Stored block length did not match one's complement",
|
|
279
|
+
INVALID_BLOCK_TYPE: "inflate::Invalid block type (type == 3)",
|
|
286
280
|
/* ADM-ZIP error messages */
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
281
|
+
CANT_EXTRACT_FILE: "Could not extract the file",
|
|
282
|
+
CANT_OVERRIDE: "Target file already exists",
|
|
283
|
+
DISK_ENTRY_TOO_LARGE: "Number of disk entries is too large",
|
|
284
|
+
NO_ZIP: "No zip file was loaded",
|
|
285
|
+
NO_ENTRY: "Entry doesn't exist",
|
|
286
|
+
DIRECTORY_CONTENT_ERROR: "A directory cannot have content",
|
|
287
|
+
FILE_NOT_FOUND: 'File not found: "{0}"',
|
|
288
|
+
NOT_IMPLEMENTED: "Not implemented",
|
|
289
|
+
INVALID_FILENAME: "Invalid filename",
|
|
290
|
+
INVALID_FORMAT: "Invalid or unsupported zip format. No END header found",
|
|
291
|
+
INVALID_PASS_PARAM: "Incompatible password parameter",
|
|
292
|
+
WRONG_PASSWORD: "Wrong Password",
|
|
293
|
+
/* ADM-ZIP */
|
|
294
|
+
COMMENT_TOO_LONG: "Comment is too long",
|
|
295
|
+
// Comment can be max 65535 bytes long (NOTE: some non-US characters may take more space)
|
|
296
|
+
EXTRA_FIELD_PARSE_ERROR: "Extra field parsing error"
|
|
296
297
|
};
|
|
298
|
+
function E(message) {
|
|
299
|
+
return function(...args) {
|
|
300
|
+
if (args.length) {
|
|
301
|
+
message = message.replace(/\{(\d)\}/g, (_, n) => args[n] || "");
|
|
302
|
+
}
|
|
303
|
+
return new Error("ADM-ZIP: " + message);
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
for (const msg of Object.keys(errors)) {
|
|
307
|
+
exports[msg] = E(errors[msg]);
|
|
308
|
+
}
|
|
297
309
|
}
|
|
298
310
|
});
|
|
299
311
|
|
|
300
|
-
//
|
|
312
|
+
// node_modules/adm-zip/util/utils.js
|
|
301
313
|
var require_utils = __commonJS({
|
|
302
|
-
"
|
|
303
|
-
var
|
|
314
|
+
"node_modules/adm-zip/util/utils.js"(exports, module) {
|
|
315
|
+
var fsystem = __require("fs");
|
|
304
316
|
var pth = __require("path");
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
317
|
+
var Constants = require_constants();
|
|
318
|
+
var Errors = require_errors();
|
|
319
|
+
var isWin = typeof process === "object" && "win32" === process.platform;
|
|
320
|
+
var is_Obj = (obj) => typeof obj === "object" && obj !== null;
|
|
321
|
+
var crcTable = new Uint32Array(256).map((t, c) => {
|
|
322
|
+
for (let k = 0; k < 8; k++) {
|
|
323
|
+
if ((c & 1) !== 0) {
|
|
324
|
+
c = 3988292384 ^ c >>> 1;
|
|
325
|
+
} else {
|
|
326
|
+
c >>>= 1;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return c >>> 0;
|
|
330
|
+
});
|
|
331
|
+
function Utils(opts) {
|
|
332
|
+
this.sep = pth.sep;
|
|
333
|
+
this.fs = fsystem;
|
|
334
|
+
if (is_Obj(opts)) {
|
|
335
|
+
if (is_Obj(opts.fs) && typeof opts.fs.statSync === "function") {
|
|
336
|
+
this.fs = opts.fs;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
module.exports = Utils;
|
|
341
|
+
Utils.prototype.makeDir = function(folder) {
|
|
342
|
+
const self = this;
|
|
343
|
+
function mkdirSync(fpath) {
|
|
344
|
+
let resolvedPath = fpath.split(self.sep)[0];
|
|
345
|
+
fpath.split(self.sep).forEach(function(name) {
|
|
311
346
|
if (!name || name.substr(-1, 1) === ":") return;
|
|
312
|
-
resolvedPath +=
|
|
347
|
+
resolvedPath += self.sep + name;
|
|
313
348
|
var stat;
|
|
314
349
|
try {
|
|
315
|
-
stat =
|
|
350
|
+
stat = self.fs.statSync(resolvedPath);
|
|
316
351
|
} catch (e) {
|
|
317
|
-
|
|
352
|
+
if (e.message && e.message.startsWith("ENOENT")) {
|
|
353
|
+
self.fs.mkdirSync(resolvedPath);
|
|
354
|
+
} else {
|
|
355
|
+
throw e;
|
|
356
|
+
}
|
|
318
357
|
}
|
|
319
|
-
if (stat && stat.isFile())
|
|
320
|
-
throw Errors.FILE_IN_THE_WAY.replace("%s", resolvedPath);
|
|
358
|
+
if (stat && stat.isFile()) throw Errors.FILE_IN_THE_WAY(`"${resolvedPath}"`);
|
|
321
359
|
});
|
|
322
360
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
361
|
+
mkdirSync(folder);
|
|
362
|
+
};
|
|
363
|
+
Utils.prototype.writeFileTo = function(path16, content, overwrite, attr) {
|
|
364
|
+
const self = this;
|
|
365
|
+
if (self.fs.existsSync(path16)) {
|
|
366
|
+
if (!overwrite) return false;
|
|
367
|
+
var stat = self.fs.statSync(path16);
|
|
368
|
+
if (stat.isDirectory()) {
|
|
369
|
+
return false;
|
|
327
370
|
}
|
|
328
|
-
var files = [];
|
|
329
|
-
fs10.readdirSync(dir).forEach(function(file) {
|
|
330
|
-
var path12 = pth.join(dir, file);
|
|
331
|
-
if (fs10.statSync(path12).isDirectory() && recoursive)
|
|
332
|
-
files = files.concat(findSync(path12, pattern, recoursive));
|
|
333
|
-
if (!pattern || pattern.test(path12)) {
|
|
334
|
-
files.push(pth.normalize(path12) + (fs10.statSync(path12).isDirectory() ? PATH_SEPARATOR : ""));
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
return files;
|
|
338
371
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
return parseInt(`0x${slice.toString("hex")}`);
|
|
372
|
+
var folder = pth.dirname(path16);
|
|
373
|
+
if (!self.fs.existsSync(folder)) {
|
|
374
|
+
self.makeDir(folder);
|
|
343
375
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
376
|
+
var fd;
|
|
377
|
+
try {
|
|
378
|
+
fd = self.fs.openSync(path16, "w", 438);
|
|
379
|
+
} catch (e) {
|
|
380
|
+
self.fs.chmodSync(path16, 438);
|
|
381
|
+
fd = self.fs.openSync(path16, "w", 438);
|
|
382
|
+
}
|
|
383
|
+
if (fd) {
|
|
384
|
+
try {
|
|
385
|
+
self.fs.writeSync(fd, content, 0, content.length, 0);
|
|
386
|
+
} finally {
|
|
387
|
+
self.fs.closeSync(fd);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
self.fs.chmodSync(path16, attr || 438);
|
|
391
|
+
return true;
|
|
392
|
+
};
|
|
393
|
+
Utils.prototype.writeFileToAsync = function(path16, content, overwrite, attr, callback) {
|
|
394
|
+
if (typeof attr === "function") {
|
|
395
|
+
callback = attr;
|
|
396
|
+
attr = void 0;
|
|
397
|
+
}
|
|
398
|
+
const self = this;
|
|
399
|
+
self.fs.exists(path16, function(exist) {
|
|
400
|
+
if (exist && !overwrite) return callback(false);
|
|
401
|
+
self.fs.stat(path16, function(err, stat) {
|
|
402
|
+
if (exist && stat && stat.isDirectory()) {
|
|
403
|
+
return callback(false);
|
|
351
404
|
}
|
|
352
|
-
var
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
} else {
|
|
360
|
-
c = c >>> 1;
|
|
361
|
-
}
|
|
362
|
-
if (c < 0) {
|
|
363
|
-
b.writeInt32LE(c, 0);
|
|
364
|
-
c = b.readUInt32LE(0);
|
|
405
|
+
var folder = pth.dirname(path16);
|
|
406
|
+
self.fs.exists(folder, function(exists) {
|
|
407
|
+
if (!exists) {
|
|
408
|
+
try {
|
|
409
|
+
self.makeDir(folder);
|
|
410
|
+
} catch (e) {
|
|
411
|
+
return callback(false);
|
|
365
412
|
}
|
|
366
|
-
crcTable[n] = c;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
var crc = 0, off = 0, len = buf.length, c1 = ~crc;
|
|
370
|
-
while (--len >= 0) c1 = crcTable[(c1 ^ buf[off++]) & 255] ^ c1 >>> 8;
|
|
371
|
-
crc = ~c1;
|
|
372
|
-
b.writeInt32LE(crc & 4294967295, 0);
|
|
373
|
-
return b.readUInt32LE(0);
|
|
374
|
-
},
|
|
375
|
-
methodToString: function(method) {
|
|
376
|
-
switch (method) {
|
|
377
|
-
case Constants.STORED:
|
|
378
|
-
return "STORED (" + method + ")";
|
|
379
|
-
case Constants.DEFLATED:
|
|
380
|
-
return "DEFLATED (" + method + ")";
|
|
381
|
-
default:
|
|
382
|
-
return "UNSUPPORTED (" + method + ")";
|
|
383
|
-
}
|
|
384
|
-
},
|
|
385
|
-
writeFileTo: function(path12, content, overwrite, attr) {
|
|
386
|
-
if (fs10.existsSync(path12)) {
|
|
387
|
-
if (!overwrite)
|
|
388
|
-
return false;
|
|
389
|
-
var stat = fs10.statSync(path12);
|
|
390
|
-
if (stat.isDirectory()) {
|
|
391
|
-
return false;
|
|
392
413
|
}
|
|
414
|
+
const writeToFd = function(fd) {
|
|
415
|
+
self.fs.write(fd, content, 0, content.length, 0, function(writeErr) {
|
|
416
|
+
self.fs.close(fd, function() {
|
|
417
|
+
if (writeErr) return callback(false);
|
|
418
|
+
self.fs.chmod(path16, attr || 438, function() {
|
|
419
|
+
callback(true);
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
});
|
|
423
|
+
};
|
|
424
|
+
self.fs.open(path16, "w", 438, function(err2, fd) {
|
|
425
|
+
if (err2) {
|
|
426
|
+
self.fs.chmod(path16, 438, function() {
|
|
427
|
+
self.fs.open(path16, "w", 438, function(retryErr, fd2) {
|
|
428
|
+
if (retryErr || !fd2) return callback(false);
|
|
429
|
+
writeToFd(fd2);
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
} else if (fd) {
|
|
433
|
+
writeToFd(fd);
|
|
434
|
+
} else {
|
|
435
|
+
callback(false);
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
});
|
|
441
|
+
};
|
|
442
|
+
Utils.prototype.findFiles = function(path16) {
|
|
443
|
+
const self = this;
|
|
444
|
+
function findSync(dir, pattern, recursive, visited) {
|
|
445
|
+
if (typeof pattern === "boolean") {
|
|
446
|
+
recursive = pattern;
|
|
447
|
+
pattern = void 0;
|
|
448
|
+
}
|
|
449
|
+
let files = [];
|
|
450
|
+
self.fs.readdirSync(dir).forEach(function(file) {
|
|
451
|
+
const path17 = pth.join(dir, file);
|
|
452
|
+
const stat = self.fs.statSync(path17);
|
|
453
|
+
if (!pattern || pattern.test(path17)) {
|
|
454
|
+
files.push(pth.normalize(path17) + (stat.isDirectory() ? self.sep : ""));
|
|
393
455
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
try {
|
|
400
|
-
fd = fs10.openSync(path12, "w", 438);
|
|
401
|
-
} catch (e) {
|
|
402
|
-
fs10.chmodSync(path12, 438);
|
|
403
|
-
fd = fs10.openSync(path12, "w", 438);
|
|
404
|
-
}
|
|
405
|
-
if (fd) {
|
|
406
|
-
try {
|
|
407
|
-
fs10.writeSync(fd, content, 0, content.length, 0);
|
|
408
|
-
} catch (e) {
|
|
409
|
-
throw e;
|
|
410
|
-
} finally {
|
|
411
|
-
fs10.closeSync(fd);
|
|
456
|
+
if (stat.isDirectory() && recursive) {
|
|
457
|
+
const realDir = self.fs.realpathSync(path17);
|
|
458
|
+
if (!visited.has(realDir)) {
|
|
459
|
+
visited.add(realDir);
|
|
460
|
+
files = files.concat(findSync(path17, pattern, recursive, visited));
|
|
412
461
|
}
|
|
413
462
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
463
|
+
});
|
|
464
|
+
return files;
|
|
465
|
+
}
|
|
466
|
+
return findSync(path16, void 0, true, /* @__PURE__ */ new Set([self.fs.realpathSync(path16)]));
|
|
467
|
+
};
|
|
468
|
+
Utils.prototype.findFilesAsync = function(dir, cb) {
|
|
469
|
+
const self = this;
|
|
470
|
+
const results = [];
|
|
471
|
+
let finished = false;
|
|
472
|
+
const finish = function(err) {
|
|
473
|
+
if (finished) return;
|
|
474
|
+
finished = true;
|
|
475
|
+
cb(err, err ? void 0 : results);
|
|
476
|
+
};
|
|
477
|
+
const walk = function(dir2, visited, done) {
|
|
478
|
+
self.fs.readdir(dir2, function(err, list) {
|
|
479
|
+
if (err) return done(err);
|
|
480
|
+
let pending = list.length;
|
|
481
|
+
if (!pending) return done();
|
|
482
|
+
list.forEach(function(name) {
|
|
483
|
+
const file = pth.join(dir2, name);
|
|
484
|
+
self.fs.stat(file, function(err2, stat) {
|
|
485
|
+
if (err2) return done(err2);
|
|
486
|
+
if (!stat) {
|
|
487
|
+
if (!--pending) done();
|
|
488
|
+
return;
|
|
428
489
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
if (
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
});
|
|
445
|
-
});
|
|
446
|
-
} else {
|
|
447
|
-
if (fd) {
|
|
448
|
-
fs10.write(fd, content, 0, content.length, 0, function() {
|
|
449
|
-
fs10.close(fd, function() {
|
|
450
|
-
fs10.chmod(path12, attr || 438, function() {
|
|
451
|
-
callback(true);
|
|
452
|
-
});
|
|
453
|
-
});
|
|
454
|
-
});
|
|
455
|
-
} else {
|
|
456
|
-
fs10.chmod(path12, attr || 438, function() {
|
|
457
|
-
callback(true);
|
|
458
|
-
});
|
|
459
|
-
}
|
|
460
|
-
}
|
|
490
|
+
results.push(pth.normalize(file) + (stat.isDirectory() ? self.sep : ""));
|
|
491
|
+
if (!stat.isDirectory()) {
|
|
492
|
+
if (!--pending) done();
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
self.fs.realpath(file, function(err3, realDir) {
|
|
496
|
+
if (err3) return done(err3);
|
|
497
|
+
if (visited.has(realDir)) {
|
|
498
|
+
if (!--pending) done();
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
visited.add(realDir);
|
|
502
|
+
walk(file, visited, function(err4) {
|
|
503
|
+
if (err4) return done(err4);
|
|
504
|
+
if (!--pending) done();
|
|
461
505
|
});
|
|
462
506
|
});
|
|
463
507
|
});
|
|
464
508
|
});
|
|
465
|
-
}
|
|
466
|
-
findFiles: function(path12) {
|
|
467
|
-
return findSync(path12, true);
|
|
468
|
-
},
|
|
469
|
-
getAttributes: function(path12) {
|
|
470
|
-
},
|
|
471
|
-
setAttributes: function(path12) {
|
|
472
|
-
},
|
|
473
|
-
toBuffer: function(input) {
|
|
474
|
-
if (Buffer.isBuffer(input)) {
|
|
475
|
-
return input;
|
|
476
|
-
} else {
|
|
477
|
-
if (input.length === 0) {
|
|
478
|
-
return Buffer.alloc(0);
|
|
479
|
-
}
|
|
480
|
-
return Buffer.from(input, "utf8");
|
|
481
|
-
}
|
|
482
|
-
},
|
|
483
|
-
readBigUInt64LE,
|
|
484
|
-
Constants,
|
|
485
|
-
Errors
|
|
509
|
+
});
|
|
486
510
|
};
|
|
487
|
-
|
|
511
|
+
self.fs.realpath(dir, function(err, realDir) {
|
|
512
|
+
if (err) return finish(err);
|
|
513
|
+
walk(dir, /* @__PURE__ */ new Set([realDir]), finish);
|
|
514
|
+
});
|
|
515
|
+
};
|
|
516
|
+
Utils.prototype.getAttributes = function() {
|
|
517
|
+
};
|
|
518
|
+
Utils.prototype.setAttributes = function() {
|
|
519
|
+
};
|
|
520
|
+
Utils.crc32update = function(crc, byte) {
|
|
521
|
+
return crcTable[(crc ^ byte) & 255] ^ crc >>> 8;
|
|
522
|
+
};
|
|
523
|
+
Utils.crc32 = function(buf) {
|
|
524
|
+
if (typeof buf === "string") {
|
|
525
|
+
buf = Buffer.from(buf, "utf8");
|
|
526
|
+
}
|
|
527
|
+
let len = buf.length;
|
|
528
|
+
let crc = ~0;
|
|
529
|
+
for (let off = 0; off < len; ) crc = Utils.crc32update(crc, buf[off++]);
|
|
530
|
+
return ~crc >>> 0;
|
|
531
|
+
};
|
|
532
|
+
Utils.methodToString = function(method) {
|
|
533
|
+
switch (method) {
|
|
534
|
+
case Constants.STORED:
|
|
535
|
+
return "STORED (" + method + ")";
|
|
536
|
+
case Constants.DEFLATED:
|
|
537
|
+
return "DEFLATED (" + method + ")";
|
|
538
|
+
default:
|
|
539
|
+
return "UNSUPPORTED (" + method + ")";
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
Utils.canonical = function(path16) {
|
|
543
|
+
if (!path16) return "";
|
|
544
|
+
const safeSuffix = pth.posix.normalize("/" + path16.split("\\").join("/"));
|
|
545
|
+
return pth.join(".", safeSuffix);
|
|
546
|
+
};
|
|
547
|
+
Utils.zipnamefix = function(path16) {
|
|
548
|
+
if (!path16) return "";
|
|
549
|
+
const safeSuffix = pth.posix.normalize("/" + path16.split("\\").join("/"));
|
|
550
|
+
return pth.posix.join(".", safeSuffix);
|
|
551
|
+
};
|
|
552
|
+
Utils.findLast = function(arr, callback) {
|
|
553
|
+
if (!Array.isArray(arr)) throw new TypeError("arr is not array");
|
|
554
|
+
const len = arr.length >>> 0;
|
|
555
|
+
for (let i = len - 1; i >= 0; i--) {
|
|
556
|
+
if (callback(arr[i], i, arr)) {
|
|
557
|
+
return arr[i];
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return void 0;
|
|
561
|
+
};
|
|
562
|
+
Utils.sanitize = function(prefix, name) {
|
|
563
|
+
prefix = pth.resolve(pth.normalize(prefix));
|
|
564
|
+
var parts = name.split("/");
|
|
565
|
+
for (var i = 0, l = parts.length; i < l; i++) {
|
|
566
|
+
var path16 = pth.normalize(pth.join(prefix, parts.slice(i, l).join(pth.sep)));
|
|
567
|
+
if (path16 === prefix || path16.startsWith(prefix + pth.sep)) {
|
|
568
|
+
return path16;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return pth.normalize(pth.join(prefix, pth.basename(name)));
|
|
572
|
+
};
|
|
573
|
+
Utils.toBuffer = function toBuffer(input, encoder) {
|
|
574
|
+
if (Buffer.isBuffer(input)) {
|
|
575
|
+
return input;
|
|
576
|
+
} else if (input instanceof Uint8Array) {
|
|
577
|
+
return Buffer.from(input);
|
|
578
|
+
} else {
|
|
579
|
+
return typeof input === "string" ? encoder(input) : Buffer.alloc(0);
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
Utils.readBigUInt64LE = function(buffer, index) {
|
|
583
|
+
const lo = buffer.readUInt32LE(index);
|
|
584
|
+
const hi = buffer.readUInt32LE(index + 4);
|
|
585
|
+
return hi * 4294967296 + lo;
|
|
586
|
+
};
|
|
587
|
+
Utils.writeBigUInt64LE = function(buffer, value, index) {
|
|
588
|
+
const lo = value >>> 0;
|
|
589
|
+
const hi = Math.floor(value / 4294967296) >>> 0;
|
|
590
|
+
buffer.writeUInt32LE(lo, index);
|
|
591
|
+
buffer.writeUInt32LE(hi, index + 4);
|
|
592
|
+
};
|
|
593
|
+
Utils.fromDOS2Date = function(val) {
|
|
594
|
+
return new Date((val >> 25 & 127) + 1980, Math.max((val >> 21 & 15) - 1, 0), Math.max(val >> 16 & 31, 1), val >> 11 & 31, val >> 5 & 63, (val & 31) << 1);
|
|
595
|
+
};
|
|
596
|
+
Utils.fromDate2DOS = function(val) {
|
|
597
|
+
let date = 0;
|
|
598
|
+
let time = 0;
|
|
599
|
+
if (val.getFullYear() > 1979) {
|
|
600
|
+
date = (val.getFullYear() - 1980 & 127) << 9 | val.getMonth() + 1 << 5 | val.getDate();
|
|
601
|
+
time = val.getHours() << 11 | val.getMinutes() << 5 | val.getSeconds() >> 1;
|
|
602
|
+
}
|
|
603
|
+
return date << 16 | time;
|
|
604
|
+
};
|
|
605
|
+
Utils.isWin = isWin;
|
|
606
|
+
Utils.crcTable = crcTable;
|
|
488
607
|
}
|
|
489
608
|
});
|
|
490
609
|
|
|
491
|
-
//
|
|
610
|
+
// node_modules/adm-zip/util/fattr.js
|
|
492
611
|
var require_fattr = __commonJS({
|
|
493
|
-
"
|
|
494
|
-
var fs10 = require_fileSystem().require();
|
|
612
|
+
"node_modules/adm-zip/util/fattr.js"(exports, module) {
|
|
495
613
|
var pth = __require("path");
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
var _path = path12 || "", _permissions = 0, _obj = newAttr(), _stat = null;
|
|
614
|
+
module.exports = function(path16, { fs: fs13 }) {
|
|
615
|
+
var _path = path16 || "", _obj = newAttr(), _stat = null;
|
|
499
616
|
function newAttr() {
|
|
500
617
|
return {
|
|
501
618
|
directory: false,
|
|
@@ -506,13 +623,13 @@ var require_fattr = __commonJS({
|
|
|
506
623
|
atime: 0
|
|
507
624
|
};
|
|
508
625
|
}
|
|
509
|
-
if (_path &&
|
|
510
|
-
_stat =
|
|
626
|
+
if (_path && fs13.existsSync(_path)) {
|
|
627
|
+
_stat = fs13.statSync(_path);
|
|
511
628
|
_obj.directory = _stat.isDirectory();
|
|
512
629
|
_obj.mtime = _stat.mtime;
|
|
513
630
|
_obj.atime = _stat.atime;
|
|
514
|
-
_obj.executable =
|
|
515
|
-
_obj.readonly =
|
|
631
|
+
_obj.executable = (73 & _stat.mode) !== 0;
|
|
632
|
+
_obj.readonly = (128 & _stat.mode) === 0;
|
|
516
633
|
_obj.hidden = pth.basename(_path)[0] === ".";
|
|
517
634
|
} else {
|
|
518
635
|
console.warn("Invalid path: " + _path);
|
|
@@ -536,42 +653,67 @@ var require_fattr = __commonJS({
|
|
|
536
653
|
get executable() {
|
|
537
654
|
return _obj.executable;
|
|
538
655
|
},
|
|
539
|
-
decodeAttributes: function(
|
|
656
|
+
decodeAttributes: function() {
|
|
657
|
+
},
|
|
658
|
+
encodeAttributes: function() {
|
|
540
659
|
},
|
|
541
|
-
|
|
660
|
+
toJSON: function() {
|
|
661
|
+
return {
|
|
662
|
+
path: _path,
|
|
663
|
+
isDirectory: _obj.directory,
|
|
664
|
+
isReadOnly: _obj.readonly,
|
|
665
|
+
isHidden: _obj.hidden,
|
|
666
|
+
isExecutable: _obj.executable,
|
|
667
|
+
mTime: _obj.mtime,
|
|
668
|
+
aTime: _obj.atime
|
|
669
|
+
};
|
|
542
670
|
},
|
|
543
671
|
toString: function() {
|
|
544
|
-
return
|
|
672
|
+
return JSON.stringify(this.toJSON(), null, " ");
|
|
545
673
|
}
|
|
546
674
|
};
|
|
547
675
|
};
|
|
548
676
|
}
|
|
549
677
|
});
|
|
550
678
|
|
|
551
|
-
//
|
|
679
|
+
// node_modules/adm-zip/util/decoder.js
|
|
680
|
+
var require_decoder = __commonJS({
|
|
681
|
+
"node_modules/adm-zip/util/decoder.js"(exports, module) {
|
|
682
|
+
module.exports = {
|
|
683
|
+
efs: true,
|
|
684
|
+
encode: (data) => Buffer.from(data, "utf8"),
|
|
685
|
+
decode: (data) => data.toString("utf8")
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
});
|
|
689
|
+
|
|
690
|
+
// node_modules/adm-zip/util/index.js
|
|
552
691
|
var require_util = __commonJS({
|
|
553
|
-
"
|
|
692
|
+
"node_modules/adm-zip/util/index.js"(exports, module) {
|
|
554
693
|
module.exports = require_utils();
|
|
555
|
-
module.exports.FileSystem = require_fileSystem();
|
|
556
694
|
module.exports.Constants = require_constants();
|
|
557
695
|
module.exports.Errors = require_errors();
|
|
558
696
|
module.exports.FileAttr = require_fattr();
|
|
697
|
+
module.exports.decoder = require_decoder();
|
|
559
698
|
}
|
|
560
699
|
});
|
|
561
700
|
|
|
562
|
-
//
|
|
701
|
+
// node_modules/adm-zip/headers/entryHeader.js
|
|
563
702
|
var require_entryHeader = __commonJS({
|
|
564
|
-
"
|
|
703
|
+
"node_modules/adm-zip/headers/entryHeader.js"(exports, module) {
|
|
565
704
|
var Utils = require_util();
|
|
566
705
|
var Constants = Utils.Constants;
|
|
567
706
|
module.exports = function() {
|
|
568
|
-
var _verMade =
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
}
|
|
574
|
-
|
|
707
|
+
var _verMade = 20, _version = 10, _flags = 0, _method = 0, _time = 0, _crc = 0, _compressedSize = 0, _size = 0, _fnameLen = 0, _extraLen = 0, _comLen = 0, _diskStart = 0, _inattr = 0, _attr = 0, _offset = 0;
|
|
708
|
+
_verMade |= Utils.isWin ? 2560 : 768;
|
|
709
|
+
_flags |= Constants.FLG_EFS;
|
|
710
|
+
const _localHeader = {
|
|
711
|
+
extraLen: 0
|
|
712
|
+
};
|
|
713
|
+
const uint32 = (val) => Math.max(0, val) >>> 0;
|
|
714
|
+
const uint16 = (val) => Math.max(0, val) & 65535;
|
|
715
|
+
const uint8 = (val) => Math.max(0, val) & 255;
|
|
716
|
+
_time = Utils.fromDate2DOS(/* @__PURE__ */ new Date());
|
|
575
717
|
return {
|
|
576
718
|
get made() {
|
|
577
719
|
return _verMade;
|
|
@@ -591,42 +733,73 @@ var require_entryHeader = __commonJS({
|
|
|
591
733
|
set flags(val) {
|
|
592
734
|
_flags = val;
|
|
593
735
|
},
|
|
736
|
+
get flags_efs() {
|
|
737
|
+
return (_flags & Constants.FLG_EFS) > 0;
|
|
738
|
+
},
|
|
739
|
+
set flags_efs(val) {
|
|
740
|
+
if (val) {
|
|
741
|
+
_flags |= Constants.FLG_EFS;
|
|
742
|
+
} else {
|
|
743
|
+
_flags &= ~Constants.FLG_EFS;
|
|
744
|
+
}
|
|
745
|
+
},
|
|
746
|
+
get flags_desc() {
|
|
747
|
+
return (_flags & Constants.FLG_DESC) > 0;
|
|
748
|
+
},
|
|
749
|
+
set flags_desc(val) {
|
|
750
|
+
if (val) {
|
|
751
|
+
_flags |= Constants.FLG_DESC;
|
|
752
|
+
} else {
|
|
753
|
+
_flags &= ~Constants.FLG_DESC;
|
|
754
|
+
}
|
|
755
|
+
},
|
|
594
756
|
get method() {
|
|
595
757
|
return _method;
|
|
596
758
|
},
|
|
597
759
|
set method(val) {
|
|
760
|
+
switch (val) {
|
|
761
|
+
case Constants.STORED:
|
|
762
|
+
this.version = 10;
|
|
763
|
+
break;
|
|
764
|
+
case Constants.DEFLATED:
|
|
765
|
+
default:
|
|
766
|
+
this.version = 20;
|
|
767
|
+
}
|
|
598
768
|
_method = val;
|
|
599
769
|
},
|
|
600
770
|
get time() {
|
|
601
|
-
return
|
|
602
|
-
(_time >> 25 & 127) + 1980,
|
|
603
|
-
(_time >> 21 & 15) - 1,
|
|
604
|
-
_time >> 16 & 31,
|
|
605
|
-
_time >> 11 & 31,
|
|
606
|
-
_time >> 5 & 63,
|
|
607
|
-
(_time & 31) << 1
|
|
608
|
-
);
|
|
771
|
+
return Utils.fromDOS2Date(this.timeval);
|
|
609
772
|
},
|
|
610
773
|
set time(val) {
|
|
611
|
-
|
|
774
|
+
val = new Date(val);
|
|
775
|
+
this.timeval = Utils.fromDate2DOS(val);
|
|
776
|
+
},
|
|
777
|
+
get timeval() {
|
|
778
|
+
return _time;
|
|
779
|
+
},
|
|
780
|
+
set timeval(val) {
|
|
781
|
+
_time = uint32(val);
|
|
782
|
+
},
|
|
783
|
+
get timeHighByte() {
|
|
784
|
+
return uint8(_time >>> 8);
|
|
612
785
|
},
|
|
613
786
|
get crc() {
|
|
614
787
|
return _crc;
|
|
615
788
|
},
|
|
616
789
|
set crc(val) {
|
|
617
|
-
_crc = val;
|
|
790
|
+
_crc = uint32(val);
|
|
618
791
|
},
|
|
619
792
|
get compressedSize() {
|
|
620
793
|
return _compressedSize;
|
|
621
794
|
},
|
|
622
795
|
set compressedSize(val) {
|
|
623
|
-
_compressedSize = val;
|
|
796
|
+
_compressedSize = uint32(val);
|
|
624
797
|
},
|
|
625
798
|
get size() {
|
|
626
799
|
return _size;
|
|
627
800
|
},
|
|
628
801
|
set size(val) {
|
|
629
|
-
_size = val;
|
|
802
|
+
_size = uint32(val);
|
|
630
803
|
},
|
|
631
804
|
get fileNameLength() {
|
|
632
805
|
return _fnameLen;
|
|
@@ -640,6 +813,12 @@ var require_entryHeader = __commonJS({
|
|
|
640
813
|
set extraLength(val) {
|
|
641
814
|
_extraLen = val;
|
|
642
815
|
},
|
|
816
|
+
get extraLocalLength() {
|
|
817
|
+
return _localHeader.extraLen;
|
|
818
|
+
},
|
|
819
|
+
set extraLocalLength(val) {
|
|
820
|
+
_localHeader.extraLen = val;
|
|
821
|
+
},
|
|
643
822
|
get commentLength() {
|
|
644
823
|
return _comLen;
|
|
645
824
|
},
|
|
@@ -650,67 +829,64 @@ var require_entryHeader = __commonJS({
|
|
|
650
829
|
return _diskStart;
|
|
651
830
|
},
|
|
652
831
|
set diskNumStart(val) {
|
|
653
|
-
_diskStart = val;
|
|
832
|
+
_diskStart = uint32(val);
|
|
654
833
|
},
|
|
655
834
|
get inAttr() {
|
|
656
835
|
return _inattr;
|
|
657
836
|
},
|
|
658
837
|
set inAttr(val) {
|
|
659
|
-
_inattr = val;
|
|
838
|
+
_inattr = uint32(val);
|
|
660
839
|
},
|
|
661
840
|
get attr() {
|
|
662
841
|
return _attr;
|
|
663
842
|
},
|
|
664
843
|
set attr(val) {
|
|
665
|
-
_attr = val;
|
|
844
|
+
_attr = uint32(val);
|
|
845
|
+
},
|
|
846
|
+
// get Unix file permissions
|
|
847
|
+
get fileAttr() {
|
|
848
|
+
return (_attr || 0) >> 16 & 4095;
|
|
666
849
|
},
|
|
667
850
|
get offset() {
|
|
668
851
|
return _offset;
|
|
669
852
|
},
|
|
670
853
|
set offset(val) {
|
|
671
|
-
_offset = val;
|
|
854
|
+
_offset = uint32(val);
|
|
672
855
|
},
|
|
673
|
-
get
|
|
674
|
-
return (_flags &
|
|
856
|
+
get encrypted() {
|
|
857
|
+
return (_flags & Constants.FLG_ENC) === Constants.FLG_ENC;
|
|
675
858
|
},
|
|
676
|
-
get
|
|
859
|
+
get centralHeaderSize() {
|
|
677
860
|
return Constants.CENHDR + _fnameLen + _extraLen + _comLen;
|
|
678
861
|
},
|
|
679
862
|
get realDataOffset() {
|
|
680
|
-
return _offset + Constants.LOCHDR +
|
|
863
|
+
return _offset + Constants.LOCHDR + _localHeader.fnameLen + _localHeader.extraLen;
|
|
681
864
|
},
|
|
682
|
-
get
|
|
683
|
-
return
|
|
865
|
+
get localHeader() {
|
|
866
|
+
return _localHeader;
|
|
684
867
|
},
|
|
685
|
-
|
|
868
|
+
loadLocalHeaderFromBinary: function(input) {
|
|
686
869
|
var data = input.slice(_offset, _offset + Constants.LOCHDR);
|
|
687
870
|
if (data.readUInt32LE(0) !== Constants.LOCSIG) {
|
|
688
|
-
throw
|
|
871
|
+
throw Utils.Errors.INVALID_LOC();
|
|
689
872
|
}
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
// uncompressed size
|
|
704
|
-
size: data.readUInt32LE(Constants.LOCLEN),
|
|
705
|
-
// filename length
|
|
706
|
-
fnameLen: data.readUInt16LE(Constants.LOCNAM),
|
|
707
|
-
// extra field length
|
|
708
|
-
extraLen: data.readUInt16LE(Constants.LOCEXT)
|
|
709
|
-
};
|
|
873
|
+
_localHeader.version = data.readUInt16LE(Constants.LOCVER);
|
|
874
|
+
_localHeader.flags = data.readUInt16LE(Constants.LOCFLG);
|
|
875
|
+
_localHeader.flags_desc = (_localHeader.flags & Constants.FLG_DESC) > 0;
|
|
876
|
+
_localHeader.method = data.readUInt16LE(Constants.LOCHOW);
|
|
877
|
+
_localHeader.time = data.readUInt32LE(Constants.LOCTIM);
|
|
878
|
+
_localHeader.crc = data.readUInt32LE(Constants.LOCCRC);
|
|
879
|
+
_localHeader.compressedSize = data.readUInt32LE(Constants.LOCSIZ);
|
|
880
|
+
_localHeader.size = data.readUInt32LE(Constants.LOCLEN);
|
|
881
|
+
_localHeader.fnameLen = data.readUInt16LE(Constants.LOCNAM);
|
|
882
|
+
_localHeader.extraLen = data.readUInt16LE(Constants.LOCEXT);
|
|
883
|
+
const extraStart = _offset + Constants.LOCHDR + _localHeader.fnameLen;
|
|
884
|
+
const extraEnd = extraStart + _localHeader.extraLen;
|
|
885
|
+
return input.slice(extraStart, extraEnd);
|
|
710
886
|
},
|
|
711
887
|
loadFromBinary: function(data) {
|
|
712
888
|
if (data.length !== Constants.CENHDR || data.readUInt32LE(0) !== Constants.CENSIG) {
|
|
713
|
-
throw
|
|
889
|
+
throw Utils.Errors.INVALID_CEN();
|
|
714
890
|
}
|
|
715
891
|
_verMade = data.readUInt16LE(Constants.CENVEM);
|
|
716
892
|
_version = data.readUInt16LE(Constants.CENVER);
|
|
@@ -728,26 +904,26 @@ var require_entryHeader = __commonJS({
|
|
|
728
904
|
_attr = data.readUInt32LE(Constants.CENATX);
|
|
729
905
|
_offset = data.readUInt32LE(Constants.CENOFF);
|
|
730
906
|
},
|
|
731
|
-
|
|
907
|
+
localHeaderToBinary: function() {
|
|
732
908
|
var data = Buffer.alloc(Constants.LOCHDR);
|
|
733
909
|
data.writeUInt32LE(Constants.LOCSIG, 0);
|
|
734
910
|
data.writeUInt16LE(_version, Constants.LOCVER);
|
|
735
|
-
data.writeUInt16LE(_flags, Constants.LOCFLG);
|
|
911
|
+
data.writeUInt16LE(_flags & ~Constants.FLG_DESC, Constants.LOCFLG);
|
|
736
912
|
data.writeUInt16LE(_method, Constants.LOCHOW);
|
|
737
913
|
data.writeUInt32LE(_time, Constants.LOCTIM);
|
|
738
914
|
data.writeUInt32LE(_crc, Constants.LOCCRC);
|
|
739
915
|
data.writeUInt32LE(_compressedSize, Constants.LOCSIZ);
|
|
740
916
|
data.writeUInt32LE(_size, Constants.LOCLEN);
|
|
741
917
|
data.writeUInt16LE(_fnameLen, Constants.LOCNAM);
|
|
742
|
-
data.writeUInt16LE(
|
|
918
|
+
data.writeUInt16LE(_localHeader.extraLen, Constants.LOCEXT);
|
|
743
919
|
return data;
|
|
744
920
|
},
|
|
745
|
-
|
|
921
|
+
centralHeaderToBinary: function() {
|
|
746
922
|
var data = Buffer.alloc(Constants.CENHDR + _fnameLen + _extraLen + _comLen);
|
|
747
923
|
data.writeUInt32LE(Constants.CENSIG, 0);
|
|
748
924
|
data.writeUInt16LE(_verMade, Constants.CENVEM);
|
|
749
925
|
data.writeUInt16LE(_version, Constants.CENVER);
|
|
750
|
-
data.writeUInt16LE(_flags, Constants.CENFLG);
|
|
926
|
+
data.writeUInt16LE(_flags & ~Constants.FLG_DESC, Constants.CENFLG);
|
|
751
927
|
data.writeUInt16LE(_method, Constants.CENHOW);
|
|
752
928
|
data.writeUInt32LE(_time, Constants.CENTIM);
|
|
753
929
|
data.writeUInt32LE(_crc, Constants.CENCRC);
|
|
@@ -760,24 +936,47 @@ var require_entryHeader = __commonJS({
|
|
|
760
936
|
data.writeUInt16LE(_inattr, Constants.CENATT);
|
|
761
937
|
data.writeUInt32LE(_attr, Constants.CENATX);
|
|
762
938
|
data.writeUInt32LE(_offset, Constants.CENOFF);
|
|
763
|
-
data.fill(0, Constants.CENHDR);
|
|
764
939
|
return data;
|
|
765
940
|
},
|
|
941
|
+
toJSON: function() {
|
|
942
|
+
const bytes = function(nr) {
|
|
943
|
+
return nr + " bytes";
|
|
944
|
+
};
|
|
945
|
+
return {
|
|
946
|
+
made: _verMade,
|
|
947
|
+
version: _version,
|
|
948
|
+
flags: _flags,
|
|
949
|
+
method: Utils.methodToString(_method),
|
|
950
|
+
time: this.time,
|
|
951
|
+
crc: "0x" + _crc.toString(16).toUpperCase(),
|
|
952
|
+
compressedSize: bytes(_compressedSize),
|
|
953
|
+
size: bytes(_size),
|
|
954
|
+
fileNameLength: bytes(_fnameLen),
|
|
955
|
+
extraLength: bytes(_extraLen),
|
|
956
|
+
commentLength: bytes(_comLen),
|
|
957
|
+
diskNumStart: _diskStart,
|
|
958
|
+
inAttr: _inattr,
|
|
959
|
+
attr: _attr,
|
|
960
|
+
offset: _offset,
|
|
961
|
+
centralHeaderSize: bytes(Constants.CENHDR + _fnameLen + _extraLen + _comLen)
|
|
962
|
+
};
|
|
963
|
+
},
|
|
766
964
|
toString: function() {
|
|
767
|
-
return
|
|
965
|
+
return JSON.stringify(this.toJSON(), null, " ");
|
|
768
966
|
}
|
|
769
967
|
};
|
|
770
968
|
};
|
|
771
969
|
}
|
|
772
970
|
});
|
|
773
971
|
|
|
774
|
-
//
|
|
972
|
+
// node_modules/adm-zip/headers/mainHeader.js
|
|
775
973
|
var require_mainHeader = __commonJS({
|
|
776
|
-
"
|
|
974
|
+
"node_modules/adm-zip/headers/mainHeader.js"(exports, module) {
|
|
777
975
|
var Utils = require_util();
|
|
778
976
|
var Constants = Utils.Constants;
|
|
779
977
|
module.exports = function() {
|
|
780
978
|
var _volumeEntries = 0, _totalEntries = 0, _size = 0, _offset = 0, _commentLength = 0;
|
|
979
|
+
const needsZip64 = () => _volumeEntries > Constants.EF_ZIP64_OR_16 || _totalEntries > Constants.EF_ZIP64_OR_16 || _size > Constants.EF_ZIP64_OR_32 || _offset > Constants.EF_ZIP64_OR_32;
|
|
781
980
|
return {
|
|
782
981
|
get diskEntries() {
|
|
783
982
|
return _volumeEntries;
|
|
@@ -810,11 +1009,11 @@ var require_mainHeader = __commonJS({
|
|
|
810
1009
|
_commentLength = val;
|
|
811
1010
|
},
|
|
812
1011
|
get mainHeaderSize() {
|
|
813
|
-
return Constants.ENDHDR + _commentLength;
|
|
1012
|
+
return (needsZip64() ? Constants.ZIP64HDR + Constants.END64HDR : 0) + Constants.ENDHDR + _commentLength;
|
|
814
1013
|
},
|
|
815
1014
|
loadFromBinary: function(data) {
|
|
816
1015
|
if ((data.length !== Constants.ENDHDR || data.readUInt32LE(0) !== Constants.ENDSIG) && (data.length < Constants.ZIP64HDR || data.readUInt32LE(0) !== Constants.ZIP64SIG)) {
|
|
817
|
-
throw
|
|
1016
|
+
throw Utils.Errors.INVALID_END();
|
|
818
1017
|
}
|
|
819
1018
|
if (data.readUInt32LE(0) === Constants.ENDSIG) {
|
|
820
1019
|
_volumeEntries = data.readUInt16LE(Constants.ENDSUB);
|
|
@@ -825,42 +1024,86 @@ var require_mainHeader = __commonJS({
|
|
|
825
1024
|
} else {
|
|
826
1025
|
_volumeEntries = Utils.readBigUInt64LE(data, Constants.ZIP64SUB);
|
|
827
1026
|
_totalEntries = Utils.readBigUInt64LE(data, Constants.ZIP64TOT);
|
|
828
|
-
_size = Utils.readBigUInt64LE(data, Constants.
|
|
1027
|
+
_size = Utils.readBigUInt64LE(data, Constants.ZIP64SIZB);
|
|
829
1028
|
_offset = Utils.readBigUInt64LE(data, Constants.ZIP64OFF);
|
|
830
1029
|
_commentLength = 0;
|
|
831
1030
|
}
|
|
832
1031
|
},
|
|
833
1032
|
toBinary: function() {
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
1033
|
+
if (!needsZip64()) {
|
|
1034
|
+
var b = Buffer.alloc(Constants.ENDHDR + _commentLength);
|
|
1035
|
+
b.writeUInt32LE(Constants.ENDSIG, 0);
|
|
1036
|
+
b.writeUInt32LE(0, 4);
|
|
1037
|
+
b.writeUInt16LE(_volumeEntries, Constants.ENDSUB);
|
|
1038
|
+
b.writeUInt16LE(_totalEntries, Constants.ENDTOT);
|
|
1039
|
+
b.writeUInt32LE(_size, Constants.ENDSIZ);
|
|
1040
|
+
b.writeUInt32LE(_offset, Constants.ENDOFF);
|
|
1041
|
+
b.writeUInt16LE(_commentLength, Constants.ENDCOM);
|
|
1042
|
+
b.fill(" ", Constants.ENDHDR);
|
|
1043
|
+
return b;
|
|
1044
|
+
}
|
|
1045
|
+
var b = Buffer.alloc(this.mainHeaderSize);
|
|
1046
|
+
let offset = 0;
|
|
1047
|
+
b.writeUInt32LE(Constants.ZIP64SIG, offset);
|
|
1048
|
+
Utils.writeBigUInt64LE(b, Constants.ZIP64HDR - Constants.ZIP64LEAD, offset + Constants.ZIP64SIZE);
|
|
1049
|
+
b.writeUInt16LE(45, offset + Constants.ZIP64VEM);
|
|
1050
|
+
b.writeUInt16LE(45, offset + Constants.ZIP64VER);
|
|
1051
|
+
b.writeUInt32LE(0, offset + Constants.ZIP64DSK);
|
|
1052
|
+
b.writeUInt32LE(0, offset + Constants.ZIP64DSKDIR);
|
|
1053
|
+
Utils.writeBigUInt64LE(b, _volumeEntries, offset + Constants.ZIP64SUB);
|
|
1054
|
+
Utils.writeBigUInt64LE(b, _totalEntries, offset + Constants.ZIP64TOT);
|
|
1055
|
+
Utils.writeBigUInt64LE(b, _size, offset + Constants.ZIP64SIZB);
|
|
1056
|
+
Utils.writeBigUInt64LE(b, _offset, offset + Constants.ZIP64OFF);
|
|
1057
|
+
const zip64EndOffset = _offset + _size;
|
|
1058
|
+
offset += Constants.ZIP64HDR;
|
|
1059
|
+
b.writeUInt32LE(Constants.END64SIG, offset);
|
|
1060
|
+
b.writeUInt32LE(0, offset + Constants.END64START);
|
|
1061
|
+
Utils.writeBigUInt64LE(b, zip64EndOffset, offset + Constants.END64OFF);
|
|
1062
|
+
b.writeUInt32LE(1, offset + Constants.END64NUMDISKS);
|
|
1063
|
+
offset += Constants.END64HDR;
|
|
1064
|
+
b.writeUInt32LE(Constants.ENDSIG, offset);
|
|
1065
|
+
b.writeUInt32LE(0, offset + 4);
|
|
1066
|
+
b.writeUInt16LE(Math.min(_volumeEntries, Constants.EF_ZIP64_OR_16), offset + Constants.ENDSUB);
|
|
1067
|
+
b.writeUInt16LE(Math.min(_totalEntries, Constants.EF_ZIP64_OR_16), offset + Constants.ENDTOT);
|
|
1068
|
+
b.writeUInt32LE(Math.min(_size, Constants.EF_ZIP64_OR_32), offset + Constants.ENDSIZ);
|
|
1069
|
+
b.writeUInt32LE(Math.min(_offset, Constants.EF_ZIP64_OR_32), offset + Constants.ENDOFF);
|
|
1070
|
+
b.writeUInt16LE(_commentLength, offset + Constants.ENDCOM);
|
|
1071
|
+
b.fill(" ", offset + Constants.ENDHDR);
|
|
843
1072
|
return b;
|
|
844
1073
|
},
|
|
1074
|
+
toJSON: function() {
|
|
1075
|
+
const offset = function(nr, len) {
|
|
1076
|
+
let offs = nr.toString(16).toUpperCase();
|
|
1077
|
+
while (offs.length < len) offs = "0" + offs;
|
|
1078
|
+
return "0x" + offs;
|
|
1079
|
+
};
|
|
1080
|
+
return {
|
|
1081
|
+
diskEntries: _volumeEntries,
|
|
1082
|
+
totalEntries: _totalEntries,
|
|
1083
|
+
size: _size + " bytes",
|
|
1084
|
+
offset: offset(_offset, 4),
|
|
1085
|
+
commentLength: _commentLength
|
|
1086
|
+
};
|
|
1087
|
+
},
|
|
845
1088
|
toString: function() {
|
|
846
|
-
return
|
|
1089
|
+
return JSON.stringify(this.toJSON(), null, " ");
|
|
847
1090
|
}
|
|
848
1091
|
};
|
|
849
1092
|
};
|
|
850
1093
|
}
|
|
851
1094
|
});
|
|
852
1095
|
|
|
853
|
-
//
|
|
1096
|
+
// node_modules/adm-zip/headers/index.js
|
|
854
1097
|
var require_headers = __commonJS({
|
|
855
|
-
"
|
|
1098
|
+
"node_modules/adm-zip/headers/index.js"(exports) {
|
|
856
1099
|
exports.EntryHeader = require_entryHeader();
|
|
857
1100
|
exports.MainHeader = require_mainHeader();
|
|
858
1101
|
}
|
|
859
1102
|
});
|
|
860
1103
|
|
|
861
|
-
//
|
|
1104
|
+
// node_modules/adm-zip/methods/deflater.js
|
|
862
1105
|
var require_deflater = __commonJS({
|
|
863
|
-
"
|
|
1106
|
+
"node_modules/adm-zip/methods/deflater.js"(exports, module) {
|
|
864
1107
|
module.exports = function(inbuf) {
|
|
865
1108
|
var zlib = __require("zlib");
|
|
866
1109
|
var opts = { chunkSize: (parseInt(inbuf.length / 1024) + 1) * 1024 };
|
|
@@ -891,17 +1134,19 @@ var require_deflater = __commonJS({
|
|
|
891
1134
|
}
|
|
892
1135
|
});
|
|
893
1136
|
|
|
894
|
-
//
|
|
1137
|
+
// node_modules/adm-zip/methods/inflater.js
|
|
895
1138
|
var require_inflater = __commonJS({
|
|
896
|
-
"
|
|
897
|
-
|
|
1139
|
+
"node_modules/adm-zip/methods/inflater.js"(exports, module) {
|
|
1140
|
+
var version = +(process?.versions?.node ?? "").split(".")[0] || 0;
|
|
1141
|
+
module.exports = function(inbuf, expectedLength) {
|
|
898
1142
|
var zlib = __require("zlib");
|
|
1143
|
+
const option = version >= 15 && expectedLength > 0 ? { maxOutputLength: expectedLength } : {};
|
|
899
1144
|
return {
|
|
900
1145
|
inflate: function() {
|
|
901
|
-
return zlib.inflateRawSync(inbuf);
|
|
1146
|
+
return zlib.inflateRawSync(inbuf, option);
|
|
902
1147
|
},
|
|
903
1148
|
inflateAsync: function(callback) {
|
|
904
|
-
var tmp = zlib.createInflateRaw(), parts = [], total = 0;
|
|
1149
|
+
var tmp = zlib.createInflateRaw(option), parts = [], total = 0;
|
|
905
1150
|
tmp.on("data", function(data) {
|
|
906
1151
|
parts.push(data);
|
|
907
1152
|
total += data.length;
|
|
@@ -923,38 +1168,153 @@ var require_inflater = __commonJS({
|
|
|
923
1168
|
}
|
|
924
1169
|
});
|
|
925
1170
|
|
|
926
|
-
//
|
|
1171
|
+
// node_modules/adm-zip/methods/zipcrypto.js
|
|
1172
|
+
var require_zipcrypto = __commonJS({
|
|
1173
|
+
"node_modules/adm-zip/methods/zipcrypto.js"(exports, module) {
|
|
1174
|
+
"use strict";
|
|
1175
|
+
var { randomFillSync } = __require("crypto");
|
|
1176
|
+
var Errors = require_errors();
|
|
1177
|
+
var crctable = new Uint32Array(256).map((t, crc) => {
|
|
1178
|
+
for (let j = 0; j < 8; j++) {
|
|
1179
|
+
if (0 !== (crc & 1)) {
|
|
1180
|
+
crc = crc >>> 1 ^ 3988292384;
|
|
1181
|
+
} else {
|
|
1182
|
+
crc >>>= 1;
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
return crc >>> 0;
|
|
1186
|
+
});
|
|
1187
|
+
var uMul = (a, b) => Math.imul(a, b) >>> 0;
|
|
1188
|
+
var crc32update = (pCrc32, bval) => {
|
|
1189
|
+
return crctable[(pCrc32 ^ bval) & 255] ^ pCrc32 >>> 8;
|
|
1190
|
+
};
|
|
1191
|
+
var genSalt = () => {
|
|
1192
|
+
if ("function" === typeof randomFillSync) {
|
|
1193
|
+
return randomFillSync(Buffer.alloc(12));
|
|
1194
|
+
} else {
|
|
1195
|
+
return genSalt.node();
|
|
1196
|
+
}
|
|
1197
|
+
};
|
|
1198
|
+
genSalt.node = () => {
|
|
1199
|
+
const salt = Buffer.alloc(12);
|
|
1200
|
+
const len = salt.length;
|
|
1201
|
+
for (let i = 0; i < len; i++) salt[i] = Math.random() * 256 & 255;
|
|
1202
|
+
return salt;
|
|
1203
|
+
};
|
|
1204
|
+
var config = {
|
|
1205
|
+
genSalt
|
|
1206
|
+
};
|
|
1207
|
+
function Initkeys(pw) {
|
|
1208
|
+
const pass = Buffer.isBuffer(pw) ? pw : Buffer.from(pw);
|
|
1209
|
+
this.keys = new Uint32Array([305419896, 591751049, 878082192]);
|
|
1210
|
+
for (let i = 0; i < pass.length; i++) {
|
|
1211
|
+
this.updateKeys(pass[i]);
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
Initkeys.prototype.updateKeys = function(byteValue) {
|
|
1215
|
+
const keys = this.keys;
|
|
1216
|
+
keys[0] = crc32update(keys[0], byteValue);
|
|
1217
|
+
keys[1] += keys[0] & 255;
|
|
1218
|
+
keys[1] = uMul(keys[1], 134775813) + 1;
|
|
1219
|
+
keys[2] = crc32update(keys[2], keys[1] >>> 24);
|
|
1220
|
+
return byteValue;
|
|
1221
|
+
};
|
|
1222
|
+
Initkeys.prototype.next = function() {
|
|
1223
|
+
const k = (this.keys[2] | 2) >>> 0;
|
|
1224
|
+
return uMul(k, k ^ 1) >> 8 & 255;
|
|
1225
|
+
};
|
|
1226
|
+
function make_decrypter(pwd) {
|
|
1227
|
+
const keys = new Initkeys(pwd);
|
|
1228
|
+
return function(data) {
|
|
1229
|
+
const result = Buffer.alloc(data.length);
|
|
1230
|
+
let pos = 0;
|
|
1231
|
+
for (let c of data) {
|
|
1232
|
+
result[pos++] = keys.updateKeys(c ^ keys.next());
|
|
1233
|
+
}
|
|
1234
|
+
return result;
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
function make_encrypter(pwd) {
|
|
1238
|
+
const keys = new Initkeys(pwd);
|
|
1239
|
+
return function(data, result, pos = 0) {
|
|
1240
|
+
if (!result) result = Buffer.alloc(data.length);
|
|
1241
|
+
for (let c of data) {
|
|
1242
|
+
const k = keys.next();
|
|
1243
|
+
result[pos++] = c ^ k;
|
|
1244
|
+
keys.updateKeys(c);
|
|
1245
|
+
}
|
|
1246
|
+
return result;
|
|
1247
|
+
};
|
|
1248
|
+
}
|
|
1249
|
+
function decrypt(data, header, pwd) {
|
|
1250
|
+
if (!data || !Buffer.isBuffer(data) || data.length < 12) {
|
|
1251
|
+
return Buffer.alloc(0);
|
|
1252
|
+
}
|
|
1253
|
+
const decrypter = make_decrypter(pwd);
|
|
1254
|
+
const salt = decrypter(data.slice(0, 12));
|
|
1255
|
+
const verifyByte = (header.flags & 8) === 8 ? header.timeHighByte : header.crc >>> 24;
|
|
1256
|
+
if (salt[11] !== verifyByte) {
|
|
1257
|
+
throw Errors.WRONG_PASSWORD();
|
|
1258
|
+
}
|
|
1259
|
+
return decrypter(data.slice(12));
|
|
1260
|
+
}
|
|
1261
|
+
function _salter(data) {
|
|
1262
|
+
if (Buffer.isBuffer(data) && data.length >= 12) {
|
|
1263
|
+
config.genSalt = function() {
|
|
1264
|
+
return data.slice(0, 12);
|
|
1265
|
+
};
|
|
1266
|
+
} else if (data === "node") {
|
|
1267
|
+
config.genSalt = genSalt.node;
|
|
1268
|
+
} else {
|
|
1269
|
+
config.genSalt = genSalt;
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
function encrypt(data, header, pwd, oldlike = false) {
|
|
1273
|
+
if (data == null) data = Buffer.alloc(0);
|
|
1274
|
+
if (!Buffer.isBuffer(data)) data = Buffer.from(data.toString());
|
|
1275
|
+
const encrypter = make_encrypter(pwd);
|
|
1276
|
+
const salt = config.genSalt();
|
|
1277
|
+
salt[11] = header.crc >>> 24 & 255;
|
|
1278
|
+
if (oldlike) salt[10] = header.crc >>> 16 & 255;
|
|
1279
|
+
const result = Buffer.alloc(data.length + 12);
|
|
1280
|
+
encrypter(salt, result);
|
|
1281
|
+
return encrypter(data, result, 12);
|
|
1282
|
+
}
|
|
1283
|
+
module.exports = { decrypt, encrypt, _salter };
|
|
1284
|
+
}
|
|
1285
|
+
});
|
|
1286
|
+
|
|
1287
|
+
// node_modules/adm-zip/methods/index.js
|
|
927
1288
|
var require_methods = __commonJS({
|
|
928
|
-
"
|
|
1289
|
+
"node_modules/adm-zip/methods/index.js"(exports) {
|
|
929
1290
|
exports.Deflater = require_deflater();
|
|
930
1291
|
exports.Inflater = require_inflater();
|
|
1292
|
+
exports.ZipCrypto = require_zipcrypto();
|
|
931
1293
|
}
|
|
932
1294
|
});
|
|
933
1295
|
|
|
934
|
-
//
|
|
1296
|
+
// node_modules/adm-zip/zipEntry.js
|
|
935
1297
|
var require_zipEntry = __commonJS({
|
|
936
|
-
"
|
|
1298
|
+
"node_modules/adm-zip/zipEntry.js"(exports, module) {
|
|
937
1299
|
var Utils = require_util();
|
|
938
1300
|
var Headers = require_headers();
|
|
939
1301
|
var Constants = Utils.Constants;
|
|
940
1302
|
var Methods = require_methods();
|
|
941
|
-
module.exports = function(input) {
|
|
942
|
-
var
|
|
1303
|
+
module.exports = function(options, input) {
|
|
1304
|
+
var _centralHeader = new Headers.EntryHeader(), _entryName = Buffer.alloc(0), _comment = Buffer.alloc(0), _isDirectory = false, uncompressedData = null, _extra = Buffer.alloc(0), _extralocal = Buffer.alloc(0), _efs = true;
|
|
1305
|
+
const opts = options;
|
|
1306
|
+
const decoder = typeof opts.decoder === "object" ? opts.decoder : Utils.decoder;
|
|
1307
|
+
_efs = decoder.hasOwnProperty("efs") ? decoder.efs : false;
|
|
943
1308
|
function getCompressedDataFromZip() {
|
|
944
|
-
if (!input || !
|
|
1309
|
+
if (!input || !(input instanceof Uint8Array)) {
|
|
945
1310
|
return Buffer.alloc(0);
|
|
946
1311
|
}
|
|
947
|
-
|
|
948
|
-
return input.slice(
|
|
1312
|
+
_extralocal = _centralHeader.loadLocalHeaderFromBinary(input);
|
|
1313
|
+
return input.slice(_centralHeader.realDataOffset, _centralHeader.realDataOffset + _centralHeader.compressedSize);
|
|
949
1314
|
}
|
|
950
1315
|
function crc32OK(data) {
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
return false;
|
|
954
|
-
}
|
|
955
|
-
} else {
|
|
956
|
-
}
|
|
957
|
-
return true;
|
|
1316
|
+
const expectedCrc = _centralHeader.flags_desc || _centralHeader.localHeader.flags_desc ? _centralHeader.crc : _centralHeader.localHeader.crc;
|
|
1317
|
+
return Utils.crc32(data) === expectedCrc;
|
|
958
1318
|
}
|
|
959
1319
|
function decompress(async, callback, pass) {
|
|
960
1320
|
if (typeof callback === "undefined" && typeof async === "string") {
|
|
@@ -963,7 +1323,7 @@ var require_zipEntry = __commonJS({
|
|
|
963
1323
|
}
|
|
964
1324
|
if (_isDirectory) {
|
|
965
1325
|
if (async && callback) {
|
|
966
|
-
callback(Buffer.alloc(0), Utils.Errors.DIRECTORY_CONTENT_ERROR);
|
|
1326
|
+
callback(Buffer.alloc(0), Utils.Errors.DIRECTORY_CONTENT_ERROR());
|
|
967
1327
|
}
|
|
968
1328
|
return Buffer.alloc(0);
|
|
969
1329
|
}
|
|
@@ -972,40 +1332,47 @@ var require_zipEntry = __commonJS({
|
|
|
972
1332
|
if (async && callback) callback(compressedData);
|
|
973
1333
|
return compressedData;
|
|
974
1334
|
}
|
|
975
|
-
|
|
976
|
-
|
|
1335
|
+
if (_centralHeader.encrypted) {
|
|
1336
|
+
if ("string" !== typeof pass && !Buffer.isBuffer(pass)) {
|
|
1337
|
+
throw Utils.Errors.INVALID_PASS_PARAM();
|
|
1338
|
+
}
|
|
1339
|
+
compressedData = Methods.ZipCrypto.decrypt(compressedData, _centralHeader, pass);
|
|
1340
|
+
}
|
|
1341
|
+
var data;
|
|
1342
|
+
switch (_centralHeader.method) {
|
|
977
1343
|
case Utils.Constants.STORED:
|
|
1344
|
+
data = Buffer.alloc(compressedData.length);
|
|
978
1345
|
compressedData.copy(data);
|
|
979
1346
|
if (!crc32OK(data)) {
|
|
980
|
-
if (async && callback) callback(data, Utils.Errors.BAD_CRC);
|
|
981
|
-
throw
|
|
1347
|
+
if (async && callback) callback(data, Utils.Errors.BAD_CRC());
|
|
1348
|
+
throw Utils.Errors.BAD_CRC();
|
|
982
1349
|
} else {
|
|
983
1350
|
if (async && callback) callback(data);
|
|
984
1351
|
return data;
|
|
985
1352
|
}
|
|
986
1353
|
case Utils.Constants.DEFLATED:
|
|
987
|
-
var inflater = new Methods.Inflater(compressedData);
|
|
1354
|
+
var inflater = new Methods.Inflater(compressedData, _centralHeader.size);
|
|
988
1355
|
if (!async) {
|
|
989
|
-
|
|
990
|
-
result.copy(data, 0);
|
|
1356
|
+
data = inflater.inflate();
|
|
991
1357
|
if (!crc32OK(data)) {
|
|
992
|
-
throw
|
|
1358
|
+
throw Utils.Errors.BAD_CRC(`"${decoder.decode(_entryName)}"`);
|
|
993
1359
|
}
|
|
994
1360
|
return data;
|
|
995
1361
|
} else {
|
|
996
|
-
inflater.inflateAsync(function(
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1362
|
+
inflater.inflateAsync(function(result) {
|
|
1363
|
+
if (callback) {
|
|
1364
|
+
if (!crc32OK(result)) {
|
|
1365
|
+
callback(result, Utils.Errors.BAD_CRC());
|
|
1366
|
+
} else {
|
|
1367
|
+
callback(result);
|
|
1368
|
+
}
|
|
1002
1369
|
}
|
|
1003
1370
|
});
|
|
1004
1371
|
}
|
|
1005
1372
|
break;
|
|
1006
1373
|
default:
|
|
1007
|
-
if (async && callback) callback(Buffer.alloc(0), Utils.Errors.UNKNOWN_METHOD);
|
|
1008
|
-
throw
|
|
1374
|
+
if (async && callback) callback(Buffer.alloc(0), Utils.Errors.UNKNOWN_METHOD());
|
|
1375
|
+
throw Utils.Errors.UNKNOWN_METHOD();
|
|
1009
1376
|
}
|
|
1010
1377
|
}
|
|
1011
1378
|
function compress(async, callback) {
|
|
@@ -1015,9 +1382,9 @@ var require_zipEntry = __commonJS({
|
|
|
1015
1382
|
}
|
|
1016
1383
|
if (uncompressedData.length && !_isDirectory) {
|
|
1017
1384
|
var compressedData;
|
|
1018
|
-
switch (
|
|
1385
|
+
switch (_centralHeader.method) {
|
|
1019
1386
|
case Utils.Constants.STORED:
|
|
1020
|
-
|
|
1387
|
+
_centralHeader.compressedSize = _centralHeader.size;
|
|
1021
1388
|
compressedData = Buffer.alloc(uncompressedData.length);
|
|
1022
1389
|
uncompressedData.copy(compressedData);
|
|
1023
1390
|
if (async && callback) callback(compressedData);
|
|
@@ -1027,12 +1394,12 @@ var require_zipEntry = __commonJS({
|
|
|
1027
1394
|
var deflater = new Methods.Deflater(uncompressedData);
|
|
1028
1395
|
if (!async) {
|
|
1029
1396
|
var deflated = deflater.deflate();
|
|
1030
|
-
|
|
1397
|
+
_centralHeader.compressedSize = deflated.length;
|
|
1031
1398
|
return deflated;
|
|
1032
1399
|
} else {
|
|
1033
1400
|
deflater.deflateAsync(function(data) {
|
|
1034
1401
|
compressedData = Buffer.alloc(data.length);
|
|
1035
|
-
|
|
1402
|
+
_centralHeader.compressedSize = data.length;
|
|
1036
1403
|
data.copy(compressedData);
|
|
1037
1404
|
callback && callback(compressedData);
|
|
1038
1405
|
});
|
|
@@ -1040,90 +1407,100 @@ var require_zipEntry = __commonJS({
|
|
|
1040
1407
|
deflater = null;
|
|
1041
1408
|
break;
|
|
1042
1409
|
}
|
|
1410
|
+
} else if (async && callback) {
|
|
1411
|
+
callback(Buffer.alloc(0));
|
|
1043
1412
|
} else {
|
|
1044
|
-
|
|
1045
|
-
callback(Buffer.alloc(0));
|
|
1046
|
-
} else {
|
|
1047
|
-
return Buffer.alloc(0);
|
|
1048
|
-
}
|
|
1413
|
+
return Buffer.alloc(0);
|
|
1049
1414
|
}
|
|
1050
1415
|
}
|
|
1051
1416
|
function readUInt64LE(buffer, offset) {
|
|
1052
|
-
return (buffer
|
|
1417
|
+
return Utils.readBigUInt64LE(buffer, offset);
|
|
1053
1418
|
}
|
|
1054
1419
|
function parseExtra(data) {
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1420
|
+
try {
|
|
1421
|
+
var offset = 0;
|
|
1422
|
+
var signature, size, part;
|
|
1423
|
+
while (offset + 4 < data.length) {
|
|
1424
|
+
signature = data.readUInt16LE(offset);
|
|
1425
|
+
offset += 2;
|
|
1426
|
+
size = data.readUInt16LE(offset);
|
|
1427
|
+
offset += 2;
|
|
1428
|
+
part = data.slice(offset, offset + size);
|
|
1429
|
+
offset += size;
|
|
1430
|
+
if (Constants.ID_ZIP64 === signature) {
|
|
1431
|
+
parseZip64ExtendedInformation(part);
|
|
1432
|
+
}
|
|
1066
1433
|
}
|
|
1434
|
+
} catch (error) {
|
|
1435
|
+
throw Utils.Errors.EXTRA_FIELD_PARSE_ERROR();
|
|
1067
1436
|
}
|
|
1068
1437
|
}
|
|
1069
1438
|
function parseZip64ExtendedInformation(data) {
|
|
1070
1439
|
var size, compressedSize, offset, diskNumStart;
|
|
1071
1440
|
if (data.length >= Constants.EF_ZIP64_SCOMP) {
|
|
1072
1441
|
size = readUInt64LE(data, Constants.EF_ZIP64_SUNCOMP);
|
|
1073
|
-
if (
|
|
1074
|
-
|
|
1442
|
+
if (_centralHeader.size === Constants.EF_ZIP64_OR_32) {
|
|
1443
|
+
_centralHeader.size = size;
|
|
1075
1444
|
}
|
|
1076
1445
|
}
|
|
1077
1446
|
if (data.length >= Constants.EF_ZIP64_RHO) {
|
|
1078
1447
|
compressedSize = readUInt64LE(data, Constants.EF_ZIP64_SCOMP);
|
|
1079
|
-
if (
|
|
1080
|
-
|
|
1448
|
+
if (_centralHeader.compressedSize === Constants.EF_ZIP64_OR_32) {
|
|
1449
|
+
_centralHeader.compressedSize = compressedSize;
|
|
1081
1450
|
}
|
|
1082
1451
|
}
|
|
1083
1452
|
if (data.length >= Constants.EF_ZIP64_DSN) {
|
|
1084
1453
|
offset = readUInt64LE(data, Constants.EF_ZIP64_RHO);
|
|
1085
|
-
if (
|
|
1086
|
-
|
|
1454
|
+
if (_centralHeader.offset === Constants.EF_ZIP64_OR_32) {
|
|
1455
|
+
_centralHeader.offset = offset;
|
|
1087
1456
|
}
|
|
1088
1457
|
}
|
|
1089
1458
|
if (data.length >= Constants.EF_ZIP64_DSN + 4) {
|
|
1090
1459
|
diskNumStart = data.readUInt32LE(Constants.EF_ZIP64_DSN);
|
|
1091
|
-
if (
|
|
1092
|
-
|
|
1460
|
+
if (_centralHeader.diskNumStart === Constants.EF_ZIP64_OR_16) {
|
|
1461
|
+
_centralHeader.diskNumStart = diskNumStart;
|
|
1093
1462
|
}
|
|
1094
1463
|
}
|
|
1095
1464
|
}
|
|
1096
1465
|
return {
|
|
1097
1466
|
get entryName() {
|
|
1098
|
-
return
|
|
1467
|
+
return decoder.decode(_entryName);
|
|
1099
1468
|
},
|
|
1100
1469
|
get rawEntryName() {
|
|
1101
1470
|
return _entryName;
|
|
1102
1471
|
},
|
|
1103
1472
|
set entryName(val) {
|
|
1104
|
-
_entryName = Utils.toBuffer(val);
|
|
1473
|
+
_entryName = Utils.toBuffer(val, decoder.encode);
|
|
1105
1474
|
var lastChar = _entryName[_entryName.length - 1];
|
|
1106
1475
|
_isDirectory = lastChar === 47 || lastChar === 92;
|
|
1107
|
-
|
|
1476
|
+
_centralHeader.fileNameLength = _entryName.length;
|
|
1477
|
+
},
|
|
1478
|
+
get efs() {
|
|
1479
|
+
if (typeof _efs === "function") {
|
|
1480
|
+
return _efs(this.entryName);
|
|
1481
|
+
} else {
|
|
1482
|
+
return _efs;
|
|
1483
|
+
}
|
|
1108
1484
|
},
|
|
1109
1485
|
get extra() {
|
|
1110
1486
|
return _extra;
|
|
1111
1487
|
},
|
|
1112
1488
|
set extra(val) {
|
|
1113
1489
|
_extra = val;
|
|
1114
|
-
|
|
1490
|
+
_centralHeader.extraLength = val.length;
|
|
1115
1491
|
parseExtra(val);
|
|
1116
1492
|
},
|
|
1117
1493
|
get comment() {
|
|
1118
|
-
return
|
|
1494
|
+
return decoder.decode(_comment);
|
|
1119
1495
|
},
|
|
1120
1496
|
set comment(val) {
|
|
1121
|
-
_comment = Utils.toBuffer(val);
|
|
1122
|
-
|
|
1497
|
+
_comment = Utils.toBuffer(val, decoder.encode);
|
|
1498
|
+
_centralHeader.commentLength = _comment.length;
|
|
1499
|
+
if (_comment.length > 65535) throw Utils.Errors.COMMENT_TOO_LONG();
|
|
1123
1500
|
},
|
|
1124
1501
|
get name() {
|
|
1125
|
-
|
|
1126
|
-
return _isDirectory ? n.
|
|
1502
|
+
const n = decoder.decode(_entryName);
|
|
1503
|
+
return _isDirectory ? n.replace(/[/\\]$/, "").split("/").pop() : n.split("/").pop();
|
|
1127
1504
|
},
|
|
1128
1505
|
get isDirectory() {
|
|
1129
1506
|
return _isDirectory;
|
|
@@ -1135,112 +1512,157 @@ var require_zipEntry = __commonJS({
|
|
|
1135
1512
|
compress(true, callback);
|
|
1136
1513
|
},
|
|
1137
1514
|
setData: function(value) {
|
|
1138
|
-
uncompressedData = Utils.toBuffer(value);
|
|
1515
|
+
uncompressedData = Utils.toBuffer(value, Utils.decoder.encode);
|
|
1139
1516
|
if (!_isDirectory && uncompressedData.length) {
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1517
|
+
_centralHeader.size = uncompressedData.length;
|
|
1518
|
+
_centralHeader.method = Utils.Constants.DEFLATED;
|
|
1519
|
+
_centralHeader.crc = Utils.crc32(value);
|
|
1520
|
+
_centralHeader.changed = true;
|
|
1144
1521
|
} else {
|
|
1145
|
-
|
|
1522
|
+
_centralHeader.method = Utils.Constants.STORED;
|
|
1146
1523
|
}
|
|
1147
1524
|
},
|
|
1148
1525
|
getData: function(pass) {
|
|
1149
|
-
if (
|
|
1526
|
+
if (_centralHeader.changed) {
|
|
1150
1527
|
return uncompressedData;
|
|
1151
1528
|
} else {
|
|
1152
1529
|
return decompress(false, null, pass);
|
|
1153
1530
|
}
|
|
1154
1531
|
},
|
|
1155
1532
|
getDataAsync: function(callback, pass) {
|
|
1156
|
-
if (
|
|
1533
|
+
if (_centralHeader.changed) {
|
|
1157
1534
|
callback(uncompressedData);
|
|
1158
1535
|
} else {
|
|
1159
1536
|
decompress(true, callback, pass);
|
|
1160
1537
|
}
|
|
1161
1538
|
},
|
|
1162
1539
|
set attr(attr) {
|
|
1163
|
-
|
|
1540
|
+
_centralHeader.attr = attr;
|
|
1164
1541
|
},
|
|
1165
1542
|
get attr() {
|
|
1166
|
-
return
|
|
1543
|
+
return _centralHeader.attr;
|
|
1167
1544
|
},
|
|
1168
1545
|
set header(data) {
|
|
1169
|
-
|
|
1546
|
+
_centralHeader.loadFromBinary(data);
|
|
1170
1547
|
},
|
|
1171
1548
|
get header() {
|
|
1172
|
-
return
|
|
1549
|
+
return _centralHeader;
|
|
1173
1550
|
},
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1551
|
+
packCentralHeader: function() {
|
|
1552
|
+
_centralHeader.flags_efs = this.efs;
|
|
1553
|
+
_centralHeader.extraLength = _extra.length;
|
|
1554
|
+
var header = _centralHeader.centralHeaderToBinary();
|
|
1555
|
+
var addpos = Utils.Constants.CENHDR;
|
|
1556
|
+
_entryName.copy(header, addpos);
|
|
1557
|
+
addpos += _entryName.length;
|
|
1558
|
+
_extra.copy(header, addpos);
|
|
1559
|
+
addpos += _centralHeader.extraLength;
|
|
1560
|
+
_comment.copy(header, addpos);
|
|
1183
1561
|
return header;
|
|
1184
1562
|
},
|
|
1563
|
+
packLocalHeader: function() {
|
|
1564
|
+
let addpos = 0;
|
|
1565
|
+
_centralHeader.flags_efs = this.efs;
|
|
1566
|
+
_centralHeader.extraLocalLength = _extralocal.length;
|
|
1567
|
+
const localHeaderBuf = _centralHeader.localHeaderToBinary();
|
|
1568
|
+
const localHeader = Buffer.alloc(localHeaderBuf.length + _entryName.length + _centralHeader.extraLocalLength);
|
|
1569
|
+
localHeaderBuf.copy(localHeader, addpos);
|
|
1570
|
+
addpos += localHeaderBuf.length;
|
|
1571
|
+
_entryName.copy(localHeader, addpos);
|
|
1572
|
+
addpos += _entryName.length;
|
|
1573
|
+
_extralocal.copy(localHeader, addpos);
|
|
1574
|
+
addpos += _extralocal.length;
|
|
1575
|
+
return localHeader;
|
|
1576
|
+
},
|
|
1577
|
+
toJSON: function() {
|
|
1578
|
+
const bytes = function(nr) {
|
|
1579
|
+
return "<" + (nr && nr.length + " bytes buffer" || "null") + ">";
|
|
1580
|
+
};
|
|
1581
|
+
return {
|
|
1582
|
+
entryName: this.entryName,
|
|
1583
|
+
name: this.name,
|
|
1584
|
+
comment: this.comment,
|
|
1585
|
+
isDirectory: this.isDirectory,
|
|
1586
|
+
header: _centralHeader.toJSON(),
|
|
1587
|
+
compressedData: bytes(input),
|
|
1588
|
+
data: bytes(uncompressedData)
|
|
1589
|
+
};
|
|
1590
|
+
},
|
|
1185
1591
|
toString: function() {
|
|
1186
|
-
return
|
|
1592
|
+
return JSON.stringify(this.toJSON(), null, " ");
|
|
1187
1593
|
}
|
|
1188
1594
|
};
|
|
1189
1595
|
};
|
|
1190
1596
|
}
|
|
1191
1597
|
});
|
|
1192
1598
|
|
|
1193
|
-
//
|
|
1599
|
+
// node_modules/adm-zip/zipFile.js
|
|
1194
1600
|
var require_zipFile = __commonJS({
|
|
1195
|
-
"
|
|
1601
|
+
"node_modules/adm-zip/zipFile.js"(exports, module) {
|
|
1196
1602
|
var ZipEntry = require_zipEntry();
|
|
1197
1603
|
var Headers = require_headers();
|
|
1198
1604
|
var Utils = require_util();
|
|
1199
|
-
module.exports = function(
|
|
1200
|
-
var entryList = [], entryTable =
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
readMainHeader();
|
|
1605
|
+
module.exports = function(inBuffer, options) {
|
|
1606
|
+
var entryList = [], entryTable = /* @__PURE__ */ Object.create(null), _comment = Buffer.alloc(0), mainHeader = new Headers.MainHeader(), loadedEntries = false;
|
|
1607
|
+
var password = null;
|
|
1608
|
+
const temporary = /* @__PURE__ */ new Set();
|
|
1609
|
+
const opts = options;
|
|
1610
|
+
const { noSort, decoder } = opts;
|
|
1611
|
+
if (inBuffer) {
|
|
1612
|
+
readMainHeader(opts.readEntries);
|
|
1208
1613
|
} else {
|
|
1209
1614
|
loadedEntries = true;
|
|
1210
1615
|
}
|
|
1211
|
-
function
|
|
1212
|
-
const
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1616
|
+
function makeTemporaryFolders() {
|
|
1617
|
+
const foldersList = /* @__PURE__ */ new Set();
|
|
1618
|
+
for (const elem of Object.keys(entryTable)) {
|
|
1619
|
+
const elements = elem.split("/");
|
|
1620
|
+
elements.pop();
|
|
1621
|
+
if (!elements.length) continue;
|
|
1622
|
+
for (let i = 0; i < elements.length; i++) {
|
|
1623
|
+
const sub = elements.slice(0, i + 1).join("/") + "/";
|
|
1624
|
+
foldersList.add(sub);
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
for (const elem of foldersList) {
|
|
1628
|
+
if (!(elem in entryTable)) {
|
|
1629
|
+
const tempfolder = new ZipEntry(opts);
|
|
1630
|
+
tempfolder.entryName = elem;
|
|
1631
|
+
tempfolder.attr = 16;
|
|
1632
|
+
tempfolder.temporary = true;
|
|
1633
|
+
entryList.push(tempfolder);
|
|
1634
|
+
entryTable[tempfolder.entryName] = tempfolder;
|
|
1635
|
+
temporary.add(tempfolder);
|
|
1636
|
+
}
|
|
1221
1637
|
}
|
|
1222
1638
|
}
|
|
1223
1639
|
function readEntries() {
|
|
1224
1640
|
loadedEntries = true;
|
|
1225
|
-
entryTable =
|
|
1641
|
+
entryTable = /* @__PURE__ */ Object.create(null);
|
|
1642
|
+
if (mainHeader.diskEntries > (inBuffer.length - mainHeader.offset) / Utils.Constants.CENHDR) {
|
|
1643
|
+
throw Utils.Errors.DISK_ENTRY_TOO_LARGE();
|
|
1644
|
+
}
|
|
1226
1645
|
entryList = new Array(mainHeader.diskEntries);
|
|
1227
1646
|
var index = mainHeader.offset;
|
|
1228
1647
|
for (var i = 0; i < entryList.length; i++) {
|
|
1229
|
-
var tmp = index, entry = new ZipEntry(inBuffer);
|
|
1648
|
+
var tmp = index, entry = new ZipEntry(opts, inBuffer);
|
|
1230
1649
|
entry.header = inBuffer.slice(tmp, tmp += Utils.Constants.CENHDR);
|
|
1231
1650
|
entry.entryName = inBuffer.slice(tmp, tmp += entry.header.fileNameLength);
|
|
1232
1651
|
if (entry.header.extraLength) {
|
|
1233
1652
|
entry.extra = inBuffer.slice(tmp, tmp += entry.header.extraLength);
|
|
1234
1653
|
}
|
|
1235
|
-
if (entry.header.commentLength)
|
|
1236
|
-
|
|
1237
|
-
index += entry.header.entryHeaderSize;
|
|
1654
|
+
if (entry.header.commentLength) entry.comment = inBuffer.slice(tmp, tmp + entry.header.commentLength);
|
|
1655
|
+
index += entry.header.centralHeaderSize;
|
|
1238
1656
|
entryList[i] = entry;
|
|
1239
1657
|
entryTable[entry.entryName] = entry;
|
|
1240
1658
|
}
|
|
1659
|
+
temporary.clear();
|
|
1660
|
+
makeTemporaryFolders();
|
|
1241
1661
|
}
|
|
1242
|
-
function readMainHeader() {
|
|
1662
|
+
function readMainHeader(readNow) {
|
|
1243
1663
|
var i = inBuffer.length - Utils.Constants.ENDHDR, max = Math.max(0, i - 65535), n = max, endStart = inBuffer.length, endOffset = -1, commentEnd = 0;
|
|
1664
|
+
const trailingSpace = typeof opts.trailingSpace === "boolean" ? opts.trailingSpace : false;
|
|
1665
|
+
if (trailingSpace) max = 0;
|
|
1244
1666
|
for (i; i >= n; i--) {
|
|
1245
1667
|
if (inBuffer[i] !== 80) continue;
|
|
1246
1668
|
if (inBuffer.readUInt32LE(i) === Utils.Constants.ENDSIG) {
|
|
@@ -1254,18 +1676,23 @@ var require_zipFile = __commonJS({
|
|
|
1254
1676
|
n = max;
|
|
1255
1677
|
continue;
|
|
1256
1678
|
}
|
|
1257
|
-
if (inBuffer.readUInt32LE(i)
|
|
1679
|
+
if (inBuffer.readUInt32LE(i) === Utils.Constants.ZIP64SIG) {
|
|
1258
1680
|
endOffset = i;
|
|
1259
1681
|
endStart = i + Utils.readBigUInt64LE(inBuffer, i + Utils.Constants.ZIP64SIZE) + Utils.Constants.ZIP64LEAD;
|
|
1260
1682
|
break;
|
|
1261
1683
|
}
|
|
1262
1684
|
}
|
|
1263
|
-
if (
|
|
1264
|
-
throw new Error(Utils.Errors.INVALID_FORMAT);
|
|
1685
|
+
if (endOffset == -1) throw Utils.Errors.INVALID_FORMAT();
|
|
1265
1686
|
mainHeader.loadFromBinary(inBuffer.slice(endOffset, endStart));
|
|
1266
1687
|
if (mainHeader.commentLength) {
|
|
1267
1688
|
_comment = inBuffer.slice(commentEnd + Utils.Constants.ENDHDR);
|
|
1268
1689
|
}
|
|
1690
|
+
if (readNow) readEntries();
|
|
1691
|
+
}
|
|
1692
|
+
function sortEntries() {
|
|
1693
|
+
if (entryList.length > 1 && !noSort) {
|
|
1694
|
+
entryList = entryList.map((entry) => ({ entry, key: entry.entryName.toLowerCase() })).sort((a, b) => a.key.localeCompare(b.key)).map((pair) => pair.entry);
|
|
1695
|
+
}
|
|
1269
1696
|
}
|
|
1270
1697
|
return {
|
|
1271
1698
|
/**
|
|
@@ -1276,18 +1703,18 @@ var require_zipFile = __commonJS({
|
|
|
1276
1703
|
if (!loadedEntries) {
|
|
1277
1704
|
readEntries();
|
|
1278
1705
|
}
|
|
1279
|
-
return entryList;
|
|
1706
|
+
return entryList.filter((e) => !temporary.has(e));
|
|
1280
1707
|
},
|
|
1281
1708
|
/**
|
|
1282
1709
|
* Archive comment
|
|
1283
1710
|
* @return {String}
|
|
1284
1711
|
*/
|
|
1285
1712
|
get comment() {
|
|
1286
|
-
return
|
|
1713
|
+
return decoder.decode(_comment);
|
|
1287
1714
|
},
|
|
1288
1715
|
set comment(val) {
|
|
1289
|
-
|
|
1290
|
-
|
|
1716
|
+
_comment = Utils.toBuffer(val, decoder.encode);
|
|
1717
|
+
mainHeader.commentLength = _comment.length;
|
|
1291
1718
|
},
|
|
1292
1719
|
getEntryCount: function() {
|
|
1293
1720
|
if (!loadedEntries) {
|
|
@@ -1296,11 +1723,7 @@ var require_zipFile = __commonJS({
|
|
|
1296
1723
|
return entryList.length;
|
|
1297
1724
|
},
|
|
1298
1725
|
forEach: function(callback) {
|
|
1299
|
-
|
|
1300
|
-
iterateEntries(callback);
|
|
1301
|
-
return;
|
|
1302
|
-
}
|
|
1303
|
-
entryList.forEach(callback);
|
|
1726
|
+
this.entries.forEach(callback);
|
|
1304
1727
|
},
|
|
1305
1728
|
/**
|
|
1306
1729
|
* Returns a reference to the entry with the given name or null if entry is inexistent
|
|
@@ -1328,27 +1751,37 @@ var require_zipFile = __commonJS({
|
|
|
1328
1751
|
mainHeader.totalEntries = entryList.length;
|
|
1329
1752
|
},
|
|
1330
1753
|
/**
|
|
1331
|
-
* Removes the
|
|
1754
|
+
* Removes the file with the given name from the entry list.
|
|
1332
1755
|
*
|
|
1333
1756
|
* If the entry is a directory, then all nested files and directories will be removed
|
|
1334
1757
|
* @param entryName
|
|
1758
|
+
* @returns {void}
|
|
1759
|
+
*/
|
|
1760
|
+
deleteFile: function(entryName, withsubfolders = true) {
|
|
1761
|
+
if (!loadedEntries) {
|
|
1762
|
+
readEntries();
|
|
1763
|
+
}
|
|
1764
|
+
const entry = entryTable[entryName];
|
|
1765
|
+
const list = this.getEntryChildren(entry, withsubfolders).map((child) => child.entryName);
|
|
1766
|
+
list.forEach(this.deleteEntry);
|
|
1767
|
+
},
|
|
1768
|
+
/**
|
|
1769
|
+
* Removes the entry with the given name from the entry list.
|
|
1770
|
+
*
|
|
1771
|
+
* @param {string} entryName
|
|
1772
|
+
* @returns {void}
|
|
1335
1773
|
*/
|
|
1336
1774
|
deleteEntry: function(entryName) {
|
|
1337
1775
|
if (!loadedEntries) {
|
|
1338
1776
|
readEntries();
|
|
1339
1777
|
}
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
}
|
|
1347
|
-
});
|
|
1778
|
+
const entry = entryTable[entryName];
|
|
1779
|
+
const index = entryList.indexOf(entry);
|
|
1780
|
+
if (index >= 0) {
|
|
1781
|
+
entryList.splice(index, 1);
|
|
1782
|
+
delete entryTable[entryName];
|
|
1783
|
+
mainHeader.totalEntries = entryList.length;
|
|
1348
1784
|
}
|
|
1349
|
-
entryList.splice(entryList.indexOf(entry), 1);
|
|
1350
|
-
delete entryTable[entryName];
|
|
1351
|
-
mainHeader.totalEntries = entryList.length;
|
|
1352
1785
|
},
|
|
1353
1786
|
/**
|
|
1354
1787
|
* Iterates and returns all nested files and directories of the given entry
|
|
@@ -1356,21 +1789,39 @@ var require_zipFile = __commonJS({
|
|
|
1356
1789
|
* @param entry
|
|
1357
1790
|
* @return Array
|
|
1358
1791
|
*/
|
|
1359
|
-
getEntryChildren: function(entry) {
|
|
1792
|
+
getEntryChildren: function(entry, subfolders = true) {
|
|
1360
1793
|
if (!loadedEntries) {
|
|
1361
1794
|
readEntries();
|
|
1362
1795
|
}
|
|
1363
|
-
if (entry
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1796
|
+
if (typeof entry === "object") {
|
|
1797
|
+
if (entry.isDirectory && subfolders) {
|
|
1798
|
+
const list = [];
|
|
1799
|
+
const name = entry.entryName;
|
|
1800
|
+
for (const zipEntry of entryList) {
|
|
1801
|
+
if (zipEntry.entryName.startsWith(name)) {
|
|
1802
|
+
list.push(zipEntry);
|
|
1803
|
+
}
|
|
1368
1804
|
}
|
|
1369
|
-
|
|
1370
|
-
|
|
1805
|
+
return list;
|
|
1806
|
+
} else {
|
|
1807
|
+
return [entry];
|
|
1808
|
+
}
|
|
1371
1809
|
}
|
|
1372
1810
|
return [];
|
|
1373
1811
|
},
|
|
1812
|
+
/**
|
|
1813
|
+
* How many child elements entry has
|
|
1814
|
+
*
|
|
1815
|
+
* @param {ZipEntry} entry
|
|
1816
|
+
* @return {integer}
|
|
1817
|
+
*/
|
|
1818
|
+
getChildCount: function(entry) {
|
|
1819
|
+
if (entry && entry.isDirectory) {
|
|
1820
|
+
const list = this.getEntryChildren(entry);
|
|
1821
|
+
return list.includes(entry) ? list.length - 1 : list.length;
|
|
1822
|
+
}
|
|
1823
|
+
return 0;
|
|
1824
|
+
},
|
|
1374
1825
|
/**
|
|
1375
1826
|
* Returns the zip file
|
|
1376
1827
|
*
|
|
@@ -1380,200 +1831,229 @@ var require_zipFile = __commonJS({
|
|
|
1380
1831
|
if (!loadedEntries) {
|
|
1381
1832
|
readEntries();
|
|
1382
1833
|
}
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
return -1;
|
|
1389
|
-
}
|
|
1390
|
-
if (nameA > nameB) {
|
|
1391
|
-
return 1;
|
|
1392
|
-
}
|
|
1393
|
-
return 0;
|
|
1394
|
-
});
|
|
1395
|
-
}
|
|
1396
|
-
var totalSize = 0, dataBlock = [], entryHeaders = [], dindex = 0;
|
|
1834
|
+
sortEntries();
|
|
1835
|
+
const dataBlock = [];
|
|
1836
|
+
const headerBlocks = [];
|
|
1837
|
+
let totalSize = 0;
|
|
1838
|
+
let dindex = 0;
|
|
1397
1839
|
mainHeader.size = 0;
|
|
1398
1840
|
mainHeader.offset = 0;
|
|
1399
|
-
|
|
1400
|
-
|
|
1841
|
+
let totalEntries = 0;
|
|
1842
|
+
for (const entry of this.entries) {
|
|
1843
|
+
const compressedData = entry.getCompressedData();
|
|
1401
1844
|
entry.header.offset = dindex;
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
var extra = entry.extra.toString();
|
|
1405
|
-
var postHeader = Buffer.alloc(entryNameLen + extra.length);
|
|
1406
|
-
entry.rawEntryName.copy(postHeader, 0);
|
|
1407
|
-
postHeader.fill(extra, entryNameLen);
|
|
1408
|
-
var dataLength = dataHeader.length + postHeader.length + compressedData.length;
|
|
1845
|
+
const localHeader = entry.packLocalHeader();
|
|
1846
|
+
const dataLength = localHeader.length + compressedData.length;
|
|
1409
1847
|
dindex += dataLength;
|
|
1410
|
-
dataBlock.push(
|
|
1411
|
-
dataBlock.push(postHeader);
|
|
1848
|
+
dataBlock.push(localHeader);
|
|
1412
1849
|
dataBlock.push(compressedData);
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
mainHeader.size +=
|
|
1416
|
-
totalSize += dataLength +
|
|
1417
|
-
|
|
1850
|
+
const centralHeader = entry.packCentralHeader();
|
|
1851
|
+
headerBlocks.push(centralHeader);
|
|
1852
|
+
mainHeader.size += centralHeader.length;
|
|
1853
|
+
totalSize += dataLength + centralHeader.length;
|
|
1854
|
+
totalEntries++;
|
|
1855
|
+
}
|
|
1418
1856
|
totalSize += mainHeader.mainHeaderSize;
|
|
1419
1857
|
mainHeader.offset = dindex;
|
|
1858
|
+
mainHeader.totalEntries = totalEntries;
|
|
1420
1859
|
dindex = 0;
|
|
1421
|
-
|
|
1422
|
-
|
|
1860
|
+
const outBuffer = Buffer.alloc(totalSize);
|
|
1861
|
+
for (const content of dataBlock) {
|
|
1423
1862
|
content.copy(outBuffer, dindex);
|
|
1424
1863
|
dindex += content.length;
|
|
1425
|
-
}
|
|
1426
|
-
|
|
1864
|
+
}
|
|
1865
|
+
for (const content of headerBlocks) {
|
|
1427
1866
|
content.copy(outBuffer, dindex);
|
|
1428
1867
|
dindex += content.length;
|
|
1429
|
-
}
|
|
1430
|
-
|
|
1868
|
+
}
|
|
1869
|
+
const mh = mainHeader.toBinary();
|
|
1431
1870
|
if (_comment) {
|
|
1432
|
-
|
|
1871
|
+
_comment.copy(mh, mh.length - _comment.length);
|
|
1433
1872
|
}
|
|
1434
1873
|
mh.copy(outBuffer, dindex);
|
|
1874
|
+
inBuffer = outBuffer;
|
|
1875
|
+
loadedEntries = false;
|
|
1435
1876
|
return outBuffer;
|
|
1436
1877
|
},
|
|
1437
1878
|
toAsyncBuffer: function(onSuccess, onFail, onItemStart, onItemEnd) {
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1879
|
+
try {
|
|
1880
|
+
if (!loadedEntries) {
|
|
1881
|
+
readEntries();
|
|
1882
|
+
}
|
|
1883
|
+
sortEntries();
|
|
1884
|
+
const dataBlock = [];
|
|
1885
|
+
const centralHeaders = [];
|
|
1886
|
+
let totalSize = 0;
|
|
1887
|
+
let dindex = 0;
|
|
1888
|
+
let totalEntries = 0;
|
|
1889
|
+
mainHeader.size = 0;
|
|
1890
|
+
mainHeader.offset = 0;
|
|
1891
|
+
const compress2Buffer = function(entryLists) {
|
|
1892
|
+
if (entryLists.length > 0) {
|
|
1893
|
+
const entry = entryLists.shift();
|
|
1894
|
+
const name = entry.entryName + entry.extra.toString();
|
|
1895
|
+
if (onItemStart) onItemStart(name);
|
|
1896
|
+
entry.getCompressedDataAsync(function(compressedData) {
|
|
1897
|
+
if (onItemEnd) onItemEnd(name);
|
|
1898
|
+
entry.header.offset = dindex;
|
|
1899
|
+
const localHeader = entry.packLocalHeader();
|
|
1900
|
+
const dataLength = localHeader.length + compressedData.length;
|
|
1901
|
+
dindex += dataLength;
|
|
1902
|
+
dataBlock.push(localHeader);
|
|
1903
|
+
dataBlock.push(compressedData);
|
|
1904
|
+
const centalHeader = entry.packCentralHeader();
|
|
1905
|
+
centralHeaders.push(centalHeader);
|
|
1906
|
+
mainHeader.size += centalHeader.length;
|
|
1907
|
+
totalSize += dataLength + centalHeader.length;
|
|
1908
|
+
totalEntries++;
|
|
1909
|
+
compress2Buffer(entryLists);
|
|
1910
|
+
});
|
|
1911
|
+
} else {
|
|
1912
|
+
totalSize += mainHeader.mainHeaderSize;
|
|
1913
|
+
mainHeader.offset = dindex;
|
|
1914
|
+
mainHeader.totalEntries = totalEntries;
|
|
1915
|
+
dindex = 0;
|
|
1916
|
+
const outBuffer = Buffer.alloc(totalSize);
|
|
1917
|
+
dataBlock.forEach(function(content) {
|
|
1918
|
+
content.copy(outBuffer, dindex);
|
|
1919
|
+
dindex += content.length;
|
|
1920
|
+
});
|
|
1921
|
+
centralHeaders.forEach(function(content) {
|
|
1922
|
+
content.copy(outBuffer, dindex);
|
|
1923
|
+
dindex += content.length;
|
|
1924
|
+
});
|
|
1925
|
+
const mh = mainHeader.toBinary();
|
|
1926
|
+
if (_comment) {
|
|
1927
|
+
_comment.copy(mh, mh.length - _comment.length);
|
|
1928
|
+
}
|
|
1929
|
+
mh.copy(outBuffer, dindex);
|
|
1930
|
+
inBuffer = outBuffer;
|
|
1931
|
+
loadedEntries = false;
|
|
1932
|
+
onSuccess(outBuffer);
|
|
1450
1933
|
}
|
|
1451
|
-
|
|
1452
|
-
|
|
1934
|
+
};
|
|
1935
|
+
compress2Buffer(Array.from(this.entries));
|
|
1936
|
+
} catch (e) {
|
|
1937
|
+
onFail(e);
|
|
1453
1938
|
}
|
|
1454
|
-
var totalSize = 0, dataBlock = [], entryHeaders = [], dindex = 0;
|
|
1455
|
-
mainHeader.size = 0;
|
|
1456
|
-
mainHeader.offset = 0;
|
|
1457
|
-
var compress = function(entryList2) {
|
|
1458
|
-
var self = arguments.callee;
|
|
1459
|
-
if (entryList2.length) {
|
|
1460
|
-
var entry = entryList2.pop();
|
|
1461
|
-
var name = entry.entryName + entry.extra.toString();
|
|
1462
|
-
if (onItemStart) onItemStart(name);
|
|
1463
|
-
entry.getCompressedDataAsync(function(compressedData) {
|
|
1464
|
-
if (onItemEnd) onItemEnd(name);
|
|
1465
|
-
entry.header.offset = dindex;
|
|
1466
|
-
var dataHeader = entry.header.dataHeaderToBinary();
|
|
1467
|
-
var postHeader;
|
|
1468
|
-
try {
|
|
1469
|
-
postHeader = Buffer.alloc(name.length, name);
|
|
1470
|
-
} catch (e) {
|
|
1471
|
-
postHeader = new Buffer(name);
|
|
1472
|
-
}
|
|
1473
|
-
var dataLength = dataHeader.length + postHeader.length + compressedData.length;
|
|
1474
|
-
dindex += dataLength;
|
|
1475
|
-
dataBlock.push(dataHeader);
|
|
1476
|
-
dataBlock.push(postHeader);
|
|
1477
|
-
dataBlock.push(compressedData);
|
|
1478
|
-
var entryHeader = entry.packHeader();
|
|
1479
|
-
entryHeaders.push(entryHeader);
|
|
1480
|
-
mainHeader.size += entryHeader.length;
|
|
1481
|
-
totalSize += dataLength + entryHeader.length;
|
|
1482
|
-
if (entryList2.length) {
|
|
1483
|
-
self(entryList2);
|
|
1484
|
-
} else {
|
|
1485
|
-
totalSize += mainHeader.mainHeaderSize;
|
|
1486
|
-
mainHeader.offset = dindex;
|
|
1487
|
-
dindex = 0;
|
|
1488
|
-
var outBuffer = Buffer.alloc(totalSize);
|
|
1489
|
-
dataBlock.forEach(function(content) {
|
|
1490
|
-
content.copy(outBuffer, dindex);
|
|
1491
|
-
dindex += content.length;
|
|
1492
|
-
});
|
|
1493
|
-
entryHeaders.forEach(function(content) {
|
|
1494
|
-
content.copy(outBuffer, dindex);
|
|
1495
|
-
dindex += content.length;
|
|
1496
|
-
});
|
|
1497
|
-
var mh = mainHeader.toBinary();
|
|
1498
|
-
if (_comment) {
|
|
1499
|
-
_comment.copy(mh, Utils.Constants.ENDHDR);
|
|
1500
|
-
}
|
|
1501
|
-
mh.copy(outBuffer, dindex);
|
|
1502
|
-
onSuccess(outBuffer);
|
|
1503
|
-
}
|
|
1504
|
-
});
|
|
1505
|
-
}
|
|
1506
|
-
};
|
|
1507
|
-
compress(entryList);
|
|
1508
1939
|
}
|
|
1509
1940
|
};
|
|
1510
1941
|
};
|
|
1511
1942
|
}
|
|
1512
1943
|
});
|
|
1513
1944
|
|
|
1514
|
-
//
|
|
1945
|
+
// node_modules/adm-zip/adm-zip.js
|
|
1515
1946
|
var require_adm_zip = __commonJS({
|
|
1516
|
-
"
|
|
1947
|
+
"node_modules/adm-zip/adm-zip.js"(exports, module) {
|
|
1517
1948
|
var Utils = require_util();
|
|
1518
|
-
var fs10 = Utils.FileSystem.require();
|
|
1519
1949
|
var pth = __require("path");
|
|
1520
|
-
fs10.existsSync = fs10.existsSync || pth.existsSync;
|
|
1521
1950
|
var ZipEntry = require_zipEntry();
|
|
1522
1951
|
var ZipFile = require_zipFile();
|
|
1523
|
-
var
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1952
|
+
var get_Bool = (...val) => Utils.findLast(val, (c) => typeof c === "boolean");
|
|
1953
|
+
var get_Str = (...val) => Utils.findLast(val, (c) => typeof c === "string");
|
|
1954
|
+
var get_Fun = (...val) => Utils.findLast(val, (c) => typeof c === "function");
|
|
1955
|
+
var defaultOptions = {
|
|
1956
|
+
// option "noSort" : if true it disables files sorting
|
|
1957
|
+
noSort: false,
|
|
1958
|
+
// read entries during load (initial loading may be slower)
|
|
1959
|
+
readEntries: false,
|
|
1960
|
+
// default method is none
|
|
1961
|
+
method: Utils.Constants.NONE,
|
|
1962
|
+
// file system
|
|
1963
|
+
fs: null
|
|
1964
|
+
};
|
|
1965
|
+
module.exports = function(input, options) {
|
|
1966
|
+
let inBuffer = null;
|
|
1967
|
+
const opts = Object.assign(/* @__PURE__ */ Object.create(null), defaultOptions);
|
|
1968
|
+
if (input && "object" === typeof input) {
|
|
1969
|
+
if (!(input instanceof Uint8Array)) {
|
|
1970
|
+
Object.assign(opts, input);
|
|
1971
|
+
input = opts.input ? opts.input : void 0;
|
|
1972
|
+
if (opts.input) delete opts.input;
|
|
1532
1973
|
}
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
}
|
|
1538
|
-
function sanitize(prefix, name) {
|
|
1539
|
-
prefix = pth.resolve(pth.normalize(prefix));
|
|
1540
|
-
var parts = name.split("/");
|
|
1541
|
-
for (var i = 0, l = parts.length; i < l; i++) {
|
|
1542
|
-
var path12 = pth.normalize(pth.join(prefix, parts.slice(i, l).join(pth.sep)));
|
|
1543
|
-
if (path12.indexOf(prefix) === 0) {
|
|
1544
|
-
return path12;
|
|
1545
|
-
}
|
|
1974
|
+
if (Buffer.isBuffer(input)) {
|
|
1975
|
+
inBuffer = input;
|
|
1976
|
+
opts.method = Utils.Constants.BUFFER;
|
|
1977
|
+
input = void 0;
|
|
1546
1978
|
}
|
|
1547
|
-
return pth.normalize(pth.join(prefix, pth.basename(name)));
|
|
1548
1979
|
}
|
|
1980
|
+
Object.assign(opts, options);
|
|
1981
|
+
const filetools = new Utils(opts);
|
|
1982
|
+
const applyDirAttributes = (dirEntries) => {
|
|
1983
|
+
dirEntries.filter((d) => d.attr).sort((a, b) => b.path.length - a.path.length).forEach((d) => filetools.fs.chmodSync(d.path, d.attr));
|
|
1984
|
+
};
|
|
1985
|
+
if (typeof opts.decoder !== "object" || typeof opts.decoder.encode !== "function" || typeof opts.decoder.decode !== "function") {
|
|
1986
|
+
opts.decoder = Utils.decoder;
|
|
1987
|
+
}
|
|
1988
|
+
if (input && "string" === typeof input) {
|
|
1989
|
+
if (filetools.fs.existsSync(input)) {
|
|
1990
|
+
opts.method = Utils.Constants.FILE;
|
|
1991
|
+
opts.filename = input;
|
|
1992
|
+
inBuffer = filetools.fs.readFileSync(input);
|
|
1993
|
+
} else {
|
|
1994
|
+
throw Utils.Errors.INVALID_FILENAME();
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
const _zip = new ZipFile(inBuffer, opts);
|
|
1998
|
+
const { canonical, sanitize, zipnamefix } = Utils;
|
|
1549
1999
|
function getEntry(entry) {
|
|
1550
2000
|
if (entry && _zip) {
|
|
1551
2001
|
var item;
|
|
1552
|
-
if (typeof entry === "string")
|
|
1553
|
-
|
|
1554
|
-
if (typeof entry === "object" && typeof entry.entryName !== "undefined" && typeof entry.header !== "undefined")
|
|
1555
|
-
item = _zip.getEntry(entry.entryName);
|
|
2002
|
+
if (typeof entry === "string") item = _zip.getEntry(pth.posix.normalize(entry));
|
|
2003
|
+
if (typeof entry === "object" && typeof entry.entryName !== "undefined" && typeof entry.header !== "undefined") item = _zip.getEntry(entry.entryName);
|
|
1556
2004
|
if (item) {
|
|
1557
2005
|
return item;
|
|
1558
2006
|
}
|
|
1559
2007
|
}
|
|
1560
2008
|
return null;
|
|
1561
2009
|
}
|
|
2010
|
+
function fixPath(zipPath) {
|
|
2011
|
+
const { join, normalize, sep } = pth.posix;
|
|
2012
|
+
return join(pth.isAbsolute(zipPath) ? "/" : ".", normalize(sep + zipPath.split("\\").join(sep) + sep));
|
|
2013
|
+
}
|
|
2014
|
+
function filenameFilter(filterfn) {
|
|
2015
|
+
if (filterfn instanceof RegExp) {
|
|
2016
|
+
return /* @__PURE__ */ (function(rx) {
|
|
2017
|
+
return function(filename) {
|
|
2018
|
+
return rx.test(filename);
|
|
2019
|
+
};
|
|
2020
|
+
})(filterfn);
|
|
2021
|
+
} else if ("function" !== typeof filterfn) {
|
|
2022
|
+
return () => true;
|
|
2023
|
+
}
|
|
2024
|
+
return filterfn;
|
|
2025
|
+
}
|
|
2026
|
+
const relativePath = (local, entry) => {
|
|
2027
|
+
let lastChar = entry.slice(-1);
|
|
2028
|
+
lastChar = lastChar === filetools.sep ? filetools.sep : "";
|
|
2029
|
+
return pth.relative(local, entry) + lastChar;
|
|
2030
|
+
};
|
|
1562
2031
|
return {
|
|
1563
2032
|
/**
|
|
1564
2033
|
* Extracts the given entry from the archive and returns the content as a Buffer object
|
|
1565
|
-
* @param entry ZipEntry object or String with the full path of the entry
|
|
1566
|
-
*
|
|
2034
|
+
* @param {ZipEntry|string} entry ZipEntry object or String with the full path of the entry
|
|
2035
|
+
* @param {Buffer|string} [pass] - password
|
|
1567
2036
|
* @return Buffer or Null in case of error
|
|
1568
2037
|
*/
|
|
1569
|
-
readFile: function(entry) {
|
|
2038
|
+
readFile: function(entry, pass) {
|
|
1570
2039
|
var item = getEntry(entry);
|
|
1571
|
-
return item && item.getData() || null;
|
|
2040
|
+
return item && item.getData(pass) || null;
|
|
2041
|
+
},
|
|
2042
|
+
/**
|
|
2043
|
+
* Returns how many child elements has on entry (directories) on files it is always 0
|
|
2044
|
+
* @param {ZipEntry|string} entry ZipEntry object or String with the full path of the entry
|
|
2045
|
+
* @returns {integer}
|
|
2046
|
+
*/
|
|
2047
|
+
childCount: function(entry) {
|
|
2048
|
+
const item = getEntry(entry);
|
|
2049
|
+
if (item) {
|
|
2050
|
+
return _zip.getChildCount(item);
|
|
2051
|
+
}
|
|
1572
2052
|
},
|
|
1573
2053
|
/**
|
|
1574
2054
|
* Asynchronous readFile
|
|
1575
|
-
* @param entry ZipEntry object or String with the full path of the entry
|
|
1576
|
-
* @param callback
|
|
2055
|
+
* @param {ZipEntry|string} entry ZipEntry object or String with the full path of the entry
|
|
2056
|
+
* @param {callback} callback
|
|
1577
2057
|
*
|
|
1578
2058
|
* @return Buffer or Null in case of error
|
|
1579
2059
|
*/
|
|
@@ -1587,8 +2067,8 @@ var require_adm_zip = __commonJS({
|
|
|
1587
2067
|
},
|
|
1588
2068
|
/**
|
|
1589
2069
|
* Extracts the given entry from the archive and returns the content as plain text in the given encoding
|
|
1590
|
-
* @param entry ZipEntry object or String with the full path of the entry
|
|
1591
|
-
* @param encoding Optional. If no encoding is specified utf8 is used
|
|
2070
|
+
* @param {ZipEntry|string} entry - ZipEntry object or String with the full path of the entry
|
|
2071
|
+
* @param {string} encoding - Optional. If no encoding is specified utf8 is used
|
|
1592
2072
|
*
|
|
1593
2073
|
* @return String
|
|
1594
2074
|
*/
|
|
@@ -1604,9 +2084,9 @@ var require_adm_zip = __commonJS({
|
|
|
1604
2084
|
},
|
|
1605
2085
|
/**
|
|
1606
2086
|
* Asynchronous readAsText
|
|
1607
|
-
* @param entry ZipEntry object or String with the full path of the entry
|
|
1608
|
-
* @param callback
|
|
1609
|
-
* @param encoding Optional. If no encoding is specified utf8 is used
|
|
2087
|
+
* @param {ZipEntry|string} entry ZipEntry object or String with the full path of the entry
|
|
2088
|
+
* @param {callback} callback
|
|
2089
|
+
* @param {string} [encoding] - Optional. If no encoding is specified utf8 is used
|
|
1610
2090
|
*
|
|
1611
2091
|
* @return String
|
|
1612
2092
|
*/
|
|
@@ -1631,9 +2111,23 @@ var require_adm_zip = __commonJS({
|
|
|
1631
2111
|
/**
|
|
1632
2112
|
* Remove the entry from the file or the entry and all it's nested directories and files if the given entry is a directory
|
|
1633
2113
|
*
|
|
1634
|
-
* @param entry
|
|
2114
|
+
* @param {ZipEntry|string} entry
|
|
2115
|
+
* @param {boolean} withsubfolders
|
|
2116
|
+
* @returns {void}
|
|
1635
2117
|
*/
|
|
1636
|
-
deleteFile: function(entry) {
|
|
2118
|
+
deleteFile: function(entry, withsubfolders = true) {
|
|
2119
|
+
var item = getEntry(entry);
|
|
2120
|
+
if (item) {
|
|
2121
|
+
_zip.deleteFile(item.entryName, withsubfolders);
|
|
2122
|
+
}
|
|
2123
|
+
},
|
|
2124
|
+
/**
|
|
2125
|
+
* Remove the entry from the file or directory without affecting any nested entries
|
|
2126
|
+
*
|
|
2127
|
+
* @param {ZipEntry|string} entry
|
|
2128
|
+
* @returns {void}
|
|
2129
|
+
*/
|
|
2130
|
+
deleteEntry: function(entry) {
|
|
1637
2131
|
var item = getEntry(entry);
|
|
1638
2132
|
if (item) {
|
|
1639
2133
|
_zip.deleteEntry(item.entryName);
|
|
@@ -1642,7 +2136,7 @@ var require_adm_zip = __commonJS({
|
|
|
1642
2136
|
/**
|
|
1643
2137
|
* Adds a comment to the zip. The zip must be rewritten after adding the comment.
|
|
1644
2138
|
*
|
|
1645
|
-
* @param comment
|
|
2139
|
+
* @param {string} comment
|
|
1646
2140
|
*/
|
|
1647
2141
|
addZipComment: function(comment) {
|
|
1648
2142
|
_zip.comment = comment;
|
|
@@ -1659,8 +2153,8 @@ var require_adm_zip = __commonJS({
|
|
|
1659
2153
|
* Adds a comment to a specified zipEntry. The zip must be rewritten after adding the comment
|
|
1660
2154
|
* The comment cannot exceed 65535 characters in length
|
|
1661
2155
|
*
|
|
1662
|
-
* @param entry
|
|
1663
|
-
* @param comment
|
|
2156
|
+
* @param {ZipEntry} entry
|
|
2157
|
+
* @param {string} comment
|
|
1664
2158
|
*/
|
|
1665
2159
|
addZipEntryComment: function(entry, comment) {
|
|
1666
2160
|
var item = getEntry(entry);
|
|
@@ -1671,7 +2165,7 @@ var require_adm_zip = __commonJS({
|
|
|
1671
2165
|
/**
|
|
1672
2166
|
* Returns the comment of the specified entry
|
|
1673
2167
|
*
|
|
1674
|
-
* @param entry
|
|
2168
|
+
* @param {ZipEntry} entry
|
|
1675
2169
|
* @return String
|
|
1676
2170
|
*/
|
|
1677
2171
|
getZipEntryComment: function(entry) {
|
|
@@ -1684,8 +2178,8 @@ var require_adm_zip = __commonJS({
|
|
|
1684
2178
|
/**
|
|
1685
2179
|
* Updates the content of an existing entry inside the archive. The zip must be rewritten after updating the content
|
|
1686
2180
|
*
|
|
1687
|
-
* @param entry
|
|
1688
|
-
* @param content
|
|
2181
|
+
* @param {ZipEntry} entry
|
|
2182
|
+
* @param {Buffer} content
|
|
1689
2183
|
*/
|
|
1690
2184
|
updateFile: function(entry, content) {
|
|
1691
2185
|
var item = getEntry(entry);
|
|
@@ -1696,142 +2190,139 @@ var require_adm_zip = __commonJS({
|
|
|
1696
2190
|
/**
|
|
1697
2191
|
* Adds a file from the disk to the archive
|
|
1698
2192
|
*
|
|
1699
|
-
* @param localPath File to add to zip
|
|
1700
|
-
* @param zipPath Optional path inside the zip
|
|
1701
|
-
* @param zipName Optional name for the file
|
|
2193
|
+
* @param {string} localPath File to add to zip
|
|
2194
|
+
* @param {string} [zipPath] Optional path inside the zip
|
|
2195
|
+
* @param {string} [zipName] Optional name for the file
|
|
2196
|
+
* @param {string} [comment] Optional file comment
|
|
1702
2197
|
*/
|
|
1703
|
-
addLocalFile: function(localPath, zipPath, zipName) {
|
|
1704
|
-
if (
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
}
|
|
1713
|
-
var p = localPath.split("\\").join("/").split("/").pop();
|
|
1714
|
-
if (zipName) {
|
|
1715
|
-
this.addFile(zipPath + zipName, fs10.readFileSync(localPath), "", 0);
|
|
1716
|
-
} else {
|
|
1717
|
-
this.addFile(zipPath + p, fs10.readFileSync(localPath), "", 0);
|
|
1718
|
-
}
|
|
2198
|
+
addLocalFile: function(localPath, zipPath, zipName, comment) {
|
|
2199
|
+
if (filetools.fs.existsSync(localPath)) {
|
|
2200
|
+
zipPath = zipPath ? fixPath(zipPath) : "";
|
|
2201
|
+
const p = pth.win32.basename(pth.win32.normalize(localPath));
|
|
2202
|
+
zipPath += zipName ? zipName : p;
|
|
2203
|
+
const _attr = filetools.fs.statSync(localPath);
|
|
2204
|
+
const data = _attr.isFile() ? filetools.fs.readFileSync(localPath) : Buffer.alloc(0);
|
|
2205
|
+
if (_attr.isDirectory()) zipPath += filetools.sep;
|
|
2206
|
+
this.addFile(zipPath, data, comment, _attr);
|
|
1719
2207
|
} else {
|
|
1720
|
-
throw
|
|
2208
|
+
throw Utils.Errors.FILE_NOT_FOUND(localPath);
|
|
1721
2209
|
}
|
|
1722
2210
|
},
|
|
2211
|
+
/**
|
|
2212
|
+
* Callback for showing if everything was done.
|
|
2213
|
+
*
|
|
2214
|
+
* @callback doneCallback
|
|
2215
|
+
* @param {Error} err - Error object
|
|
2216
|
+
* @param {boolean} done - was request fully completed
|
|
2217
|
+
*/
|
|
2218
|
+
/**
|
|
2219
|
+
* Adds a file from the disk to the archive
|
|
2220
|
+
*
|
|
2221
|
+
* @param {(object|string)} options - options object, if it is string it us used as localPath.
|
|
2222
|
+
* @param {string} options.localPath - Local path to the file.
|
|
2223
|
+
* @param {string} [options.comment] - Optional file comment.
|
|
2224
|
+
* @param {string} [options.zipPath] - Optional path inside the zip
|
|
2225
|
+
* @param {string} [options.zipName] - Optional name for the file
|
|
2226
|
+
* @param {doneCallback} callback - The callback that handles the response.
|
|
2227
|
+
*/
|
|
2228
|
+
addLocalFileAsync: function(options2, callback) {
|
|
2229
|
+
options2 = typeof options2 === "object" ? options2 : { localPath: options2 };
|
|
2230
|
+
const localPath = pth.resolve(options2.localPath);
|
|
2231
|
+
const { comment } = options2;
|
|
2232
|
+
let { zipPath, zipName } = options2;
|
|
2233
|
+
const self = this;
|
|
2234
|
+
filetools.fs.stat(localPath, function(err, stats) {
|
|
2235
|
+
if (err) return callback(err, false);
|
|
2236
|
+
zipPath = zipPath ? fixPath(zipPath) : "";
|
|
2237
|
+
const p = pth.win32.basename(pth.win32.normalize(localPath));
|
|
2238
|
+
zipPath += zipName ? zipName : p;
|
|
2239
|
+
if (stats.isFile()) {
|
|
2240
|
+
filetools.fs.readFile(localPath, function(err2, data) {
|
|
2241
|
+
if (err2) return callback(err2, false);
|
|
2242
|
+
self.addFile(zipPath, data, comment, stats);
|
|
2243
|
+
return setImmediate(callback, void 0, true);
|
|
2244
|
+
});
|
|
2245
|
+
} else if (stats.isDirectory()) {
|
|
2246
|
+
zipPath += filetools.sep;
|
|
2247
|
+
self.addFile(zipPath, Buffer.alloc(0), comment, stats);
|
|
2248
|
+
return setImmediate(callback, void 0, true);
|
|
2249
|
+
}
|
|
2250
|
+
});
|
|
2251
|
+
},
|
|
1723
2252
|
/**
|
|
1724
2253
|
* Adds a local directory and all its nested files and directories to the archive
|
|
1725
2254
|
*
|
|
1726
|
-
* @param localPath
|
|
1727
|
-
* @param zipPath optional path inside zip
|
|
1728
|
-
* @param filter optional RegExp or Function if files match will
|
|
1729
|
-
* be included.
|
|
2255
|
+
* @param {string} localPath - local path to the folder
|
|
2256
|
+
* @param {string} [zipPath] - optional path inside zip
|
|
2257
|
+
* @param {(RegExp|function)} [filter] - optional RegExp or Function if files match will be included.
|
|
1730
2258
|
*/
|
|
1731
2259
|
addLocalFolder: function(localPath, zipPath, filter) {
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
return true;
|
|
1735
|
-
};
|
|
1736
|
-
} else if (filter instanceof RegExp) {
|
|
1737
|
-
filter = /* @__PURE__ */ (function(filter2) {
|
|
1738
|
-
return function(filename) {
|
|
1739
|
-
return filter2.test(filename);
|
|
1740
|
-
};
|
|
1741
|
-
})(filter);
|
|
1742
|
-
}
|
|
1743
|
-
if (zipPath) {
|
|
1744
|
-
zipPath = zipPath.split("\\").join("/");
|
|
1745
|
-
if (zipPath.charAt(zipPath.length - 1) !== "/") {
|
|
1746
|
-
zipPath += "/";
|
|
1747
|
-
}
|
|
1748
|
-
} else {
|
|
1749
|
-
zipPath = "";
|
|
1750
|
-
}
|
|
2260
|
+
filter = filenameFilter(filter);
|
|
2261
|
+
zipPath = zipPath ? fixPath(zipPath) : "";
|
|
1751
2262
|
localPath = pth.normalize(localPath);
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
if (fs10.existsSync(localPath)) {
|
|
1756
|
-
var items = Utils.findFiles(localPath), self = this;
|
|
2263
|
+
if (filetools.fs.existsSync(localPath)) {
|
|
2264
|
+
const items = filetools.findFiles(localPath);
|
|
2265
|
+
const self = this;
|
|
1757
2266
|
if (items.length) {
|
|
1758
|
-
items
|
|
1759
|
-
|
|
2267
|
+
for (const filepath of items) {
|
|
2268
|
+
const p = pth.join(zipPath, relativePath(localPath, filepath));
|
|
1760
2269
|
if (filter(p)) {
|
|
1761
|
-
|
|
1762
|
-
self.addFile(zipPath + p, fs10.readFileSync(path12), "", 0);
|
|
1763
|
-
} else {
|
|
1764
|
-
self.addFile(zipPath + p, Buffer.alloc(0), "", 0);
|
|
1765
|
-
}
|
|
2270
|
+
self.addLocalFile(filepath, pth.dirname(p));
|
|
1766
2271
|
}
|
|
1767
|
-
}
|
|
2272
|
+
}
|
|
1768
2273
|
}
|
|
1769
2274
|
} else {
|
|
1770
|
-
throw
|
|
2275
|
+
throw Utils.Errors.FILE_NOT_FOUND(localPath);
|
|
1771
2276
|
}
|
|
1772
2277
|
},
|
|
1773
2278
|
/**
|
|
1774
|
-
* Asynchronous
|
|
1775
|
-
* @param localPath
|
|
1776
|
-
* @param callback
|
|
1777
|
-
* @param zipPath optional path inside zip
|
|
1778
|
-
* @param filter optional RegExp or Function if files match will
|
|
2279
|
+
* Asynchronous addLocalFolder
|
|
2280
|
+
* @param {string} localPath
|
|
2281
|
+
* @param {callback} callback
|
|
2282
|
+
* @param {string} [zipPath] optional path inside zip
|
|
2283
|
+
* @param {RegExp|function} [filter] optional RegExp or Function if files match will
|
|
1779
2284
|
* be included.
|
|
1780
2285
|
*/
|
|
1781
2286
|
addLocalFolderAsync: function(localPath, callback, zipPath, filter) {
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
return true;
|
|
1785
|
-
};
|
|
1786
|
-
} else if (filter instanceof RegExp) {
|
|
1787
|
-
filter = /* @__PURE__ */ (function(filter2) {
|
|
1788
|
-
return function(filename) {
|
|
1789
|
-
return filter2.test(filename);
|
|
1790
|
-
};
|
|
1791
|
-
})(filter);
|
|
1792
|
-
}
|
|
1793
|
-
if (zipPath) {
|
|
1794
|
-
zipPath = zipPath.split("\\").join("/");
|
|
1795
|
-
if (zipPath.charAt(zipPath.length - 1) !== "/") {
|
|
1796
|
-
zipPath += "/";
|
|
1797
|
-
}
|
|
1798
|
-
} else {
|
|
1799
|
-
zipPath = "";
|
|
1800
|
-
}
|
|
2287
|
+
filter = filenameFilter(filter);
|
|
2288
|
+
zipPath = zipPath ? fixPath(zipPath) : "";
|
|
1801
2289
|
localPath = pth.normalize(localPath);
|
|
1802
|
-
localPath = localPath.split("\\").join("/");
|
|
1803
|
-
if (localPath.charAt(localPath.length - 1) !== "/")
|
|
1804
|
-
localPath += "/";
|
|
1805
2290
|
var self = this;
|
|
1806
|
-
|
|
2291
|
+
filetools.fs.open(localPath, "r", function(err) {
|
|
1807
2292
|
if (err && err.code === "ENOENT") {
|
|
1808
|
-
callback(void 0, Utils.Errors.FILE_NOT_FOUND
|
|
2293
|
+
callback(void 0, Utils.Errors.FILE_NOT_FOUND(localPath));
|
|
1809
2294
|
} else if (err) {
|
|
1810
2295
|
callback(void 0, err);
|
|
1811
2296
|
} else {
|
|
1812
|
-
var items =
|
|
2297
|
+
var items = filetools.findFiles(localPath);
|
|
1813
2298
|
var i = -1;
|
|
1814
2299
|
var next = function() {
|
|
1815
2300
|
i += 1;
|
|
1816
2301
|
if (i < items.length) {
|
|
1817
|
-
var
|
|
2302
|
+
var filepath = items[i];
|
|
2303
|
+
var p = relativePath(localPath, filepath).split("\\").join("/");
|
|
1818
2304
|
p = p.normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\x20-\x7E]/g, "");
|
|
1819
2305
|
if (filter(p)) {
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
2306
|
+
filetools.fs.stat(filepath, function(er0, stats) {
|
|
2307
|
+
if (er0) callback(void 0, er0);
|
|
2308
|
+
if (stats.isFile()) {
|
|
2309
|
+
filetools.fs.readFile(filepath, function(er1, data) {
|
|
2310
|
+
if (er1) {
|
|
2311
|
+
callback(void 0, er1);
|
|
2312
|
+
} else {
|
|
2313
|
+
self.addFile(zipPath + p, data, "", stats);
|
|
2314
|
+
next();
|
|
2315
|
+
}
|
|
2316
|
+
});
|
|
2317
|
+
} else {
|
|
2318
|
+
self.addFile(zipPath + p + "/", Buffer.alloc(0), "", stats);
|
|
2319
|
+
next();
|
|
2320
|
+
}
|
|
2321
|
+
});
|
|
1833
2322
|
} else {
|
|
1834
|
-
|
|
2323
|
+
process.nextTick(() => {
|
|
2324
|
+
next();
|
|
2325
|
+
});
|
|
1835
2326
|
}
|
|
1836
2327
|
} else {
|
|
1837
2328
|
callback(true, void 0);
|
|
@@ -1841,47 +2332,138 @@ var require_adm_zip = __commonJS({
|
|
|
1841
2332
|
}
|
|
1842
2333
|
});
|
|
1843
2334
|
},
|
|
2335
|
+
/**
|
|
2336
|
+
* Adds a local directory and all its nested files and directories to the archive
|
|
2337
|
+
*
|
|
2338
|
+
* @param {object | string} options - options object, if it is string it us used as localPath.
|
|
2339
|
+
* @param {string} options.localPath - Local path to the folder.
|
|
2340
|
+
* @param {string} [options.zipPath] - optional path inside zip.
|
|
2341
|
+
* @param {RegExp|function} [options.filter] - optional RegExp or Function if files match will be included.
|
|
2342
|
+
* @param {function|string} [options.namefix] - optional function to help fix filename
|
|
2343
|
+
* @param {doneCallback} callback - The callback that handles the response.
|
|
2344
|
+
*
|
|
2345
|
+
*/
|
|
2346
|
+
addLocalFolderAsync2: function(options2, callback) {
|
|
2347
|
+
const self = this;
|
|
2348
|
+
options2 = typeof options2 === "object" ? options2 : { localPath: options2 };
|
|
2349
|
+
const localPath = pth.resolve(fixPath(options2.localPath));
|
|
2350
|
+
let { zipPath, filter, namefix } = options2;
|
|
2351
|
+
if (filter instanceof RegExp) {
|
|
2352
|
+
filter = /* @__PURE__ */ (function(rx) {
|
|
2353
|
+
return function(filename) {
|
|
2354
|
+
return rx.test(filename);
|
|
2355
|
+
};
|
|
2356
|
+
})(filter);
|
|
2357
|
+
} else if ("function" !== typeof filter) {
|
|
2358
|
+
filter = function() {
|
|
2359
|
+
return true;
|
|
2360
|
+
};
|
|
2361
|
+
}
|
|
2362
|
+
zipPath = zipPath ? fixPath(zipPath) : "";
|
|
2363
|
+
if (namefix === "latin1") {
|
|
2364
|
+
namefix = (str) => str.normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\x20-\x7E]/g, "");
|
|
2365
|
+
}
|
|
2366
|
+
if (typeof namefix !== "function") namefix = (str) => str;
|
|
2367
|
+
const relPathFix = (entry) => pth.join(zipPath, namefix(relativePath(localPath, entry)));
|
|
2368
|
+
const fileNameFix = (entry) => pth.win32.basename(pth.win32.normalize(namefix(entry)));
|
|
2369
|
+
filetools.fs.open(localPath, "r", function(err) {
|
|
2370
|
+
if (err && err.code === "ENOENT") {
|
|
2371
|
+
callback(void 0, Utils.Errors.FILE_NOT_FOUND(localPath));
|
|
2372
|
+
} else if (err) {
|
|
2373
|
+
callback(void 0, err);
|
|
2374
|
+
} else {
|
|
2375
|
+
filetools.findFilesAsync(localPath, function(err2, fileEntries) {
|
|
2376
|
+
if (err2) return callback(err2);
|
|
2377
|
+
fileEntries = fileEntries.filter((dir) => filter(relPathFix(dir)));
|
|
2378
|
+
if (!fileEntries.length) callback(void 0, false);
|
|
2379
|
+
setImmediate(
|
|
2380
|
+
fileEntries.reverse().reduce(function(next, entry) {
|
|
2381
|
+
return function(err3, done) {
|
|
2382
|
+
if (err3 || done === false) return setImmediate(next, err3, false);
|
|
2383
|
+
self.addLocalFileAsync(
|
|
2384
|
+
{
|
|
2385
|
+
localPath: entry,
|
|
2386
|
+
zipPath: pth.dirname(relPathFix(entry)),
|
|
2387
|
+
zipName: fileNameFix(entry)
|
|
2388
|
+
},
|
|
2389
|
+
next
|
|
2390
|
+
);
|
|
2391
|
+
};
|
|
2392
|
+
}, callback)
|
|
2393
|
+
);
|
|
2394
|
+
});
|
|
2395
|
+
}
|
|
2396
|
+
});
|
|
2397
|
+
},
|
|
2398
|
+
/**
|
|
2399
|
+
* Adds a local directory and all its nested files and directories to the archive
|
|
2400
|
+
*
|
|
2401
|
+
* @param {string} localPath - path where files will be extracted
|
|
2402
|
+
* @param {object} props - optional properties
|
|
2403
|
+
* @param {string} [props.zipPath] - optional path inside zip
|
|
2404
|
+
* @param {RegExp|function} [props.filter] - optional RegExp or Function if files match will be included.
|
|
2405
|
+
* @param {function|string} [props.namefix] - optional function to help fix filename
|
|
2406
|
+
*/
|
|
2407
|
+
addLocalFolderPromise: function(localPath, props) {
|
|
2408
|
+
return new Promise((resolve, reject) => {
|
|
2409
|
+
this.addLocalFolderAsync2(Object.assign({ localPath }, props), (err, done) => {
|
|
2410
|
+
if (err) reject(err);
|
|
2411
|
+
if (done) resolve(this);
|
|
2412
|
+
});
|
|
2413
|
+
});
|
|
2414
|
+
},
|
|
1844
2415
|
/**
|
|
1845
2416
|
* Allows you to create a entry (file or directory) in the zip file.
|
|
1846
2417
|
* If you want to create a directory the entryName must end in / and a null buffer should be provided.
|
|
1847
2418
|
* Comment and attributes are optional
|
|
1848
2419
|
*
|
|
1849
|
-
* @param entryName
|
|
1850
|
-
* @param content
|
|
1851
|
-
* @param comment
|
|
1852
|
-
* @param attr
|
|
2420
|
+
* @param {string} entryName
|
|
2421
|
+
* @param {Buffer | string} content - file content as buffer or utf8 coded string
|
|
2422
|
+
* @param {string} [comment] - file comment
|
|
2423
|
+
* @param {number | object} [attr] - number as unix file permissions, object as filesystem Stats object
|
|
1853
2424
|
*/
|
|
1854
2425
|
addFile: function(entryName, content, comment, attr) {
|
|
1855
|
-
|
|
1856
|
-
entry
|
|
2426
|
+
entryName = zipnamefix(entryName);
|
|
2427
|
+
let entry = getEntry(entryName);
|
|
2428
|
+
const update = entry != null;
|
|
2429
|
+
if (!update) {
|
|
2430
|
+
entry = new ZipEntry(opts);
|
|
2431
|
+
entry.entryName = entryName;
|
|
2432
|
+
}
|
|
1857
2433
|
entry.comment = comment || "";
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
} else {
|
|
1862
|
-
attr = 420 << 16;
|
|
1863
|
-
}
|
|
2434
|
+
const isStat = "object" === typeof attr && attr instanceof filetools.fs.Stats;
|
|
2435
|
+
if (isStat) {
|
|
2436
|
+
entry.header.time = attr.mtime;
|
|
1864
2437
|
}
|
|
1865
|
-
entry.
|
|
2438
|
+
var fileattr = entry.isDirectory ? 16 : 0;
|
|
2439
|
+
let unix = entry.isDirectory ? 16384 : 32768;
|
|
2440
|
+
if (isStat) {
|
|
2441
|
+
unix |= 4095 & attr.mode;
|
|
2442
|
+
} else if ("number" === typeof attr) {
|
|
2443
|
+
unix |= 4095 & attr;
|
|
2444
|
+
} else {
|
|
2445
|
+
unix |= entry.isDirectory ? 493 : 420;
|
|
2446
|
+
}
|
|
2447
|
+
fileattr = (fileattr | unix << 16) >>> 0;
|
|
2448
|
+
entry.attr = fileattr;
|
|
1866
2449
|
entry.setData(content);
|
|
1867
|
-
_zip.setEntry(entry);
|
|
2450
|
+
if (!update) _zip.setEntry(entry);
|
|
2451
|
+
return entry;
|
|
1868
2452
|
},
|
|
1869
2453
|
/**
|
|
1870
2454
|
* Returns an array of ZipEntry objects representing the files and folders inside the archive
|
|
1871
2455
|
*
|
|
1872
|
-
* @
|
|
2456
|
+
* @param {string} [password]
|
|
2457
|
+
* @returns Array
|
|
1873
2458
|
*/
|
|
1874
|
-
getEntries: function() {
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
} else {
|
|
1878
|
-
return [];
|
|
1879
|
-
}
|
|
2459
|
+
getEntries: function(password) {
|
|
2460
|
+
_zip.password = password;
|
|
2461
|
+
return _zip ? _zip.entries : [];
|
|
1880
2462
|
},
|
|
1881
2463
|
/**
|
|
1882
2464
|
* Returns a ZipEntry object representing the file or folder specified by ``name``.
|
|
1883
2465
|
*
|
|
1884
|
-
* @param name
|
|
2466
|
+
* @param {string} name
|
|
1885
2467
|
* @return ZipEntry
|
|
1886
2468
|
*/
|
|
1887
2469
|
getEntry: function(name) {
|
|
@@ -1897,60 +2479,64 @@ var require_adm_zip = __commonJS({
|
|
|
1897
2479
|
* Extracts the given entry to the given targetPath
|
|
1898
2480
|
* If the entry is a directory inside the archive, the entire directory and it's subdirectories will be extracted
|
|
1899
2481
|
*
|
|
1900
|
-
* @param entry ZipEntry object or String with the full path of the entry
|
|
1901
|
-
* @param targetPath Target folder where to write the file
|
|
1902
|
-
* @param maintainEntryPath If maintainEntryPath is true and the entry is inside a folder, the entry folder
|
|
1903
|
-
*
|
|
1904
|
-
* @param
|
|
1905
|
-
*
|
|
2482
|
+
* @param {string|ZipEntry} entry - ZipEntry object or String with the full path of the entry
|
|
2483
|
+
* @param {string} targetPath - Target folder where to write the file
|
|
2484
|
+
* @param {boolean} [maintainEntryPath=true] - If maintainEntryPath is true and the entry is inside a folder, the entry folder will be created in targetPath as well. Default is TRUE
|
|
2485
|
+
* @param {boolean} [overwrite=false] - If the file already exists at the target path, the file will be overwriten if this is true.
|
|
2486
|
+
* @param {boolean} [keepOriginalPermission=false] - The file will be set as the permission from the entry if this is true.
|
|
2487
|
+
* @param {string} [outFileName] - String If set will override the filename of the extracted file (Only works if the entry is a file)
|
|
1906
2488
|
*
|
|
1907
2489
|
* @return Boolean
|
|
1908
2490
|
*/
|
|
1909
|
-
extractEntryTo: function(entry, targetPath, maintainEntryPath, overwrite) {
|
|
1910
|
-
overwrite = overwrite
|
|
1911
|
-
|
|
2491
|
+
extractEntryTo: function(entry, targetPath, maintainEntryPath, overwrite, keepOriginalPermission, outFileName) {
|
|
2492
|
+
overwrite = get_Bool(false, overwrite);
|
|
2493
|
+
keepOriginalPermission = get_Bool(false, keepOriginalPermission);
|
|
2494
|
+
maintainEntryPath = get_Bool(true, maintainEntryPath);
|
|
2495
|
+
outFileName = get_Str(keepOriginalPermission, outFileName);
|
|
1912
2496
|
var item = getEntry(entry);
|
|
1913
2497
|
if (!item) {
|
|
1914
|
-
throw
|
|
2498
|
+
throw Utils.Errors.NO_ENTRY();
|
|
1915
2499
|
}
|
|
1916
|
-
var entryName = item.entryName;
|
|
1917
|
-
var target = sanitize(targetPath, maintainEntryPath ? entryName : pth.basename(entryName));
|
|
2500
|
+
var entryName = canonical(item.entryName);
|
|
2501
|
+
var target = sanitize(targetPath, outFileName && !item.isDirectory ? canonical(outFileName) : maintainEntryPath ? entryName : pth.basename(entryName));
|
|
1918
2502
|
if (item.isDirectory) {
|
|
1919
|
-
target = pth.resolve(target, "..");
|
|
1920
2503
|
var children = _zip.getEntryChildren(item);
|
|
1921
2504
|
children.forEach(function(child) {
|
|
1922
2505
|
if (child.isDirectory) return;
|
|
1923
2506
|
var content2 = child.getData();
|
|
1924
2507
|
if (!content2) {
|
|
1925
|
-
throw
|
|
2508
|
+
throw Utils.Errors.CANT_EXTRACT_FILE();
|
|
1926
2509
|
}
|
|
1927
|
-
var
|
|
1928
|
-
|
|
2510
|
+
var name = canonical(maintainEntryPath ? child.entryName : child.entryName.substring(item.entryName.length));
|
|
2511
|
+
var childName = sanitize(targetPath, name);
|
|
2512
|
+
const fileAttr2 = keepOriginalPermission ? child.header.fileAttr : void 0;
|
|
2513
|
+
filetools.writeFileTo(childName, content2, overwrite, fileAttr2);
|
|
1929
2514
|
});
|
|
1930
2515
|
return true;
|
|
1931
2516
|
}
|
|
1932
|
-
var content = item.getData();
|
|
1933
|
-
if (!content) throw
|
|
1934
|
-
if (
|
|
1935
|
-
throw
|
|
2517
|
+
var content = item.getData(_zip.password);
|
|
2518
|
+
if (!content) throw Utils.Errors.CANT_EXTRACT_FILE();
|
|
2519
|
+
if (filetools.fs.existsSync(target) && !overwrite) {
|
|
2520
|
+
throw Utils.Errors.CANT_OVERRIDE();
|
|
1936
2521
|
}
|
|
1937
|
-
|
|
2522
|
+
const fileAttr = keepOriginalPermission ? entry.header.fileAttr : void 0;
|
|
2523
|
+
filetools.writeFileTo(target, content, overwrite, fileAttr);
|
|
1938
2524
|
return true;
|
|
1939
2525
|
},
|
|
1940
2526
|
/**
|
|
1941
2527
|
* Test the archive
|
|
1942
|
-
*
|
|
2528
|
+
* @param {string} [pass]
|
|
1943
2529
|
*/
|
|
1944
|
-
test: function() {
|
|
2530
|
+
test: function(pass) {
|
|
1945
2531
|
if (!_zip) {
|
|
1946
2532
|
return false;
|
|
1947
2533
|
}
|
|
1948
|
-
for (var entry
|
|
2534
|
+
for (var entry of _zip.entries) {
|
|
1949
2535
|
try {
|
|
1950
2536
|
if (entry.isDirectory) {
|
|
1951
2537
|
continue;
|
|
1952
2538
|
}
|
|
1953
|
-
var content =
|
|
2539
|
+
var content = entry.getData(pass);
|
|
1954
2540
|
if (!content) {
|
|
1955
2541
|
return false;
|
|
1956
2542
|
}
|
|
@@ -1963,96 +2549,139 @@ var require_adm_zip = __commonJS({
|
|
|
1963
2549
|
/**
|
|
1964
2550
|
* Extracts the entire archive to the given location
|
|
1965
2551
|
*
|
|
1966
|
-
* @param targetPath Target location
|
|
1967
|
-
* @param overwrite If the file already exists at the target path, the file will be overwriten if this is true.
|
|
2552
|
+
* @param {string} targetPath Target location
|
|
2553
|
+
* @param {boolean} [overwrite=false] If the file already exists at the target path, the file will be overwriten if this is true.
|
|
1968
2554
|
* Default is FALSE
|
|
2555
|
+
* @param {boolean} [keepOriginalPermission=false] The file will be set as the permission from the entry if this is true.
|
|
2556
|
+
* Default is FALSE
|
|
2557
|
+
* @param {string|Buffer} [pass] password
|
|
1969
2558
|
*/
|
|
1970
|
-
extractAllTo: function(targetPath, overwrite) {
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
2559
|
+
extractAllTo: function(targetPath, overwrite, keepOriginalPermission, pass) {
|
|
2560
|
+
keepOriginalPermission = get_Bool(false, keepOriginalPermission);
|
|
2561
|
+
pass = get_Str(keepOriginalPermission, pass);
|
|
2562
|
+
overwrite = get_Bool(false, overwrite);
|
|
2563
|
+
if (!_zip) throw Utils.Errors.NO_ZIP();
|
|
2564
|
+
const dirEntries = [];
|
|
1975
2565
|
_zip.entries.forEach(function(entry) {
|
|
1976
|
-
var entryName = sanitize(targetPath, entry.entryName
|
|
2566
|
+
var entryName = sanitize(targetPath, canonical(entry.entryName));
|
|
1977
2567
|
if (entry.isDirectory) {
|
|
1978
|
-
|
|
2568
|
+
filetools.makeDir(entryName);
|
|
2569
|
+
if (keepOriginalPermission) dirEntries.push({ path: entryName, attr: entry.header.fileAttr });
|
|
1979
2570
|
return;
|
|
1980
2571
|
}
|
|
1981
|
-
var content = entry.getData();
|
|
2572
|
+
var content = entry.getData(pass);
|
|
1982
2573
|
if (!content) {
|
|
1983
|
-
throw
|
|
2574
|
+
throw Utils.Errors.CANT_EXTRACT_FILE();
|
|
1984
2575
|
}
|
|
1985
|
-
|
|
2576
|
+
const fileAttr = keepOriginalPermission ? entry.header.fileAttr : void 0;
|
|
2577
|
+
filetools.writeFileTo(entryName, content, overwrite, fileAttr);
|
|
1986
2578
|
try {
|
|
1987
|
-
|
|
2579
|
+
filetools.fs.utimesSync(entryName, entry.header.time, entry.header.time);
|
|
1988
2580
|
} catch (err) {
|
|
1989
|
-
throw new Error(Utils.Errors.CANT_EXTRACT_FILE);
|
|
1990
2581
|
}
|
|
1991
2582
|
});
|
|
2583
|
+
applyDirAttributes(dirEntries);
|
|
1992
2584
|
},
|
|
1993
2585
|
/**
|
|
1994
2586
|
* Asynchronous extractAllTo
|
|
1995
2587
|
*
|
|
1996
|
-
* @param targetPath Target location
|
|
1997
|
-
* @param overwrite If the file already exists at the target path, the file will be overwriten if this is true.
|
|
2588
|
+
* @param {string} targetPath Target location
|
|
2589
|
+
* @param {boolean} [overwrite=false] If the file already exists at the target path, the file will be overwriten if this is true.
|
|
2590
|
+
* Default is FALSE
|
|
2591
|
+
* @param {boolean} [keepOriginalPermission=false] The file will be set as the permission from the entry if this is true.
|
|
1998
2592
|
* Default is FALSE
|
|
1999
|
-
* @param callback
|
|
2593
|
+
* @param {function} callback The callback will be executed when all entries are extracted successfully or any error is thrown.
|
|
2000
2594
|
*/
|
|
2001
|
-
extractAllToAsync: function(targetPath, overwrite, callback) {
|
|
2595
|
+
extractAllToAsync: function(targetPath, overwrite, keepOriginalPermission, callback) {
|
|
2596
|
+
callback = get_Fun(overwrite, keepOriginalPermission, callback);
|
|
2597
|
+
keepOriginalPermission = get_Bool(false, keepOriginalPermission);
|
|
2598
|
+
overwrite = get_Bool(false, overwrite);
|
|
2002
2599
|
if (!callback) {
|
|
2003
|
-
|
|
2004
|
-
|
|
2600
|
+
return new Promise((resolve, reject) => {
|
|
2601
|
+
this.extractAllToAsync(targetPath, overwrite, keepOriginalPermission, function(err) {
|
|
2602
|
+
if (err) {
|
|
2603
|
+
reject(err);
|
|
2604
|
+
} else {
|
|
2605
|
+
resolve(this);
|
|
2606
|
+
}
|
|
2607
|
+
});
|
|
2608
|
+
});
|
|
2005
2609
|
}
|
|
2006
|
-
overwrite = overwrite || false;
|
|
2007
2610
|
if (!_zip) {
|
|
2008
|
-
callback(
|
|
2611
|
+
callback(Utils.Errors.NO_ZIP());
|
|
2009
2612
|
return;
|
|
2010
2613
|
}
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2614
|
+
targetPath = pth.resolve(targetPath);
|
|
2615
|
+
const getPath = (entry) => sanitize(targetPath, pth.normalize(canonical(entry.entryName)));
|
|
2616
|
+
const getError = (msg, file) => new Error(msg + ': "' + file + '"');
|
|
2617
|
+
const dirEntries = [];
|
|
2618
|
+
const fileEntries = [];
|
|
2619
|
+
_zip.entries.forEach((e) => {
|
|
2620
|
+
if (e.isDirectory) {
|
|
2621
|
+
dirEntries.push(e);
|
|
2622
|
+
} else {
|
|
2623
|
+
fileEntries.push(e);
|
|
2021
2624
|
}
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2625
|
+
});
|
|
2626
|
+
const deferredDirAttr = [];
|
|
2627
|
+
for (const entry of dirEntries) {
|
|
2628
|
+
const dirPath = getPath(entry);
|
|
2629
|
+
const dirAttr = keepOriginalPermission ? entry.header.fileAttr : void 0;
|
|
2630
|
+
try {
|
|
2631
|
+
filetools.makeDir(dirPath);
|
|
2632
|
+
} catch (er) {
|
|
2633
|
+
callback(getError("Unable to create folder", dirPath));
|
|
2634
|
+
continue;
|
|
2635
|
+
}
|
|
2636
|
+
if (dirAttr) deferredDirAttr.push({ path: dirPath, attr: dirAttr });
|
|
2637
|
+
try {
|
|
2638
|
+
filetools.fs.utimesSync(dirPath, entry.header.time, entry.header.time);
|
|
2639
|
+
} catch (er) {
|
|
2640
|
+
}
|
|
2641
|
+
}
|
|
2642
|
+
const done = (err) => {
|
|
2643
|
+
if (!err) {
|
|
2644
|
+
try {
|
|
2645
|
+
applyDirAttributes(deferredDirAttr);
|
|
2646
|
+
} catch (er) {
|
|
2647
|
+
return callback(getError("Unable to set folder permissions", er.path || ""));
|
|
2027
2648
|
}
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2649
|
+
}
|
|
2650
|
+
callback(err);
|
|
2651
|
+
};
|
|
2652
|
+
fileEntries.reverse().reduce(function(next, entry) {
|
|
2653
|
+
return function(err) {
|
|
2654
|
+
if (err) {
|
|
2655
|
+
next(err);
|
|
2656
|
+
} else {
|
|
2657
|
+
const entryName = pth.normalize(canonical(entry.entryName));
|
|
2658
|
+
const filePath = sanitize(targetPath, entryName);
|
|
2659
|
+
entry.getDataAsync(function(content, err_1) {
|
|
2660
|
+
if (err_1) {
|
|
2661
|
+
next(err_1);
|
|
2662
|
+
} else if (!content) {
|
|
2663
|
+
next(Utils.Errors.CANT_EXTRACT_FILE());
|
|
2664
|
+
} else {
|
|
2665
|
+
const fileAttr = keepOriginalPermission ? entry.header.fileAttr : void 0;
|
|
2666
|
+
filetools.writeFileToAsync(filePath, content, overwrite, fileAttr, function(succ) {
|
|
2667
|
+
if (!succ) {
|
|
2668
|
+
return next(getError("Unable to write file", filePath));
|
|
2669
|
+
}
|
|
2670
|
+
filetools.fs.utimes(filePath, entry.header.time, entry.header.time, function() {
|
|
2671
|
+
next();
|
|
2672
|
+
});
|
|
2673
|
+
});
|
|
2674
|
+
}
|
|
2675
|
+
});
|
|
2032
2676
|
}
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
fs10.utimesSync(pth.resolve(targetPath, entryName), entry.header.time, entry.header.time);
|
|
2036
|
-
} catch (err2) {
|
|
2037
|
-
callback(new Error("Unable to set utimes"));
|
|
2038
|
-
}
|
|
2039
|
-
if (i <= 0) return;
|
|
2040
|
-
if (!succ) {
|
|
2041
|
-
i = 0;
|
|
2042
|
-
callback(new Error("Unable to write"));
|
|
2043
|
-
return;
|
|
2044
|
-
}
|
|
2045
|
-
if (--i === 0)
|
|
2046
|
-
callback(void 0);
|
|
2047
|
-
});
|
|
2048
|
-
});
|
|
2049
|
-
});
|
|
2677
|
+
};
|
|
2678
|
+
}, done)();
|
|
2050
2679
|
},
|
|
2051
2680
|
/**
|
|
2052
2681
|
* Writes the newly created zip file to disk at the specified location or if a zip was opened and no ``targetFileName`` is provided, it will overwrite the opened zip
|
|
2053
2682
|
*
|
|
2054
|
-
* @param targetFileName
|
|
2055
|
-
* @param callback
|
|
2683
|
+
* @param {string} targetFileName
|
|
2684
|
+
* @param {function} callback
|
|
2056
2685
|
*/
|
|
2057
2686
|
writeZip: function(targetFileName, callback) {
|
|
2058
2687
|
if (arguments.length === 1) {
|
|
@@ -2061,23 +2690,54 @@ var require_adm_zip = __commonJS({
|
|
|
2061
2690
|
targetFileName = "";
|
|
2062
2691
|
}
|
|
2063
2692
|
}
|
|
2064
|
-
if (!targetFileName &&
|
|
2065
|
-
targetFileName =
|
|
2693
|
+
if (!targetFileName && opts.filename) {
|
|
2694
|
+
targetFileName = opts.filename;
|
|
2066
2695
|
}
|
|
2067
2696
|
if (!targetFileName) return;
|
|
2068
2697
|
var zipData = _zip.compressToBuffer();
|
|
2069
2698
|
if (zipData) {
|
|
2070
|
-
var ok =
|
|
2699
|
+
var ok = filetools.writeFileTo(targetFileName, zipData, true);
|
|
2071
2700
|
if (typeof callback === "function") callback(!ok ? new Error("failed") : null, "");
|
|
2072
2701
|
}
|
|
2073
2702
|
},
|
|
2703
|
+
/**
|
|
2704
|
+
*
|
|
2705
|
+
* @param {string} targetFileName
|
|
2706
|
+
* @param {object} [props]
|
|
2707
|
+
* @param {boolean} [props.overwrite=true] If the file already exists at the target path, the file will be overwriten if this is true.
|
|
2708
|
+
* @param {boolean} [props.perm] The file will be set as the permission from the entry if this is true.
|
|
2709
|
+
|
|
2710
|
+
* @returns {Promise<void>}
|
|
2711
|
+
*/
|
|
2712
|
+
writeZipPromise: function(targetFileName, props) {
|
|
2713
|
+
const { overwrite, perm } = Object.assign({ overwrite: true }, props);
|
|
2714
|
+
return new Promise((resolve, reject) => {
|
|
2715
|
+
if (!targetFileName && opts.filename) targetFileName = opts.filename;
|
|
2716
|
+
if (!targetFileName) reject("ADM-ZIP: ZIP File Name Missing");
|
|
2717
|
+
this.toBufferPromise().then((zipData) => {
|
|
2718
|
+
const ret = (done) => done ? resolve(done) : reject("ADM-ZIP: Wasn't able to write zip file");
|
|
2719
|
+
filetools.writeFileToAsync(targetFileName, zipData, overwrite, perm, ret);
|
|
2720
|
+
}, reject);
|
|
2721
|
+
});
|
|
2722
|
+
},
|
|
2723
|
+
/**
|
|
2724
|
+
* @returns {Promise<Buffer>} A promise to the Buffer.
|
|
2725
|
+
*/
|
|
2726
|
+
toBufferPromise: function() {
|
|
2727
|
+
return new Promise((resolve, reject) => {
|
|
2728
|
+
_zip.toAsyncBuffer(resolve, reject);
|
|
2729
|
+
});
|
|
2730
|
+
},
|
|
2074
2731
|
/**
|
|
2075
2732
|
* Returns the content of the entire zip file as a Buffer object
|
|
2076
2733
|
*
|
|
2077
|
-
* @
|
|
2734
|
+
* @prop {function} [onSuccess]
|
|
2735
|
+
* @prop {function} [onFail]
|
|
2736
|
+
* @prop {function} [onItemStart]
|
|
2737
|
+
* @prop {function} [onItemEnd]
|
|
2738
|
+
* @returns {Buffer}
|
|
2078
2739
|
*/
|
|
2079
2740
|
toBuffer: function(onSuccess, onFail, onItemStart, onItemEnd) {
|
|
2080
|
-
this.valueOf = 2;
|
|
2081
2741
|
if (typeof onSuccess === "function") {
|
|
2082
2742
|
_zip.toAsyncBuffer(onSuccess, onFail, onItemStart, onItemEnd);
|
|
2083
2743
|
return null;
|
|
@@ -2090,8 +2750,8 @@ var require_adm_zip = __commonJS({
|
|
|
2090
2750
|
});
|
|
2091
2751
|
|
|
2092
2752
|
// src/index.ts
|
|
2093
|
-
import
|
|
2094
|
-
import
|
|
2753
|
+
import fs12 from "node:fs";
|
|
2754
|
+
import path15 from "node:path";
|
|
2095
2755
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
2096
2756
|
import os4 from "node:os";
|
|
2097
2757
|
|
|
@@ -3974,14 +4634,156 @@ async function repairNestedExpertSkillLayouts(openclawRoot) {
|
|
|
3974
4634
|
}
|
|
3975
4635
|
}
|
|
3976
4636
|
}
|
|
3977
|
-
return result;
|
|
4637
|
+
return result;
|
|
4638
|
+
}
|
|
4639
|
+
|
|
4640
|
+
// src/ws-client.ts
|
|
4641
|
+
import WebSocket from "ws";
|
|
4642
|
+
import path10 from "path";
|
|
4643
|
+
import fs9 from "fs/promises";
|
|
4644
|
+
import { DatabaseSync } from "node:sqlite";
|
|
4645
|
+
|
|
4646
|
+
// src/free-skill-directory.ts
|
|
4647
|
+
import fs8 from "node:fs/promises";
|
|
4648
|
+
import path9 from "node:path";
|
|
4649
|
+
var FREE_SKILL_DIRECTORY_NAME = ".xg-platform";
|
|
4650
|
+
var SKILL_FILE_NAME = "SKILL.md";
|
|
4651
|
+
function isRecord(value) {
|
|
4652
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4653
|
+
}
|
|
4654
|
+
function isWithin(parent, candidate) {
|
|
4655
|
+
const relative = path9.relative(parent, candidate);
|
|
4656
|
+
return relative === "" || relative !== ".." && !relative.startsWith(`..${path9.sep}`) && !path9.isAbsolute(relative);
|
|
4657
|
+
}
|
|
4658
|
+
function asNonEmptyString(value) {
|
|
4659
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
4660
|
+
}
|
|
4661
|
+
function parseScalar(value) {
|
|
4662
|
+
const trimmed = value.trim().replace(/\s+#.*$/, "").trim();
|
|
4663
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
4664
|
+
return trimmed.slice(1, -1).trim();
|
|
4665
|
+
}
|
|
4666
|
+
return trimmed;
|
|
4667
|
+
}
|
|
4668
|
+
function parseFrontmatter(content) {
|
|
4669
|
+
const lines = content.replace(/^\uFEFF/, "").split(/\r?\n/);
|
|
4670
|
+
if (lines[0]?.trim() !== "---") return {};
|
|
4671
|
+
const fields = {};
|
|
4672
|
+
for (const line of lines.slice(1)) {
|
|
4673
|
+
if (line.trim() === "---" || line.trim() === "...") break;
|
|
4674
|
+
const match2 = /^\s*([A-Za-z][A-Za-z0-9_-]*)\s*:\s*(.*?)\s*$/.exec(line);
|
|
4675
|
+
if (match2) fields[match2[1]] = parseScalar(match2[2]);
|
|
4676
|
+
}
|
|
4677
|
+
return fields;
|
|
4678
|
+
}
|
|
4679
|
+
async function realPathIfRegularFile(filePath) {
|
|
4680
|
+
try {
|
|
4681
|
+
const resolved = await fs8.realpath(filePath);
|
|
4682
|
+
const stats = await fs8.stat(resolved);
|
|
4683
|
+
return stats.isFile() ? resolved : void 0;
|
|
4684
|
+
} catch {
|
|
4685
|
+
return void 0;
|
|
4686
|
+
}
|
|
4687
|
+
}
|
|
4688
|
+
async function readOptionalMetadata(skillPath, workspacePath) {
|
|
4689
|
+
const candidate = path9.resolve(skillPath, ".meta.json");
|
|
4690
|
+
if (!isWithin(skillPath, candidate) || !isWithin(workspacePath, candidate)) return {};
|
|
4691
|
+
const metadataPath = await realPathIfRegularFile(candidate);
|
|
4692
|
+
if (!metadataPath || !isWithin(skillPath, metadataPath) || !isWithin(workspacePath, metadataPath)) return {};
|
|
4693
|
+
try {
|
|
4694
|
+
const parsed = JSON.parse(await fs8.readFile(metadataPath, "utf8"));
|
|
4695
|
+
if (!isRecord(parsed)) return {};
|
|
4696
|
+
return parsed;
|
|
4697
|
+
} catch {
|
|
4698
|
+
return {};
|
|
4699
|
+
}
|
|
4700
|
+
}
|
|
4701
|
+
async function scanSkill(directoryPath, workspacePath, entryName) {
|
|
4702
|
+
const candidateSkillPath = path9.resolve(directoryPath, entryName);
|
|
4703
|
+
if (!isWithin(directoryPath, candidateSkillPath) || !isWithin(workspacePath, candidateSkillPath)) return void 0;
|
|
4704
|
+
const skillPath = await realPathIfRegularFile(candidateSkillPath);
|
|
4705
|
+
if (skillPath) return void 0;
|
|
4706
|
+
let resolvedSkillPath;
|
|
4707
|
+
try {
|
|
4708
|
+
resolvedSkillPath = await fs8.realpath(candidateSkillPath);
|
|
4709
|
+
const stats = await fs8.stat(resolvedSkillPath);
|
|
4710
|
+
if (!stats.isDirectory()) return void 0;
|
|
4711
|
+
} catch {
|
|
4712
|
+
return void 0;
|
|
4713
|
+
}
|
|
4714
|
+
if (!isWithin(directoryPath, resolvedSkillPath) || !isWithin(workspacePath, resolvedSkillPath)) return void 0;
|
|
4715
|
+
const candidateSkillFilePath = path9.resolve(resolvedSkillPath, SKILL_FILE_NAME);
|
|
4716
|
+
if (!isWithin(resolvedSkillPath, candidateSkillFilePath) || !isWithin(workspacePath, candidateSkillFilePath)) {
|
|
4717
|
+
return void 0;
|
|
4718
|
+
}
|
|
4719
|
+
const skillFilePath = await realPathIfRegularFile(candidateSkillFilePath);
|
|
4720
|
+
if (!skillFilePath || !isWithin(resolvedSkillPath, skillFilePath) || !isWithin(workspacePath, skillFilePath)) {
|
|
4721
|
+
return void 0;
|
|
4722
|
+
}
|
|
4723
|
+
let skillFileContent;
|
|
4724
|
+
try {
|
|
4725
|
+
skillFileContent = await fs8.readFile(skillFilePath, "utf8");
|
|
4726
|
+
} catch {
|
|
4727
|
+
return void 0;
|
|
4728
|
+
}
|
|
4729
|
+
const frontmatter = parseFrontmatter(skillFileContent);
|
|
4730
|
+
const meta = await readOptionalMetadata(resolvedSkillPath, workspacePath);
|
|
4731
|
+
const nestedMetadata = isRecord(meta.metadata) ? meta.metadata : {};
|
|
4732
|
+
const getValue = (...values) => {
|
|
4733
|
+
for (const value of values) {
|
|
4734
|
+
const result = asNonEmptyString(value);
|
|
4735
|
+
if (result) return result;
|
|
4736
|
+
}
|
|
4737
|
+
return void 0;
|
|
4738
|
+
};
|
|
4739
|
+
const code = entryName;
|
|
4740
|
+
return {
|
|
4741
|
+
code,
|
|
4742
|
+
name: getValue(meta.name, nestedMetadata.name, frontmatter.name) ?? code,
|
|
4743
|
+
description: getValue(meta.description, nestedMetadata.description, frontmatter.description) ?? "",
|
|
4744
|
+
version: getValue(meta.version, nestedMetadata.version, frontmatter.version) ?? "",
|
|
4745
|
+
directoryPath,
|
|
4746
|
+
skillPath: resolvedSkillPath,
|
|
4747
|
+
skillFilePath
|
|
4748
|
+
};
|
|
4749
|
+
}
|
|
4750
|
+
async function scanFreeSkillDirectory(workspace) {
|
|
4751
|
+
const resolvedWorkspace = path9.resolve(workspace);
|
|
4752
|
+
let workspacePath;
|
|
4753
|
+
try {
|
|
4754
|
+
workspacePath = await fs8.realpath(resolvedWorkspace);
|
|
4755
|
+
const stats = await fs8.stat(workspacePath);
|
|
4756
|
+
if (!stats.isDirectory()) return [];
|
|
4757
|
+
} catch {
|
|
4758
|
+
return [];
|
|
4759
|
+
}
|
|
4760
|
+
const candidateDirectoryPath = path9.resolve(workspacePath, FREE_SKILL_DIRECTORY_NAME);
|
|
4761
|
+
if (!isWithin(workspacePath, candidateDirectoryPath)) return [];
|
|
4762
|
+
let directoryPath;
|
|
4763
|
+
try {
|
|
4764
|
+
directoryPath = await fs8.realpath(candidateDirectoryPath);
|
|
4765
|
+
const stats = await fs8.stat(directoryPath);
|
|
4766
|
+
if (!stats.isDirectory()) return [];
|
|
4767
|
+
} catch {
|
|
4768
|
+
return [];
|
|
4769
|
+
}
|
|
4770
|
+
if (!isWithin(workspacePath, directoryPath)) return [];
|
|
4771
|
+
let entries;
|
|
4772
|
+
try {
|
|
4773
|
+
entries = await fs8.readdir(directoryPath, { withFileTypes: true });
|
|
4774
|
+
} catch {
|
|
4775
|
+
return [];
|
|
4776
|
+
}
|
|
4777
|
+
const skills = [];
|
|
4778
|
+
for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
4779
|
+
if (!entry.isDirectory()) continue;
|
|
4780
|
+
const skill = await scanSkill(directoryPath, workspacePath, entry.name);
|
|
4781
|
+
if (skill) skills.push(skill);
|
|
4782
|
+
}
|
|
4783
|
+
return skills;
|
|
3978
4784
|
}
|
|
3979
4785
|
|
|
3980
4786
|
// src/ws-client.ts
|
|
3981
|
-
import WebSocket from "ws";
|
|
3982
|
-
import path9 from "path";
|
|
3983
|
-
import fs8 from "fs/promises";
|
|
3984
|
-
import { DatabaseSync } from "node:sqlite";
|
|
3985
4787
|
var HEARTBEAT_INTERVAL_MS = 3e4;
|
|
3986
4788
|
var HEARTBEAT_ACK_TIMEOUT_MS = 75e3;
|
|
3987
4789
|
var AGENT_SCAN_INTERVAL_MS = 3 * 60 * 1e3;
|
|
@@ -4034,10 +4836,10 @@ function resolveSkillInstallTarget(config, userId) {
|
|
|
4034
4836
|
if (typeof workspace !== "string" || !workspace.trim()) {
|
|
4035
4837
|
throw new Error(`\u672C\u5730 Agent ${localAgentId} \u672A\u914D\u7F6E workspace`);
|
|
4036
4838
|
}
|
|
4037
|
-
return { skillsDir:
|
|
4839
|
+
return { skillsDir: path10.join(workspace, "skills"), localAgentId };
|
|
4038
4840
|
}
|
|
4039
4841
|
function normalizeAssistantUserId(userId) {
|
|
4040
|
-
const safeUserId =
|
|
4842
|
+
const safeUserId = path10.basename(userId);
|
|
4041
4843
|
if (safeUserId !== userId) return void 0;
|
|
4042
4844
|
const pureId = safeUserId.startsWith(ASSISTANT_AGENT_PREFIX) ? safeUserId.slice(ASSISTANT_AGENT_PREFIX.length) : safeUserId;
|
|
4043
4845
|
if (!ASSISTANT_WORKSPACE_ID_RE.test(pureId)) return void 0;
|
|
@@ -4046,29 +4848,29 @@ function normalizeAssistantUserId(userId) {
|
|
|
4046
4848
|
function normalizeCommandCode(code) {
|
|
4047
4849
|
if (typeof code !== "string" || code.length === 0 || code === "." || code === "..") return void 0;
|
|
4048
4850
|
if (code.includes("/") || code.includes("\\") || code.includes("\0")) return void 0;
|
|
4049
|
-
if (
|
|
4851
|
+
if (path10.basename(code) !== code) return void 0;
|
|
4050
4852
|
return code;
|
|
4051
4853
|
}
|
|
4052
4854
|
function shouldSyncBuiltInTemplate(action, isBuiltIn) {
|
|
4053
4855
|
return action === "UPDATE_SKILL" && isBuiltIn === true;
|
|
4054
4856
|
}
|
|
4055
4857
|
function resolveGatewaySkillTarget(home = openclawHome()) {
|
|
4056
|
-
return
|
|
4858
|
+
return path10.join(home, "skills");
|
|
4057
4859
|
}
|
|
4058
4860
|
function isGatewaySkillCommand(action, installScope) {
|
|
4059
4861
|
return installScope === "gateway" && ["INSTALL_SKILL", "UPDATE_SKILL", "UNINSTALL_SKILL"].includes(String(action || ""));
|
|
4060
4862
|
}
|
|
4061
4863
|
async function findInstalledExpertSkillsRoot(rootPath, pureId, code) {
|
|
4062
|
-
const skillsRoot =
|
|
4864
|
+
const skillsRoot = path10.join(rootPath, `workspace-assistant-${pureId}`, ".user", "skills");
|
|
4063
4865
|
try {
|
|
4064
|
-
const stat = await
|
|
4866
|
+
const stat = await fs9.stat(path10.join(skillsRoot, code));
|
|
4065
4867
|
return stat.isDirectory() ? skillsRoot : void 0;
|
|
4066
4868
|
} catch {
|
|
4067
4869
|
return void 0;
|
|
4068
4870
|
}
|
|
4069
4871
|
}
|
|
4070
4872
|
function defaultOpenclawSqlitePath() {
|
|
4071
|
-
return
|
|
4873
|
+
return path10.join(openclawHome(), "state", "openclaw.sqlite");
|
|
4072
4874
|
}
|
|
4073
4875
|
function readCronJobsByAgentId(agentId, sqlitePath = defaultOpenclawSqlitePath(), onError) {
|
|
4074
4876
|
let db;
|
|
@@ -4082,6 +4884,49 @@ function readCronJobsByAgentId(agentId, sqlitePath = defaultOpenclawSqlitePath()
|
|
|
4082
4884
|
db?.close();
|
|
4083
4885
|
}
|
|
4084
4886
|
}
|
|
4887
|
+
function isWithinPath(parent, candidate) {
|
|
4888
|
+
const relative = path10.relative(parent, candidate);
|
|
4889
|
+
return relative === "" || relative !== ".." && !relative.startsWith(`..${path10.sep}`) && !path10.isAbsolute(relative);
|
|
4890
|
+
}
|
|
4891
|
+
function relativeWorkspacePath(workspace, target) {
|
|
4892
|
+
const relative = path10.relative(workspace, target);
|
|
4893
|
+
return isWithinPath(workspace, target) ? relative : "";
|
|
4894
|
+
}
|
|
4895
|
+
async function resolveRealWorkspace(workspace) {
|
|
4896
|
+
const resolved = path10.resolve(workspace);
|
|
4897
|
+
try {
|
|
4898
|
+
return await fs9.realpath(resolved);
|
|
4899
|
+
} catch {
|
|
4900
|
+
return resolved;
|
|
4901
|
+
}
|
|
4902
|
+
}
|
|
4903
|
+
async function resolveFreeSkillDirectoryPath(workspace) {
|
|
4904
|
+
const workspacePath = await resolveRealWorkspace(workspace);
|
|
4905
|
+
const candidate = path10.resolve(workspacePath, ".xg-platform");
|
|
4906
|
+
try {
|
|
4907
|
+
const directoryPath = await fs9.realpath(candidate);
|
|
4908
|
+
const stat = await fs9.stat(directoryPath);
|
|
4909
|
+
return stat.isDirectory() && isWithinPath(workspacePath, directoryPath) ? directoryPath : "";
|
|
4910
|
+
} catch {
|
|
4911
|
+
return "";
|
|
4912
|
+
}
|
|
4913
|
+
}
|
|
4914
|
+
function buildFreeSkillDirectoryResponse(gatewayId, agentId, workspacePath, directoryPath, skills) {
|
|
4915
|
+
return {
|
|
4916
|
+
gatewayId,
|
|
4917
|
+
agentId,
|
|
4918
|
+
directoryPath,
|
|
4919
|
+
skills: skills.map((skill) => ({
|
|
4920
|
+
code: skill.code,
|
|
4921
|
+
name: skill.name,
|
|
4922
|
+
description: skill.description,
|
|
4923
|
+
version: skill.version,
|
|
4924
|
+
workspaceRelativePath: relativeWorkspacePath(workspacePath, skill.skillPath),
|
|
4925
|
+
skillFilePath: relativeWorkspacePath(workspacePath, skill.skillFilePath),
|
|
4926
|
+
hostSkillFilePath: skill.skillFilePath
|
|
4927
|
+
}))
|
|
4928
|
+
};
|
|
4929
|
+
}
|
|
4085
4930
|
var GatewayWsClient = class {
|
|
4086
4931
|
ws = null;
|
|
4087
4932
|
options;
|
|
@@ -4108,10 +4953,10 @@ var GatewayWsClient = class {
|
|
|
4108
4953
|
}
|
|
4109
4954
|
}
|
|
4110
4955
|
logLine += "\n";
|
|
4111
|
-
const logsDir =
|
|
4112
|
-
|
|
4113
|
-
const logPath =
|
|
4114
|
-
|
|
4956
|
+
const logsDir = path10.join(openclawHome(), "logs");
|
|
4957
|
+
fs9.mkdir(logsDir, { recursive: true }).then(() => {
|
|
4958
|
+
const logPath = path10.join(logsDir, "skill-logger.err");
|
|
4959
|
+
fs9.appendFile(logPath, logLine).catch(() => {
|
|
4115
4960
|
});
|
|
4116
4961
|
}).catch(() => {
|
|
4117
4962
|
});
|
|
@@ -4126,16 +4971,25 @@ var GatewayWsClient = class {
|
|
|
4126
4971
|
});
|
|
4127
4972
|
};
|
|
4128
4973
|
}
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
const configPath = path9.join(openclawHome(), "openclaw.json");
|
|
4132
|
-
let config;
|
|
4974
|
+
async readOpenclawConfig() {
|
|
4975
|
+
const configPath = path10.join(openclawHome(), "openclaw.json");
|
|
4133
4976
|
try {
|
|
4134
|
-
|
|
4977
|
+
return JSON.parse(await fs9.readFile(configPath, "utf-8"));
|
|
4135
4978
|
} catch (err) {
|
|
4136
4979
|
throw new Error(`\u65E0\u6CD5\u8BFB\u53D6 openclaw.json: ${err?.message || String(err)}`);
|
|
4137
4980
|
}
|
|
4138
|
-
|
|
4981
|
+
}
|
|
4982
|
+
async resolveRegularSkillContext(userId) {
|
|
4983
|
+
const target = resolveSkillInstallTarget(await this.readOpenclawConfig(), userId);
|
|
4984
|
+
return { ...target, workspace: path10.dirname(target.skillsDir) };
|
|
4985
|
+
}
|
|
4986
|
+
/** 普通 Skill 的所有读写操作共用这一个配置驱动的寻址入口。 */
|
|
4987
|
+
async resolveRegularSkillTarget(userId) {
|
|
4988
|
+
return (await this.resolveRegularSkillContext(userId)).skillsDir;
|
|
4989
|
+
}
|
|
4990
|
+
async resolveFreeSkillRequestContext(userId) {
|
|
4991
|
+
const target = await this.resolveRegularSkillContext(userId);
|
|
4992
|
+
return { workspace: target.workspace, agentId: target.localAgentId };
|
|
4139
4993
|
}
|
|
4140
4994
|
constructor(options) {
|
|
4141
4995
|
this.options = options;
|
|
@@ -4236,10 +5090,10 @@ var GatewayWsClient = class {
|
|
|
4236
5090
|
async scanAndReportAgents(isInitialReport) {
|
|
4237
5091
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
|
|
4238
5092
|
try {
|
|
4239
|
-
const configPath =
|
|
5093
|
+
const configPath = path10.join(openclawHome(), "openclaw.json");
|
|
4240
5094
|
let rawConfig;
|
|
4241
5095
|
try {
|
|
4242
|
-
rawConfig = await
|
|
5096
|
+
rawConfig = await fs9.readFile(configPath, "utf-8");
|
|
4243
5097
|
} catch (e) {
|
|
4244
5098
|
this.appendLogToFile("WARN", "AgentScan", "OpenClaw config is not readable; skipping this scan cycle", e);
|
|
4245
5099
|
return;
|
|
@@ -4423,6 +5277,14 @@ var GatewayWsClient = class {
|
|
|
4423
5277
|
}
|
|
4424
5278
|
if (!userId) {
|
|
4425
5279
|
this.appendLogToFile("WARN", "Command", `Message dropped: missing userId`, msg);
|
|
5280
|
+
if (action === "LIST_FREE_SKILLS") {
|
|
5281
|
+
this.reply(replyId, {
|
|
5282
|
+
success: false,
|
|
5283
|
+
error: "INVALID_REQUEST",
|
|
5284
|
+
message: "Missing userId parameter",
|
|
5285
|
+
action
|
|
5286
|
+
});
|
|
5287
|
+
}
|
|
4426
5288
|
return;
|
|
4427
5289
|
}
|
|
4428
5290
|
const safeCode = normalizeCommandCode(code);
|
|
@@ -4461,14 +5323,27 @@ var GatewayWsClient = class {
|
|
|
4461
5323
|
const targetDir = gatewaySkillCommand ? resolveGatewaySkillTarget() : await this.resolveRegularSkillTarget(userId);
|
|
4462
5324
|
console.log(`[skill-logger-plugin][WS] Executing UNINSTALL for user ${userId}, code: ${safeCode}`);
|
|
4463
5325
|
this.appendLogToFile("INFO", "Command", `UNINSTALL_SKILL received`, { userId, code: safeCode });
|
|
4464
|
-
const skillPath =
|
|
4465
|
-
await
|
|
5326
|
+
const skillPath = path10.join(targetDir, safeCode);
|
|
5327
|
+
await fs9.rm(skillPath, { recursive: true, force: true });
|
|
4466
5328
|
this.reply(replyId, {
|
|
4467
5329
|
success: true,
|
|
4468
5330
|
message: `Skill ${safeCode} removed`,
|
|
4469
5331
|
action,
|
|
4470
5332
|
data: { code: safeCode, installScope: gatewaySkillCommand ? "gateway" : "agent", removed: true }
|
|
4471
5333
|
});
|
|
5334
|
+
} else if (action === "LIST_FREE_SKILLS") {
|
|
5335
|
+
const context = await this.resolveFreeSkillRequestContext(userId);
|
|
5336
|
+
const workspacePath = await resolveRealWorkspace(context.workspace);
|
|
5337
|
+
const scannedSkills = await scanFreeSkillDirectory(context.workspace);
|
|
5338
|
+
const directoryPath = scannedSkills[0]?.directoryPath || await resolveFreeSkillDirectoryPath(context.workspace);
|
|
5339
|
+
const data = buildFreeSkillDirectoryResponse(
|
|
5340
|
+
this.options.gatewayId,
|
|
5341
|
+
context.agentId,
|
|
5342
|
+
workspacePath,
|
|
5343
|
+
directoryPath,
|
|
5344
|
+
scannedSkills
|
|
5345
|
+
);
|
|
5346
|
+
this.reply(replyId, { success: true, data, action });
|
|
4472
5347
|
} else if (action === "LIST_SKILLS") {
|
|
4473
5348
|
const regularTargetDir = await this.resolveRegularSkillTarget(userId);
|
|
4474
5349
|
const skillsByCode = /* @__PURE__ */ new Map();
|
|
@@ -4479,22 +5354,22 @@ var GatewayWsClient = class {
|
|
|
4479
5354
|
for (const source of sources) {
|
|
4480
5355
|
let entries;
|
|
4481
5356
|
try {
|
|
4482
|
-
entries = await
|
|
5357
|
+
entries = await fs9.readdir(source.dir, { withFileTypes: true });
|
|
4483
5358
|
} catch (err) {
|
|
4484
5359
|
if (err?.code === "ENOENT") continue;
|
|
4485
5360
|
throw err;
|
|
4486
5361
|
}
|
|
4487
5362
|
const dirs = entries.filter((e) => (e.isDirectory() || e.isSymbolicLink()) && !e.name.startsWith("."));
|
|
4488
5363
|
for (const e of dirs) {
|
|
4489
|
-
const skillDir =
|
|
4490
|
-
const skillMdPath =
|
|
5364
|
+
const skillDir = path10.join(source.dir, e.name);
|
|
5365
|
+
const skillMdPath = path10.join(skillDir, "SKILL.md");
|
|
4491
5366
|
try {
|
|
4492
|
-
const stat = await
|
|
5367
|
+
const stat = await fs9.stat(skillMdPath);
|
|
4493
5368
|
if (!stat.isFile()) continue;
|
|
4494
5369
|
} catch {
|
|
4495
5370
|
continue;
|
|
4496
5371
|
}
|
|
4497
|
-
const metaPath =
|
|
5372
|
+
const metaPath = path10.join(skillDir, ".meta.json");
|
|
4498
5373
|
let isPlatform = source.gatewayBuiltIn;
|
|
4499
5374
|
let isBuiltIn2 = source.gatewayBuiltIn || e.isSymbolicLink();
|
|
4500
5375
|
let metaData = null;
|
|
@@ -4502,7 +5377,7 @@ var GatewayWsClient = class {
|
|
|
4502
5377
|
let description = "";
|
|
4503
5378
|
let skillVersion = "";
|
|
4504
5379
|
try {
|
|
4505
|
-
const mdContent = await
|
|
5380
|
+
const mdContent = await fs9.readFile(skillMdPath, "utf8");
|
|
4506
5381
|
const fm = /^---\r?\n([\s\S]*?)\r?\n---/.exec(mdContent)?.[1] ?? "";
|
|
4507
5382
|
const parsedName = /(^|\n)name:\s*(.+)/.exec(fm)?.[2]?.trim();
|
|
4508
5383
|
if (parsedName) name = parsedName;
|
|
@@ -4511,7 +5386,7 @@ var GatewayWsClient = class {
|
|
|
4511
5386
|
} catch {
|
|
4512
5387
|
}
|
|
4513
5388
|
try {
|
|
4514
|
-
const parsed = JSON.parse(await
|
|
5389
|
+
const parsed = JSON.parse(await fs9.readFile(metaPath, "utf8"));
|
|
4515
5390
|
if (parsed) {
|
|
4516
5391
|
if (parsed.ownerId === "CMS" || parsed.ownerId === "CMS_COMPAT") isPlatform = true;
|
|
4517
5392
|
if (parsed.isBuiltIn === true || parsed.ownerId === "built-in") isBuiltIn2 = true;
|
|
@@ -4561,7 +5436,7 @@ var GatewayWsClient = class {
|
|
|
4561
5436
|
setTimeout(async () => {
|
|
4562
5437
|
try {
|
|
4563
5438
|
const targetDir = gatewaySkillCommand ? resolveGatewaySkillTarget() : await this.resolveRegularSkillTarget(userId);
|
|
4564
|
-
const additionalTargetDirs = syncBuiltInTemplate ? [
|
|
5439
|
+
const additionalTargetDirs = syncBuiltInTemplate ? [path10.join(openclawHome(), "workspace-xgjk-assistant-template", "skills")] : [];
|
|
4565
5440
|
const userSkillRoot = pureId ? await findInstalledExpertSkillsRoot(openclawHome(), pureId, safeCode) : void 0;
|
|
4566
5441
|
if (userSkillRoot) additionalTargetDirs.push(userSkillRoot);
|
|
4567
5442
|
const result = await this.options.updater.manualInstall({
|
|
@@ -4612,12 +5487,12 @@ var GatewayWsClient = class {
|
|
|
4612
5487
|
const { name, version: version2, downloadUrl, skills } = msg;
|
|
4613
5488
|
console.log(`[skill-logger-plugin][WS] Executing INSTALL_EXPERT for user ${userId}, code: ${safeCode}`);
|
|
4614
5489
|
this.appendLogToFile("INFO", "Command", `INSTALL_EXPERT received`, { userId, code: safeCode, version: version2, downloadUrl });
|
|
4615
|
-
const userSkillRoot =
|
|
4616
|
-
const expertTarget =
|
|
5490
|
+
const userSkillRoot = path10.join(openclawHome(), `workspace-assistant-${pureId}`, ".user");
|
|
5491
|
+
const expertTarget = path10.join(userSkillRoot, "experts", safeCode);
|
|
4617
5492
|
let skipInstall = false;
|
|
4618
|
-
const metaPath =
|
|
5493
|
+
const metaPath = path10.join(expertTarget, ".meta.json");
|
|
4619
5494
|
try {
|
|
4620
|
-
const raw = await
|
|
5495
|
+
const raw = await fs9.readFile(metaPath, "utf-8");
|
|
4621
5496
|
const existing = JSON.parse(raw);
|
|
4622
5497
|
if (existing.version && existing.version === (version2 || "1.0.0")) {
|
|
4623
5498
|
skipInstall = true;
|
|
@@ -4625,16 +5500,16 @@ var GatewayWsClient = class {
|
|
|
4625
5500
|
} catch {
|
|
4626
5501
|
}
|
|
4627
5502
|
if (!skipInstall) {
|
|
4628
|
-
await
|
|
5503
|
+
await fs9.mkdir(path10.dirname(expertTarget), { recursive: true });
|
|
4629
5504
|
const expertResult = await this.options.updater.installExpertZipFromUrl(downloadUrl, expertTarget);
|
|
4630
5505
|
if (!expertResult.success) {
|
|
4631
5506
|
throw new Error(`\u4E13\u5BB6\u5B89\u88C5\u5931\u8D25: ${expertResult.message}`);
|
|
4632
5507
|
}
|
|
4633
5508
|
}
|
|
4634
5509
|
const meta = { code: safeCode, name, version: version2 || "1.0.0", installedAt: Date.now() };
|
|
4635
|
-
await
|
|
4636
|
-
const skillTargetRoot =
|
|
4637
|
-
await
|
|
5510
|
+
await fs9.writeFile(metaPath, JSON.stringify(meta, null, 2));
|
|
5511
|
+
const skillTargetRoot = path10.join(userSkillRoot, "skills");
|
|
5512
|
+
await fs9.mkdir(skillTargetRoot, { recursive: true });
|
|
4638
5513
|
const skillResults = [];
|
|
4639
5514
|
if (Array.isArray(skills)) {
|
|
4640
5515
|
for (const sk of skills) {
|
|
@@ -4671,23 +5546,23 @@ var GatewayWsClient = class {
|
|
|
4671
5546
|
if (!safeCode) throw new Error("Missing code parameter");
|
|
4672
5547
|
console.log(`[skill-logger-plugin][WS] Executing UNINSTALL_EXPERT for user ${userId}, code: ${safeCode}`);
|
|
4673
5548
|
this.appendLogToFile("INFO", "Command", `UNINSTALL_EXPERT received`, { userId, code: safeCode });
|
|
4674
|
-
const expertPath =
|
|
4675
|
-
await
|
|
5549
|
+
const expertPath = path10.join(openclawHome(), `workspace-assistant-${pureId}`, ".user", "experts", safeCode);
|
|
5550
|
+
await fs9.rm(expertPath, { recursive: true, force: true });
|
|
4676
5551
|
this.reply(replyId, { success: true, message: `\u4E13\u5BB6 ${safeCode} \u5DF2\u5378\u8F7D`, action });
|
|
4677
5552
|
} else if (action === "LIST_EXPERTS") {
|
|
4678
5553
|
console.log(`[skill-logger-plugin][WS] Executing LIST_EXPERTS for user ${userId}`);
|
|
4679
5554
|
this.appendLogToFile("INFO", "Command", `LIST_EXPERTS received`, { userId });
|
|
4680
|
-
const expertsDir =
|
|
5555
|
+
const expertsDir = path10.join(openclawHome(), `workspace-assistant-${pureId}`, ".user", "experts");
|
|
4681
5556
|
const list = [];
|
|
4682
5557
|
try {
|
|
4683
|
-
const stat = await
|
|
5558
|
+
const stat = await fs9.stat(expertsDir);
|
|
4684
5559
|
if (stat.isDirectory()) {
|
|
4685
|
-
const entries = await
|
|
5560
|
+
const entries = await fs9.readdir(expertsDir, { withFileTypes: true });
|
|
4686
5561
|
for (const e of entries) {
|
|
4687
5562
|
if (!e.isDirectory()) continue;
|
|
4688
|
-
const metaPath =
|
|
5563
|
+
const metaPath = path10.join(expertsDir, e.name, ".meta.json");
|
|
4689
5564
|
try {
|
|
4690
|
-
const raw = await
|
|
5565
|
+
const raw = await fs9.readFile(metaPath, "utf-8");
|
|
4691
5566
|
const meta = JSON.parse(raw);
|
|
4692
5567
|
list.push({
|
|
4693
5568
|
code: meta.code || e.name,
|
|
@@ -4706,7 +5581,17 @@ var GatewayWsClient = class {
|
|
|
4706
5581
|
} else {
|
|
4707
5582
|
console.warn(`[skill-logger-plugin][WS] Unknown action: ${action}`);
|
|
4708
5583
|
this.appendLogToFile("WARN", "Command", `Unknown action: ${action}`);
|
|
4709
|
-
|
|
5584
|
+
if (action === "LIST_FREE_SKILLS") {
|
|
5585
|
+
this.reply(replyId, {
|
|
5586
|
+
success: false,
|
|
5587
|
+
unsupported: true,
|
|
5588
|
+
error: "UNSUPPORTED_ACTION",
|
|
5589
|
+
message: "LIST_FREE_SKILLS unsupported by this plugin",
|
|
5590
|
+
action
|
|
5591
|
+
});
|
|
5592
|
+
} else {
|
|
5593
|
+
this.reply(replyId, { success: false, message: `Unknown action: ${action}`, action });
|
|
5594
|
+
}
|
|
4710
5595
|
}
|
|
4711
5596
|
} catch (err) {
|
|
4712
5597
|
this.appendLogToFile("ERROR", "Command", `Error executing action ${action}`, err);
|
|
@@ -4741,7 +5626,7 @@ var GatewayWsClient = class {
|
|
|
4741
5626
|
};
|
|
4742
5627
|
|
|
4743
5628
|
// src/hooks.ts
|
|
4744
|
-
import
|
|
5629
|
+
import path11 from "node:path";
|
|
4745
5630
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
4746
5631
|
var PENDING_TTL_MS = 30 * 60 * 1e3;
|
|
4747
5632
|
var PENDING_MAX = 5e3;
|
|
@@ -4750,7 +5635,7 @@ function toMySQLDateTime(d) {
|
|
|
4750
5635
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
|
4751
5636
|
}
|
|
4752
5637
|
function isSkillMdReadPath(filePath) {
|
|
4753
|
-
return
|
|
5638
|
+
return path11.basename(filePath) === "SKILL.md";
|
|
4754
5639
|
}
|
|
4755
5640
|
function extractAppKey(event, ctx) {
|
|
4756
5641
|
try {
|
|
@@ -4930,8 +5815,8 @@ var Hooks = class {
|
|
|
4930
5815
|
if (toolName === "read") {
|
|
4931
5816
|
const filePath = params.path ?? params.file_path ?? "";
|
|
4932
5817
|
if (!isSkillMdReadPath(filePath)) return;
|
|
4933
|
-
const rootDir =
|
|
4934
|
-
const skillName = this.configSync.resolveSkillName(rootDir) ||
|
|
5818
|
+
const rootDir = path11.dirname(filePath);
|
|
5819
|
+
const skillName = this.configSync.resolveSkillName(rootDir) || path11.basename(rootDir);
|
|
4935
5820
|
if (!skillName) return;
|
|
4936
5821
|
this.debug(`Intercepted 'read' for SKILL.md. Attributed to skill: ${skillName}`);
|
|
4937
5822
|
this.recordTrigger(skillName, "inline", "read", ctx, appKey);
|
|
@@ -5113,6 +5998,637 @@ var Hooks = class {
|
|
|
5113
5998
|
}
|
|
5114
5999
|
};
|
|
5115
6000
|
|
|
6001
|
+
// src/free-skill-tool.ts
|
|
6002
|
+
import path14 from "node:path";
|
|
6003
|
+
|
|
6004
|
+
// src/free-skill-writer.ts
|
|
6005
|
+
import crypto from "node:crypto";
|
|
6006
|
+
import fs11 from "node:fs/promises";
|
|
6007
|
+
import path13 from "node:path";
|
|
6008
|
+
|
|
6009
|
+
// src/free-skill-workspace.ts
|
|
6010
|
+
import fs10 from "node:fs/promises";
|
|
6011
|
+
import path12 from "node:path";
|
|
6012
|
+
var FREE_SKILL_DIRECTORY_NAME2 = ".xg-platform";
|
|
6013
|
+
var FreeSkillWorkspaceError = class extends Error {
|
|
6014
|
+
code;
|
|
6015
|
+
constructor(code, message) {
|
|
6016
|
+
super(message);
|
|
6017
|
+
this.code = code;
|
|
6018
|
+
this.name = "FreeSkillWorkspaceError";
|
|
6019
|
+
}
|
|
6020
|
+
};
|
|
6021
|
+
function isRecord2(value) {
|
|
6022
|
+
return typeof value === "object" && value !== null;
|
|
6023
|
+
}
|
|
6024
|
+
function nonEmptyString(value) {
|
|
6025
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
6026
|
+
}
|
|
6027
|
+
function isWithin2(parent, candidate) {
|
|
6028
|
+
const relative = path12.relative(parent, candidate);
|
|
6029
|
+
return relative === "" || !relative.startsWith(`..${path12.sep}`) && relative !== ".." && !path12.isAbsolute(relative);
|
|
6030
|
+
}
|
|
6031
|
+
function nestedRecord(value, key) {
|
|
6032
|
+
if (!isRecord2(value)) return void 0;
|
|
6033
|
+
const nested = value[key];
|
|
6034
|
+
return isRecord2(nested) ? nested : void 0;
|
|
6035
|
+
}
|
|
6036
|
+
function firstWorkspaceValue(context) {
|
|
6037
|
+
if (!isRecord2(context)) return void 0;
|
|
6038
|
+
const wrapped = nestedRecord(context, "ctx");
|
|
6039
|
+
const nestedContext = nestedRecord(context, "context");
|
|
6040
|
+
const candidates = [
|
|
6041
|
+
context.workspaceDir,
|
|
6042
|
+
context.workspace,
|
|
6043
|
+
wrapped?.workspaceDir,
|
|
6044
|
+
wrapped?.workspace,
|
|
6045
|
+
nestedContext?.workspaceDir,
|
|
6046
|
+
nestedContext?.workspace
|
|
6047
|
+
];
|
|
6048
|
+
return candidates.map(nonEmptyString).find((value) => Boolean(value));
|
|
6049
|
+
}
|
|
6050
|
+
function firstAgentIdValue(context) {
|
|
6051
|
+
if (!isRecord2(context)) return void 0;
|
|
6052
|
+
const wrapped = nestedRecord(context, "ctx");
|
|
6053
|
+
const nestedContext = nestedRecord(context, "context");
|
|
6054
|
+
const agent = isRecord2(context.agent) ? context.agent.id : void 0;
|
|
6055
|
+
const wrappedAgent = isRecord2(wrapped?.agent) ? wrapped?.agent.id : void 0;
|
|
6056
|
+
const nestedContextAgent = isRecord2(nestedContext?.agent) ? nestedContext?.agent.id : void 0;
|
|
6057
|
+
const candidates = [
|
|
6058
|
+
context.agentId,
|
|
6059
|
+
agent,
|
|
6060
|
+
wrapped?.agentId,
|
|
6061
|
+
wrappedAgent,
|
|
6062
|
+
nestedContext?.agentId,
|
|
6063
|
+
nestedContextAgent
|
|
6064
|
+
];
|
|
6065
|
+
return candidates.map(nonEmptyString).find((value) => Boolean(value));
|
|
6066
|
+
}
|
|
6067
|
+
async function resolveWorkspacePath(workspaceInput) {
|
|
6068
|
+
let workspacePath;
|
|
6069
|
+
try {
|
|
6070
|
+
workspacePath = await fs10.realpath(path12.resolve(workspaceInput));
|
|
6071
|
+
} catch {
|
|
6072
|
+
throw new FreeSkillWorkspaceError(
|
|
6073
|
+
"WORKSPACE_MISSING",
|
|
6074
|
+
`Agent workspace \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u8BBF\u95EE: ${workspaceInput}`
|
|
6075
|
+
);
|
|
6076
|
+
}
|
|
6077
|
+
try {
|
|
6078
|
+
const stat = await fs10.stat(workspacePath);
|
|
6079
|
+
if (!stat.isDirectory()) {
|
|
6080
|
+
throw new FreeSkillWorkspaceError(
|
|
6081
|
+
"WORKSPACE_NOT_DIRECTORY",
|
|
6082
|
+
`Agent workspace \u4E0D\u662F\u76EE\u5F55: ${workspaceInput}`
|
|
6083
|
+
);
|
|
6084
|
+
}
|
|
6085
|
+
} catch (error) {
|
|
6086
|
+
if (error instanceof FreeSkillWorkspaceError) throw error;
|
|
6087
|
+
throw new FreeSkillWorkspaceError(
|
|
6088
|
+
"WORKSPACE_MISSING",
|
|
6089
|
+
`Agent workspace \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u8BBF\u95EE: ${workspaceInput}`
|
|
6090
|
+
);
|
|
6091
|
+
}
|
|
6092
|
+
return workspacePath;
|
|
6093
|
+
}
|
|
6094
|
+
async function resolvePlatformDirectory(workspacePath) {
|
|
6095
|
+
const candidate = path12.resolve(workspacePath, FREE_SKILL_DIRECTORY_NAME2);
|
|
6096
|
+
if (!isWithin2(workspacePath, candidate)) {
|
|
6097
|
+
throw new FreeSkillWorkspaceError(
|
|
6098
|
+
"PLATFORM_DIRECTORY_ESCAPE",
|
|
6099
|
+
"`.xg-platform` \u4E0D\u5728 Agent workspace \u5185"
|
|
6100
|
+
);
|
|
6101
|
+
}
|
|
6102
|
+
let entry;
|
|
6103
|
+
try {
|
|
6104
|
+
entry = await fs10.lstat(candidate);
|
|
6105
|
+
} catch (error) {
|
|
6106
|
+
if (error?.code === "ENOENT") return candidate;
|
|
6107
|
+
throw new FreeSkillWorkspaceError(
|
|
6108
|
+
"PLATFORM_DIRECTORY_BROKEN_LINK",
|
|
6109
|
+
"\u65E0\u6CD5\u68C0\u67E5 Agent workspace \u4E0B\u7684 `.xg-platform`"
|
|
6110
|
+
);
|
|
6111
|
+
}
|
|
6112
|
+
let resolved = candidate;
|
|
6113
|
+
if (entry.isSymbolicLink()) {
|
|
6114
|
+
try {
|
|
6115
|
+
resolved = await fs10.realpath(candidate);
|
|
6116
|
+
} catch {
|
|
6117
|
+
throw new FreeSkillWorkspaceError(
|
|
6118
|
+
"PLATFORM_DIRECTORY_BROKEN_LINK",
|
|
6119
|
+
"`.xg-platform` \u662F\u5931\u6548\u7B26\u53F7\u94FE\u63A5"
|
|
6120
|
+
);
|
|
6121
|
+
}
|
|
6122
|
+
if (!isWithin2(workspacePath, resolved)) {
|
|
6123
|
+
throw new FreeSkillWorkspaceError(
|
|
6124
|
+
"PLATFORM_DIRECTORY_ESCAPE",
|
|
6125
|
+
"`.xg-platform` \u7B26\u53F7\u94FE\u63A5\u8D8A\u51FA Agent workspace"
|
|
6126
|
+
);
|
|
6127
|
+
}
|
|
6128
|
+
}
|
|
6129
|
+
try {
|
|
6130
|
+
const stat = await fs10.stat(resolved);
|
|
6131
|
+
if (!stat.isDirectory()) {
|
|
6132
|
+
throw new FreeSkillWorkspaceError(
|
|
6133
|
+
"PLATFORM_DIRECTORY_NOT_DIRECTORY",
|
|
6134
|
+
"Agent workspace \u4E0B\u7684 `.xg-platform` \u4E0D\u662F\u76EE\u5F55"
|
|
6135
|
+
);
|
|
6136
|
+
}
|
|
6137
|
+
} catch (error) {
|
|
6138
|
+
if (error instanceof FreeSkillWorkspaceError) throw error;
|
|
6139
|
+
throw new FreeSkillWorkspaceError(
|
|
6140
|
+
"PLATFORM_DIRECTORY_BROKEN_LINK",
|
|
6141
|
+
"\u65E0\u6CD5\u8BBF\u95EE Agent workspace \u4E0B\u7684 `.xg-platform`"
|
|
6142
|
+
);
|
|
6143
|
+
}
|
|
6144
|
+
return resolved;
|
|
6145
|
+
}
|
|
6146
|
+
async function resolveFreeSkillWorkspace(context, fallbackWorkspace) {
|
|
6147
|
+
const workspaceInput = firstWorkspaceValue(context) ?? nonEmptyString(fallbackWorkspace);
|
|
6148
|
+
if (!workspaceInput) {
|
|
6149
|
+
throw new FreeSkillWorkspaceError(
|
|
6150
|
+
"WORKSPACE_MISSING",
|
|
6151
|
+
"\u672A\u63D0\u4F9B\u5F53\u524D Agent workspace"
|
|
6152
|
+
);
|
|
6153
|
+
}
|
|
6154
|
+
const workspacePath = await resolveWorkspacePath(workspaceInput);
|
|
6155
|
+
const directoryPath = await resolvePlatformDirectory(workspacePath);
|
|
6156
|
+
return {
|
|
6157
|
+
agentId: firstAgentIdValue(context),
|
|
6158
|
+
workspacePath,
|
|
6159
|
+
directoryPath,
|
|
6160
|
+
workspaceRelativePath: FREE_SKILL_DIRECTORY_NAME2
|
|
6161
|
+
};
|
|
6162
|
+
}
|
|
6163
|
+
|
|
6164
|
+
// src/free-skill-writer.ts
|
|
6165
|
+
var FREE_SKILL_DIRECTORY_NAME3 = ".xg-platform";
|
|
6166
|
+
var SKILL_FILE_NAME2 = "SKILL.md";
|
|
6167
|
+
var FreeSkillWriterError = class extends Error {
|
|
6168
|
+
code;
|
|
6169
|
+
constructor(code, message, options) {
|
|
6170
|
+
super(message, options);
|
|
6171
|
+
this.code = code;
|
|
6172
|
+
this.name = "FreeSkillWriterError";
|
|
6173
|
+
}
|
|
6174
|
+
};
|
|
6175
|
+
var defaultFileSystem = {
|
|
6176
|
+
lstat: fs11.lstat,
|
|
6177
|
+
realpath: fs11.realpath,
|
|
6178
|
+
stat: fs11.stat,
|
|
6179
|
+
mkdir: fs11.mkdir,
|
|
6180
|
+
writeFile: fs11.writeFile,
|
|
6181
|
+
rename: fs11.rename,
|
|
6182
|
+
rm: fs11.rm
|
|
6183
|
+
};
|
|
6184
|
+
function isRecord3(value) {
|
|
6185
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6186
|
+
}
|
|
6187
|
+
function isWithin3(parent, candidate) {
|
|
6188
|
+
const relative = path13.relative(parent, candidate);
|
|
6189
|
+
return relative === "" || !relative.startsWith(`..${path13.sep}`) && relative !== ".." && !path13.isAbsolute(relative);
|
|
6190
|
+
}
|
|
6191
|
+
function asErrnoCode(error) {
|
|
6192
|
+
return typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
|
|
6193
|
+
}
|
|
6194
|
+
function asMessage(error) {
|
|
6195
|
+
return error instanceof Error ? error.message : String(error);
|
|
6196
|
+
}
|
|
6197
|
+
function fail(code, message) {
|
|
6198
|
+
throw new FreeSkillWriterError(code, message);
|
|
6199
|
+
}
|
|
6200
|
+
function stripYamlComment(value) {
|
|
6201
|
+
let quote;
|
|
6202
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
6203
|
+
const character = value[index];
|
|
6204
|
+
if (quote === '"' && character === "\\") {
|
|
6205
|
+
index += 1;
|
|
6206
|
+
continue;
|
|
6207
|
+
}
|
|
6208
|
+
if ((character === "'" || character === '"') && (!quote || quote === character)) {
|
|
6209
|
+
if (quote === "'" && character === "'" && value[index + 1] === "'") {
|
|
6210
|
+
index += 1;
|
|
6211
|
+
continue;
|
|
6212
|
+
}
|
|
6213
|
+
quote = quote ? void 0 : character;
|
|
6214
|
+
continue;
|
|
6215
|
+
}
|
|
6216
|
+
if (!quote && character === "#" && (index === 0 || /\s/.test(value[index - 1]))) {
|
|
6217
|
+
return value.slice(0, index).trimEnd();
|
|
6218
|
+
}
|
|
6219
|
+
}
|
|
6220
|
+
return value.trim();
|
|
6221
|
+
}
|
|
6222
|
+
function parseQuotedScalar(rawValue) {
|
|
6223
|
+
if (rawValue.startsWith('"')) {
|
|
6224
|
+
if (!rawValue.endsWith('"')) return void 0;
|
|
6225
|
+
try {
|
|
6226
|
+
const parsed = JSON.parse(rawValue);
|
|
6227
|
+
return typeof parsed === "string" ? parsed : void 0;
|
|
6228
|
+
} catch {
|
|
6229
|
+
return void 0;
|
|
6230
|
+
}
|
|
6231
|
+
}
|
|
6232
|
+
if (rawValue.startsWith("'")) {
|
|
6233
|
+
if (!rawValue.endsWith("'")) return void 0;
|
|
6234
|
+
const inner = rawValue.slice(1, -1);
|
|
6235
|
+
let value = "";
|
|
6236
|
+
for (let index = 0; index < inner.length; index += 1) {
|
|
6237
|
+
if (inner[index] === "'" && inner[index + 1] === "'") {
|
|
6238
|
+
value += "'";
|
|
6239
|
+
index += 1;
|
|
6240
|
+
} else if (inner[index] === "'") {
|
|
6241
|
+
return void 0;
|
|
6242
|
+
} else {
|
|
6243
|
+
value += inner[index];
|
|
6244
|
+
}
|
|
6245
|
+
}
|
|
6246
|
+
return value;
|
|
6247
|
+
}
|
|
6248
|
+
return void 0;
|
|
6249
|
+
}
|
|
6250
|
+
function hasBalancedCollection(value) {
|
|
6251
|
+
const opening = value[0];
|
|
6252
|
+
const closing = opening === "[" ? "]" : "}";
|
|
6253
|
+
if (opening !== "[" && opening !== "{" || !value.endsWith(closing)) return false;
|
|
6254
|
+
let depth = 0;
|
|
6255
|
+
let quote;
|
|
6256
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
6257
|
+
const character = value[index];
|
|
6258
|
+
if (quote === '"' && character === "\\") {
|
|
6259
|
+
index += 1;
|
|
6260
|
+
continue;
|
|
6261
|
+
}
|
|
6262
|
+
if ((character === "'" || character === '"') && (!quote || quote === character)) {
|
|
6263
|
+
if (quote === "'" && character === "'" && value[index + 1] === "'") {
|
|
6264
|
+
index += 1;
|
|
6265
|
+
continue;
|
|
6266
|
+
}
|
|
6267
|
+
quote = quote ? void 0 : character;
|
|
6268
|
+
continue;
|
|
6269
|
+
}
|
|
6270
|
+
if (quote) continue;
|
|
6271
|
+
if (character === opening) depth += 1;
|
|
6272
|
+
if (character === closing) depth -= 1;
|
|
6273
|
+
if (depth < 0) return false;
|
|
6274
|
+
}
|
|
6275
|
+
return depth === 0 && !quote;
|
|
6276
|
+
}
|
|
6277
|
+
function parseInlineValue(rawValue) {
|
|
6278
|
+
const value = stripYamlComment(rawValue);
|
|
6279
|
+
if (value.startsWith('"') || value.startsWith("'")) {
|
|
6280
|
+
const parsed = parseQuotedScalar(value);
|
|
6281
|
+
if (parsed === void 0) fail("INVALID_FRONTMATTER", "SKILL.md frontmatter \u4E2D\u5B58\u5728\u672A\u95ED\u5408\u6216\u65E0\u6548\u5B57\u7B26\u4E32");
|
|
6282
|
+
return { kind: "scalar", value: parsed };
|
|
6283
|
+
}
|
|
6284
|
+
if (value.startsWith("[") || value.startsWith("{")) {
|
|
6285
|
+
if (!hasBalancedCollection(value)) {
|
|
6286
|
+
fail("INVALID_FRONTMATTER", "SKILL.md frontmatter \u4E2D\u5B58\u5728\u672A\u95ED\u5408\u96C6\u5408\u503C");
|
|
6287
|
+
}
|
|
6288
|
+
return { kind: "other" };
|
|
6289
|
+
}
|
|
6290
|
+
return { kind: "scalar", value };
|
|
6291
|
+
}
|
|
6292
|
+
function parseBlockValue(lines, startIndex, header) {
|
|
6293
|
+
const headerMatch = /^([|>])(?:[+-]|[1-9])?$/.exec(header);
|
|
6294
|
+
if (!headerMatch) fail("INVALID_FRONTMATTER", "SKILL.md frontmatter \u4E2D\u5B58\u5728\u65E0\u6548\u5757\u6807\u91CF");
|
|
6295
|
+
const blockLines = [];
|
|
6296
|
+
let index = startIndex;
|
|
6297
|
+
let contentIndent;
|
|
6298
|
+
while (index < lines.length) {
|
|
6299
|
+
const line = lines[index];
|
|
6300
|
+
if (line.trim() !== "" && !/^\s+/.test(line)) break;
|
|
6301
|
+
if (line.trim() === "") {
|
|
6302
|
+
blockLines.push("");
|
|
6303
|
+
index += 1;
|
|
6304
|
+
continue;
|
|
6305
|
+
}
|
|
6306
|
+
const indent = line.match(/^\s*/)?.[0].length ?? 0;
|
|
6307
|
+
contentIndent ??= indent;
|
|
6308
|
+
if (indent < contentIndent) break;
|
|
6309
|
+
blockLines.push(line.slice(contentIndent));
|
|
6310
|
+
index += 1;
|
|
6311
|
+
}
|
|
6312
|
+
if (headerMatch[1] === ">") {
|
|
6313
|
+
const folded = [];
|
|
6314
|
+
for (const line of blockLines) {
|
|
6315
|
+
if (line === "") {
|
|
6316
|
+
folded.push("\n");
|
|
6317
|
+
} else if (folded.length > 0 && folded[folded.length - 1] !== "\n") {
|
|
6318
|
+
folded.push(" ", line);
|
|
6319
|
+
} else {
|
|
6320
|
+
folded.push(line);
|
|
6321
|
+
}
|
|
6322
|
+
}
|
|
6323
|
+
return { value: folded.join(""), nextIndex: index };
|
|
6324
|
+
}
|
|
6325
|
+
return { value: blockLines.join("\n"), nextIndex: index };
|
|
6326
|
+
}
|
|
6327
|
+
function parseFrontmatter2(content) {
|
|
6328
|
+
const normalized = content.replace(/^\uFEFF/, "");
|
|
6329
|
+
const lines = normalized.split(/\r?\n/);
|
|
6330
|
+
if (lines[0]?.trim() !== "---") {
|
|
6331
|
+
fail("INVALID_FRONTMATTER", "SKILL.md \u5FC5\u987B\u4EE5 YAML frontmatter \u5F00\u59CB");
|
|
6332
|
+
}
|
|
6333
|
+
const fields = /* @__PURE__ */ new Map();
|
|
6334
|
+
let closingIndex = -1;
|
|
6335
|
+
let index = 1;
|
|
6336
|
+
while (index < lines.length) {
|
|
6337
|
+
const line = lines[index];
|
|
6338
|
+
const trimmed = line.trim();
|
|
6339
|
+
if (trimmed === "---" || trimmed === "...") {
|
|
6340
|
+
closingIndex = index;
|
|
6341
|
+
break;
|
|
6342
|
+
}
|
|
6343
|
+
if (trimmed === "" || trimmed.startsWith("#")) {
|
|
6344
|
+
index += 1;
|
|
6345
|
+
continue;
|
|
6346
|
+
}
|
|
6347
|
+
if (/^\s/.test(line) || line.includes(" ")) {
|
|
6348
|
+
fail("INVALID_FRONTMATTER", "SKILL.md frontmatter \u4E2D\u5B58\u5728\u65E0\u6548\u7F29\u8FDB");
|
|
6349
|
+
}
|
|
6350
|
+
const match2 = /^([A-Za-z][A-Za-z0-9_-]*)\s*:\s*(.*?)\s*$/.exec(line);
|
|
6351
|
+
if (!match2) fail("INVALID_FRONTMATTER", "SKILL.md frontmatter \u4E2D\u5B58\u5728\u65E0\u6548\u5B57\u6BB5");
|
|
6352
|
+
const [, key, rawValue] = match2;
|
|
6353
|
+
if (fields.has(key)) fail("INVALID_FRONTMATTER", `SKILL.md frontmatter \u5B57\u6BB5\u91CD\u590D: ${key}`);
|
|
6354
|
+
const value = stripYamlComment(rawValue);
|
|
6355
|
+
if (value === "|" || value === ">" || /^[|>][+-]$/.test(value)) {
|
|
6356
|
+
const block = parseBlockValue(lines, index + 1, value);
|
|
6357
|
+
fields.set(key, { kind: "scalar", value: block.value });
|
|
6358
|
+
index = block.nextIndex;
|
|
6359
|
+
continue;
|
|
6360
|
+
}
|
|
6361
|
+
fields.set(key, parseInlineValue(rawValue));
|
|
6362
|
+
index += 1;
|
|
6363
|
+
}
|
|
6364
|
+
if (closingIndex < 0) fail("INVALID_FRONTMATTER", "SKILL.md frontmatter \u7F3A\u5C11\u7ED3\u675F\u6807\u8BB0");
|
|
6365
|
+
const name = fields.get("name");
|
|
6366
|
+
if (!name || name.kind !== "scalar" || !name.value.trim()) {
|
|
6367
|
+
fail("MISSING_NAME", "SKILL.md frontmatter \u5FC5\u987B\u5305\u542B\u975E\u7A7A name");
|
|
6368
|
+
}
|
|
6369
|
+
const description = fields.get("description");
|
|
6370
|
+
if (!description || description.kind !== "scalar" || !description.value.trim()) {
|
|
6371
|
+
fail("MISSING_DESCRIPTION", "SKILL.md frontmatter \u5FC5\u987B\u5305\u542B\u975E\u7A7A description");
|
|
6372
|
+
}
|
|
6373
|
+
const body = lines.slice(closingIndex + 1).join("\n");
|
|
6374
|
+
if (!body.trim()) fail("EMPTY_BODY", "SKILL.md \u6B63\u6587\u4E0D\u80FD\u4E3A\u7A7A");
|
|
6375
|
+
return { name: name.value.trim(), description: description.value.trim(), body };
|
|
6376
|
+
}
|
|
6377
|
+
function validateFreeSkillContent(content) {
|
|
6378
|
+
if (typeof content !== "string") fail("INVALID_CONTENT", "SKILL.md \u5185\u5BB9\u5FC5\u987B\u662F\u5B57\u7B26\u4E32");
|
|
6379
|
+
return parseFrontmatter2(content);
|
|
6380
|
+
}
|
|
6381
|
+
function validateSkillName(value) {
|
|
6382
|
+
if (typeof value !== "string" || value.length === 0 || value !== value.trim()) {
|
|
6383
|
+
fail("INVALID_SKILL_NAME", "Skill \u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u7684\u5355\u7EA7\u76EE\u5F55\u540D");
|
|
6384
|
+
}
|
|
6385
|
+
if (value === "." || value === ".." || value.startsWith(".") || value.endsWith(".") || value.endsWith(" ") || path13.basename(value) !== value || path13.win32.basename(value) !== value || path13.isAbsolute(value) || /[\\/\0<>:"|?*\u0000-\u001f\u007f]/u.test(value)) {
|
|
6386
|
+
fail("INVALID_SKILL_NAME", `\u975E\u6CD5\u7684 Skill \u540D\u79F0: ${value}`);
|
|
6387
|
+
}
|
|
6388
|
+
return value;
|
|
6389
|
+
}
|
|
6390
|
+
function serializeMetadata(value) {
|
|
6391
|
+
if (value === void 0) return void 0;
|
|
6392
|
+
if (!isRecord3(value)) fail("INVALID_METADATA", ".meta.json metadata \u5FC5\u987B\u662F JSON \u5BF9\u8C61");
|
|
6393
|
+
try {
|
|
6394
|
+
const serialized = JSON.stringify(value, null, 2);
|
|
6395
|
+
if (serialized === void 0) fail("INVALID_METADATA", ".meta.json metadata \u65E0\u6CD5\u5E8F\u5217\u5316");
|
|
6396
|
+
return `${serialized}
|
|
6397
|
+
`;
|
|
6398
|
+
} catch (error) {
|
|
6399
|
+
fail("INVALID_METADATA", `.meta.json metadata \u65E0\u6CD5\u5E8F\u5217\u5316: ${asMessage(error)}`);
|
|
6400
|
+
}
|
|
6401
|
+
}
|
|
6402
|
+
function isResolvedWorkspace(value) {
|
|
6403
|
+
if (!isRecord3(value)) return false;
|
|
6404
|
+
return typeof value.workspacePath === "string" && typeof value.directoryPath === "string" && value.workspaceRelativePath === FREE_SKILL_DIRECTORY_NAME3;
|
|
6405
|
+
}
|
|
6406
|
+
async function ensurePlatformDirectory(workspace, io) {
|
|
6407
|
+
if (!path13.isAbsolute(workspace.workspacePath) || !path13.isAbsolute(workspace.directoryPath)) {
|
|
6408
|
+
fail("TARGET_ESCAPE", "Skill workspace \u8DEF\u5F84\u5FC5\u987B\u662F\u89E3\u6790\u5668\u8FD4\u56DE\u7684\u7EDD\u5BF9\u8DEF\u5F84");
|
|
6409
|
+
}
|
|
6410
|
+
let workspacePath;
|
|
6411
|
+
try {
|
|
6412
|
+
workspacePath = await io.realpath(path13.resolve(workspace.workspacePath));
|
|
6413
|
+
const workspaceStat = await io.stat(workspacePath);
|
|
6414
|
+
if (!workspaceStat.isDirectory()) fail("WORKSPACE_NOT_DIRECTORY", "Agent workspace \u4E0D\u662F\u76EE\u5F55");
|
|
6415
|
+
} catch (error) {
|
|
6416
|
+
if (error instanceof FreeSkillWriterError) throw error;
|
|
6417
|
+
fail("WORKSPACE_MISSING", `Agent workspace \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u8BBF\u95EE: ${asMessage(error)}`);
|
|
6418
|
+
}
|
|
6419
|
+
const directoryPath = path13.resolve(workspacePath, FREE_SKILL_DIRECTORY_NAME3);
|
|
6420
|
+
if (!isWithin3(workspacePath, directoryPath) || path13.resolve(workspace.directoryPath) !== directoryPath) {
|
|
6421
|
+
fail("TARGET_ESCAPE", "\u81EA\u7531 Skill \u76EE\u6807\u76EE\u5F55\u5FC5\u987B\u662F workspace/.xg-platform");
|
|
6422
|
+
}
|
|
6423
|
+
let entry;
|
|
6424
|
+
try {
|
|
6425
|
+
entry = await io.lstat(directoryPath);
|
|
6426
|
+
} catch (error) {
|
|
6427
|
+
if (asErrnoCode(error) !== "ENOENT") {
|
|
6428
|
+
fail("TARGET_UNAVAILABLE", `\u65E0\u6CD5\u68C0\u67E5\u81EA\u7531 Skill \u76EE\u6807\u76EE\u5F55: ${asMessage(error)}`);
|
|
6429
|
+
}
|
|
6430
|
+
try {
|
|
6431
|
+
await io.mkdir(directoryPath, { recursive: false });
|
|
6432
|
+
entry = await io.lstat(directoryPath);
|
|
6433
|
+
} catch (mkdirError) {
|
|
6434
|
+
if (asErrnoCode(mkdirError) !== "EEXIST") {
|
|
6435
|
+
fail("ATOMIC_WRITE_FAILED", `\u521B\u5EFA\u81EA\u7531 Skill \u76EE\u6807\u76EE\u5F55\u5931\u8D25: ${asMessage(mkdirError)}`);
|
|
6436
|
+
}
|
|
6437
|
+
try {
|
|
6438
|
+
entry = await io.lstat(directoryPath);
|
|
6439
|
+
} catch (statError) {
|
|
6440
|
+
fail("TARGET_UNAVAILABLE", `\u65E0\u6CD5\u68C0\u67E5\u81EA\u7531 Skill \u76EE\u6807\u76EE\u5F55: ${asMessage(statError)}`);
|
|
6441
|
+
}
|
|
6442
|
+
}
|
|
6443
|
+
}
|
|
6444
|
+
if (entry.isSymbolicLink()) fail("TARGET_SYMLINK", "\u62D2\u7EDD\u5199\u5165\u7B26\u53F7\u94FE\u63A5\u76EE\u6807\u76EE\u5F55");
|
|
6445
|
+
if (!entry.isDirectory()) fail("TARGET_NOT_DIRECTORY", "\u81EA\u7531 Skill \u76EE\u6807\u4E0D\u662F\u76EE\u5F55");
|
|
6446
|
+
let realDirectory;
|
|
6447
|
+
try {
|
|
6448
|
+
realDirectory = await io.realpath(directoryPath);
|
|
6449
|
+
} catch (error) {
|
|
6450
|
+
fail("TARGET_UNAVAILABLE", `\u65E0\u6CD5\u89E3\u6790\u81EA\u7531 Skill \u76EE\u6807\u76EE\u5F55: ${asMessage(error)}`);
|
|
6451
|
+
}
|
|
6452
|
+
if (realDirectory !== directoryPath || !isWithin3(workspacePath, realDirectory)) {
|
|
6453
|
+
fail("TARGET_ESCAPE", "\u81EA\u7531 Skill \u76EE\u6807\u76EE\u5F55\u8D8A\u51FA Agent workspace");
|
|
6454
|
+
}
|
|
6455
|
+
return { workspacePath, directoryPath };
|
|
6456
|
+
}
|
|
6457
|
+
async function resolveWriterWorkspace(input, suppliedWorkspace, io) {
|
|
6458
|
+
let workspace;
|
|
6459
|
+
const candidate = suppliedWorkspace ?? input.workspace;
|
|
6460
|
+
if (isResolvedWorkspace(candidate)) {
|
|
6461
|
+
workspace = candidate;
|
|
6462
|
+
} else {
|
|
6463
|
+
const context = input.context ?? candidate ?? input;
|
|
6464
|
+
try {
|
|
6465
|
+
workspace = await resolveFreeSkillWorkspace(context);
|
|
6466
|
+
} catch (error) {
|
|
6467
|
+
if (error instanceof FreeSkillWorkspaceError) throw error;
|
|
6468
|
+
fail("WORKSPACE_MISSING", `\u65E0\u6CD5\u89E3\u6790 Agent workspace: ${asMessage(error)}`);
|
|
6469
|
+
}
|
|
6470
|
+
}
|
|
6471
|
+
return ensurePlatformDirectory(workspace, io);
|
|
6472
|
+
}
|
|
6473
|
+
function makeTemporaryPath(directoryPath, skillName, suffix) {
|
|
6474
|
+
return path13.join(
|
|
6475
|
+
directoryPath,
|
|
6476
|
+
`.${skillName}.${suffix}-${process.pid}-${Date.now()}-${crypto.randomUUID()}`
|
|
6477
|
+
);
|
|
6478
|
+
}
|
|
6479
|
+
async function removePath(io, target) {
|
|
6480
|
+
await io.rm(target, { recursive: true, force: true }).catch(() => void 0);
|
|
6481
|
+
}
|
|
6482
|
+
async function targetAlreadyExists(targetPath, io) {
|
|
6483
|
+
try {
|
|
6484
|
+
const entry = await io.lstat(targetPath);
|
|
6485
|
+
return entry.isSymbolicLink() ? "symlink" : "exists";
|
|
6486
|
+
} catch (error) {
|
|
6487
|
+
if (asErrnoCode(error) === "ENOENT") return "missing";
|
|
6488
|
+
fail("TARGET_UNAVAILABLE", `\u65E0\u6CD5\u68C0\u67E5 Skill \u76EE\u6807\u76EE\u5F55: ${asMessage(error)}`);
|
|
6489
|
+
}
|
|
6490
|
+
}
|
|
6491
|
+
async function writeFreeSkill(input, workspace, dependencies) {
|
|
6492
|
+
const io = {
|
|
6493
|
+
...defaultFileSystem,
|
|
6494
|
+
...dependencies?.fileSystem
|
|
6495
|
+
};
|
|
6496
|
+
try {
|
|
6497
|
+
if (!isRecord3(input)) fail("INVALID_CONTENT", "Skill \u5199\u5165\u8BF7\u6C42\u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
6498
|
+
const skillName = validateSkillName(input.skillName ?? input.name);
|
|
6499
|
+
const content = input.content ?? input.skillContent;
|
|
6500
|
+
validateFreeSkillContent(content);
|
|
6501
|
+
const metadata = serializeMetadata(input.metadata);
|
|
6502
|
+
const { directoryPath: platformDirectoryPath } = await resolveWriterWorkspace(input, workspace, io);
|
|
6503
|
+
const targetDirectoryPath = path13.resolve(platformDirectoryPath, skillName);
|
|
6504
|
+
if (!isWithin3(platformDirectoryPath, targetDirectoryPath)) {
|
|
6505
|
+
fail("TARGET_ESCAPE", "Skill \u76EE\u6807\u76EE\u5F55\u8D8A\u51FA workspace/.xg-platform");
|
|
6506
|
+
}
|
|
6507
|
+
const existing = await targetAlreadyExists(targetDirectoryPath, io);
|
|
6508
|
+
if (existing === "symlink") fail("TARGET_SYMLINK", "\u62D2\u7EDD\u5199\u5165\u7B26\u53F7\u94FE\u63A5 Skill \u76EE\u5F55");
|
|
6509
|
+
if (existing === "exists") fail("SKILL_EXISTS", `Skill \u5DF2\u5B58\u5728: ${skillName}`);
|
|
6510
|
+
let createdTargetDirectory = false;
|
|
6511
|
+
let skillTempPath;
|
|
6512
|
+
let metadataTempPath;
|
|
6513
|
+
const skillFilePath = path13.join(targetDirectoryPath, SKILL_FILE_NAME2);
|
|
6514
|
+
const metadataFilePath = metadata ? path13.join(targetDirectoryPath, ".meta.json") : void 0;
|
|
6515
|
+
try {
|
|
6516
|
+
try {
|
|
6517
|
+
await io.mkdir(targetDirectoryPath, { recursive: false });
|
|
6518
|
+
createdTargetDirectory = true;
|
|
6519
|
+
} catch (error) {
|
|
6520
|
+
if (asErrnoCode(error) === "EEXIST") {
|
|
6521
|
+
const raced = await targetAlreadyExists(targetDirectoryPath, io);
|
|
6522
|
+
if (raced === "symlink") fail("TARGET_SYMLINK", "\u62D2\u7EDD\u5199\u5165\u7B26\u53F7\u94FE\u63A5 Skill \u76EE\u5F55");
|
|
6523
|
+
fail("SKILL_EXISTS", `Skill \u5DF2\u5B58\u5728: ${skillName}`);
|
|
6524
|
+
}
|
|
6525
|
+
fail("ATOMIC_WRITE_FAILED", `\u521B\u5EFA Skill \u76EE\u5F55\u5931\u8D25: ${asMessage(error)}`);
|
|
6526
|
+
}
|
|
6527
|
+
skillTempPath = makeTemporaryPath(targetDirectoryPath, skillName, "skill-md-tmp");
|
|
6528
|
+
await io.writeFile(skillTempPath, content, {
|
|
6529
|
+
encoding: "utf8",
|
|
6530
|
+
flag: "wx",
|
|
6531
|
+
mode: 384
|
|
6532
|
+
});
|
|
6533
|
+
await io.rename(skillTempPath, skillFilePath);
|
|
6534
|
+
skillTempPath = void 0;
|
|
6535
|
+
if (metadata && metadataFilePath) {
|
|
6536
|
+
metadataTempPath = makeTemporaryPath(targetDirectoryPath, skillName, "metadata-tmp");
|
|
6537
|
+
await io.writeFile(metadataTempPath, metadata, {
|
|
6538
|
+
encoding: "utf8",
|
|
6539
|
+
flag: "wx",
|
|
6540
|
+
mode: 384
|
|
6541
|
+
});
|
|
6542
|
+
await io.rename(metadataTempPath, metadataFilePath);
|
|
6543
|
+
metadataTempPath = void 0;
|
|
6544
|
+
}
|
|
6545
|
+
} catch (error) {
|
|
6546
|
+
if (error instanceof FreeSkillWriterError && error.code === "SKILL_EXISTS") throw error;
|
|
6547
|
+
await Promise.all([
|
|
6548
|
+
skillTempPath ? removePath(io, skillTempPath) : Promise.resolve(),
|
|
6549
|
+
metadataTempPath ? removePath(io, metadataTempPath) : Promise.resolve()
|
|
6550
|
+
]);
|
|
6551
|
+
if (createdTargetDirectory) await removePath(io, targetDirectoryPath);
|
|
6552
|
+
if (error instanceof FreeSkillWriterError) throw error;
|
|
6553
|
+
fail("ATOMIC_WRITE_FAILED", `\u81EA\u7531 Skill \u539F\u5B50\u5199\u5165\u5931\u8D25: ${asMessage(error)}`);
|
|
6554
|
+
}
|
|
6555
|
+
return {
|
|
6556
|
+
success: true,
|
|
6557
|
+
skillName,
|
|
6558
|
+
directoryPath: targetDirectoryPath,
|
|
6559
|
+
skillFilePath,
|
|
6560
|
+
...metadataFilePath ? { metadataFilePath } : {}
|
|
6561
|
+
};
|
|
6562
|
+
} catch (error) {
|
|
6563
|
+
if (error instanceof FreeSkillWriterError) {
|
|
6564
|
+
return { success: false, code: error.code, message: error.message };
|
|
6565
|
+
}
|
|
6566
|
+
if (error instanceof FreeSkillWorkspaceError) {
|
|
6567
|
+
return { success: false, code: error.code, message: error.message };
|
|
6568
|
+
}
|
|
6569
|
+
return { success: false, code: "ATOMIC_WRITE_FAILED", message: `\u81EA\u7531 Skill \u5199\u5165\u5931\u8D25: ${asMessage(error)}` };
|
|
6570
|
+
}
|
|
6571
|
+
}
|
|
6572
|
+
async function writeFreeSkillOrThrow(input, workspace, dependencies) {
|
|
6573
|
+
const result = await writeFreeSkill(input, workspace, dependencies);
|
|
6574
|
+
if (!result.success) throw new FreeSkillWriterError(result.code, result.message);
|
|
6575
|
+
return result;
|
|
6576
|
+
}
|
|
6577
|
+
|
|
6578
|
+
// src/free-skill-tool.ts
|
|
6579
|
+
var FREE_SKILL_TOOL_NAME = "skill_logger_create_free_skill";
|
|
6580
|
+
var parameters = {
|
|
6581
|
+
type: "object",
|
|
6582
|
+
additionalProperties: false,
|
|
6583
|
+
properties: {
|
|
6584
|
+
skillName: { type: "string", description: "\u81EA\u7531 Skill \u7684\u4E00\u7EA7\u76EE\u5F55\u540D" },
|
|
6585
|
+
content: { type: "string", description: "\u5B8C\u6574\u7684 SKILL.md \u5185\u5BB9" },
|
|
6586
|
+
metadata: { type: "object", description: "\u53EF\u9009\u7684 JSON \u5143\u6570\u636E" }
|
|
6587
|
+
},
|
|
6588
|
+
required: ["skillName", "content"]
|
|
6589
|
+
};
|
|
6590
|
+
function hasOwn(value, key) {
|
|
6591
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
6592
|
+
}
|
|
6593
|
+
function asInput(params) {
|
|
6594
|
+
if (hasOwn(params, "target") || hasOwn(params, "path")) {
|
|
6595
|
+
throw new FreeSkillWriterError(
|
|
6596
|
+
"INVALID_CONTENT",
|
|
6597
|
+
"\u81EA\u7531 Skill \u5DE5\u5177\u4E0D\u63A5\u53D7 target/path\uFF0C\u76EE\u6807\u8DEF\u5F84\u7531\u5F53\u524D Agent workspace \u51B3\u5B9A"
|
|
6598
|
+
);
|
|
6599
|
+
}
|
|
6600
|
+
return {
|
|
6601
|
+
skillName: params.skillName ?? params.name,
|
|
6602
|
+
content: params.content ?? params.skillContent,
|
|
6603
|
+
metadata: params.metadata
|
|
6604
|
+
};
|
|
6605
|
+
}
|
|
6606
|
+
function createFreeSkillToolFactory(context) {
|
|
6607
|
+
return {
|
|
6608
|
+
name: FREE_SKILL_TOOL_NAME,
|
|
6609
|
+
label: "Create free Skill",
|
|
6610
|
+
description: "Create a validated Skill in the current Agent workspace under .xg-platform. The target path is runtime controlled.",
|
|
6611
|
+
parameters,
|
|
6612
|
+
async execute(_toolCallId, params) {
|
|
6613
|
+
const workspace = await resolveFreeSkillWorkspace(context);
|
|
6614
|
+
const result = await writeFreeSkillOrThrow(asInput(params), workspace);
|
|
6615
|
+
const workspaceRelativePath = path14.posix.join(".xg-platform", result.skillName);
|
|
6616
|
+
const details = {
|
|
6617
|
+
success: true,
|
|
6618
|
+
skillName: result.skillName,
|
|
6619
|
+
workspaceRelativePath,
|
|
6620
|
+
directoryPath: result.directoryPath,
|
|
6621
|
+
skillFilePath: result.skillFilePath,
|
|
6622
|
+
...workspace.agentId ? { agentId: workspace.agentId } : {}
|
|
6623
|
+
};
|
|
6624
|
+
return {
|
|
6625
|
+
content: [{ type: "text", text: `\u81EA\u7531 Skill \u5DF2\u5199\u5165 ${workspaceRelativePath}` }],
|
|
6626
|
+
details
|
|
6627
|
+
};
|
|
6628
|
+
}
|
|
6629
|
+
};
|
|
6630
|
+
}
|
|
6631
|
+
|
|
5116
6632
|
// src/index.ts
|
|
5117
6633
|
var wsClient;
|
|
5118
6634
|
var RECONCILE_INTERVAL_MS = 3 * 60 * 1e3;
|
|
@@ -5129,11 +6645,14 @@ var definition = {
|
|
|
5129
6645
|
name: "Skill Logger",
|
|
5130
6646
|
description: "\u8FFD\u8E2A openclaw skill \u5185\u529F\u80FD\u70B9\uFF08\u811A\u672C/\u547D\u4EE4/\u5DE5\u5177/HTTP\uFF09\u4F7F\u7528\u4E0E\u62A5\u9519\uFF0C\u843D\u672C\u5730\u5E76\u6279\u91CF\u4E0A\u62A5",
|
|
5131
6647
|
register(api) {
|
|
6648
|
+
if (typeof api.registerTool === "function") {
|
|
6649
|
+
api.registerTool(createFreeSkillToolFactory, { name: FREE_SKILL_TOOL_NAME });
|
|
6650
|
+
}
|
|
5132
6651
|
let pkgVersion = "unknown";
|
|
5133
6652
|
try {
|
|
5134
|
-
const dir =
|
|
5135
|
-
const pkgPath =
|
|
5136
|
-
const pkg = JSON.parse(
|
|
6653
|
+
const dir = path15.dirname(fileURLToPath2(import.meta.url));
|
|
6654
|
+
const pkgPath = path15.join(dir, "..", "package.json");
|
|
6655
|
+
const pkg = JSON.parse(fs12.readFileSync(pkgPath, "utf-8"));
|
|
5137
6656
|
if (pkg.version) pkgVersion = pkg.version;
|
|
5138
6657
|
} catch {
|
|
5139
6658
|
}
|