@poe-platform/safe-bash 0.1.623 → 0.1.625

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.
@@ -26638,6 +26638,7 @@ var longOptions = {
26638
26638
  freshen: "f",
26639
26639
  filesync: "FS",
26640
26640
  "archive-comment": "z",
26641
+ "entry-comments": "c",
26641
26642
  delete: "d",
26642
26643
  include: "i",
26643
26644
  exclude: "x",
@@ -26668,7 +26669,6 @@ var longOptions = {
26668
26669
  var reservedOptions = [
26669
26670
  "adjust-sfx",
26670
26671
  "temp-path",
26671
- "entry-comments",
26672
26672
  "display-bytes",
26673
26673
  "display-counts",
26674
26674
  "display-dots",
@@ -26824,37 +26824,68 @@ function zipEnvironmentArguments(env, argv, limits) {
26824
26824
 
26825
26825
  // packages/safe-bash/src/commands/archive/zip/comments.ts
26826
26826
  init_platform();
26827
+ var ZipCommentInput = class {
26828
+ constructor(source2, limits, signal) {
26829
+ this.limits = limits;
26830
+ this.signal = signal;
26831
+ this.iterator = readBytes(source2, signal)[Symbol.asyncIterator]();
26832
+ }
26833
+ limits;
26834
+ signal;
26835
+ iterator;
26836
+ chunk = new Uint8Array();
26837
+ offset = 0;
26838
+ bytes = 0;
26839
+ pulls = 0;
26840
+ ended = false;
26841
+ async readLine() {
26842
+ const line = [];
26843
+ while (line.length < 65535) {
26844
+ this.signal.throwIfAborted();
26845
+ if (this.offset === this.chunk.length) {
26846
+ if (this.ended) break;
26847
+ if (++this.pulls > this.limits.maxPatternSteps) fail("ZIP comment input work limit exceeded");
26848
+ const next = await this.iterator.next();
26849
+ if (next.done) {
26850
+ this.ended = true;
26851
+ break;
26852
+ }
26853
+ if (next.value.length > this.limits.maxFilesFromBytes - this.bytes) fail("ZIP comment input byte limit exceeded");
26854
+ this.chunk = new Uint8Array(next.value);
26855
+ this.offset = 0;
26856
+ if (this.pulls % 64 === 0) await yieldTurn(this.signal);
26857
+ if (!this.chunk.length) continue;
26858
+ }
26859
+ if (++this.bytes > this.limits.maxFilesFromBytes) fail("ZIP comment input byte limit exceeded");
26860
+ const byte = this.chunk[this.offset++];
26861
+ line.push(byte);
26862
+ if (this.bytes % 4096 === 0) await yieldTurn(this.signal);
26863
+ if (byte === 10) break;
26864
+ }
26865
+ if (!line.length) return void 0;
26866
+ const zero2 = line.indexOf(0);
26867
+ return Uint8Array.from(line.slice(0, zero2 < 0 ? void 0 : zero2));
26868
+ }
26869
+ };
26827
26870
  async function readZipComment(source2, limits, signal) {
26871
+ const input3 = source2 instanceof ZipCommentInput ? source2 : new ZipCommentInput(source2, limits, signal);
26828
26872
  const parts = [];
26829
- const line = [];
26830
26873
  let length = 0;
26831
- let bytes3 = 0;
26832
- let pulls = 0;
26833
- const append = () => {
26834
- const zero2 = line.indexOf(0);
26835
- const text3 = line.slice(0, zero2 < 0 ? void 0 : zero2);
26836
- line.length = 0;
26837
- if (text3.length === 2 && text3[0] === 46 && text3[1] === 10) return false;
26838
- if (text3.at(-1) === 10) text3.pop();
26839
- const separator = length || !text3.length ? 2 : 0;
26840
- if (text3.length + separator > Math.min(limits.maxTextBytes, 65535) - length) fail("ZIP archive comment byte limit exceeded");
26841
- if (separator) parts.push(import_buffer.Buffer.from("\r\n"));
26842
- if (text3.length) parts.push(Uint8Array.from(text3));
26843
- length += separator + text3.length;
26844
- return true;
26845
- };
26846
- for await (const chunk of readBytes(source2, signal)) {
26847
- if (++pulls > limits.maxPatternSteps) fail("ZIP comment input work limit exceeded");
26848
- for (const byte of chunk) {
26849
- if (++bytes3 > limits.maxFilesFromBytes) fail("ZIP comment input byte limit exceeded");
26850
- line.push(byte);
26851
- if ((byte === 10 || line.length === 65535) && !append()) return import_buffer.Buffer.concat(parts, length);
26852
- if (bytes3 % 4096 === 0) await yieldTurn(signal);
26853
- }
26854
- if (pulls % 64 === 0) await yieldTurn(signal);
26874
+ try {
26875
+ for (; ; ) {
26876
+ const line = await input3.readLine();
26877
+ if (line === void 0 || line.length === 2 && line[0] === 46 && line[1] === 10) break;
26878
+ const text3 = line.at(-1) === 10 ? line.subarray(0, -1) : line;
26879
+ const separator = length || !text3.length ? 2 : 0;
26880
+ if (text3.length + separator > Math.min(limits.maxTextBytes, 65535) - length) fail("ZIP archive comment byte limit exceeded");
26881
+ if (separator) parts.push(import_buffer.Buffer.from("\r\n"));
26882
+ if (text3.length) parts.push(text3);
26883
+ length += separator + text3.length;
26884
+ }
26885
+ return import_buffer.Buffer.concat(parts, length);
26886
+ } finally {
26887
+ await input3.iterator.return?.();
26855
26888
  }
26856
- if (line.length) append();
26857
- return import_buffer.Buffer.concat(parts, length);
26858
26889
  }
26859
26890
 
26860
26891
  // packages/safe-bash/src/commands/archive/zip-format.ts
@@ -26892,7 +26923,7 @@ function zip64Directory(view, end, limits) {
26892
26923
  members = count2;
26893
26924
  centralSize = size;
26894
26925
  centralStart = start;
26895
- } else if (members === 65535 || centralSize === 4294967295 || centralStart === 4294967295) fail("ZIP64 missing end record and locator");
26926
+ } else if (centralSize === 4294967295 || centralStart === 4294967295) fail("ZIP64 missing end record and locator");
26896
26927
  else if (diskMembers !== members) fail("ZIP inconsistent member count");
26897
26928
  if (members > limits.maxMembers) fail("ZIP member limit exceeded");
26898
26929
  if (centralStart > limits.maxArchiveBytes || centralSize > limits.maxArchiveBytes || centralStart + centralSize !== centralEnd) fail("ZIP invalid central directory span");
@@ -27099,7 +27130,7 @@ async function readZipArchive(bytes3, limits, signal) {
27099
27130
  if (view.getUint32(offset2, true) === 101010256 && offset2 + 22 + view.getUint16(offset2 + 20, true) === bytes3.length) {
27100
27131
  const size = view.getUint32(offset2 + 12, true);
27101
27132
  const start = view.getUint32(offset2 + 16, true);
27102
- const zip64 = size === 4294967295 || start === 4294967295 || view.getUint16(offset2 + 10, true) === 65535 || offset2 >= 20 && view.getUint32(offset2 - 20, true) === 117853008;
27133
+ const zip64 = size === 4294967295 || start === 4294967295 || offset2 >= 20 && view.getUint32(offset2 - 20, true) === 117853008;
27103
27134
  if (!zip64 && start + size !== offset2) continue;
27104
27135
  if (end !== -1) fail("ZIP ambiguous end records");
27105
27136
  end = offset2;
@@ -27331,11 +27362,51 @@ function updateZipExtras(entry, previous, mode, limits) {
27331
27362
  }
27332
27363
  return { ...entry, localExtra: retained[0], centralExtra: retained[1] };
27333
27364
  }
27365
+ function setZipEntryComment(entry, comment2, limits) {
27366
+ number3(comment2.length, Math.min(limits.maxTextBytes, 65535), "entry comment");
27367
+ let flags3 = entry.flags ?? 2048;
27368
+ if (flags3 & 2048) {
27369
+ try {
27370
+ new TextDecoder("utf-8", { fatal: true }).decode(comment2);
27371
+ } catch {
27372
+ flags3 &= ~2048;
27373
+ }
27374
+ }
27375
+ const rawName = entry.rawName ?? pathBytes(entry.name, limits);
27376
+ const needUnicodePath = !(flags3 & 2048) && legacyName(rawName) !== entry.name;
27377
+ const metadata3 = [];
27378
+ for (const [original, central] of [[entry.localExtra ?? timestampExtra(entry.modified), false], [entry.centralExtra ?? timestampExtra(entry.modified), true]]) {
27379
+ extras(original, rawName, entry.comment ?? new Uint8Array(), central, limits);
27380
+ const fields4 = [];
27381
+ const view = new DataView(original.buffer, original.byteOffset, original.byteLength);
27382
+ for (let offset = 0; offset < original.length; ) {
27383
+ const identifier = view.getUint16(offset, true);
27384
+ const next = offset + 4 + view.getUint16(offset + 2, true);
27385
+ if (identifier !== 25461 && !(needUnicodePath && identifier === 28789)) fields4.push(original.subarray(offset, next));
27386
+ offset = next;
27387
+ }
27388
+ if (needUnicodePath) {
27389
+ const name2 = pathBytes(entry.name, limits);
27390
+ const field2 = new Uint8Array(9 + name2.length);
27391
+ const header3 = new DataView(field2.buffer);
27392
+ header3.setUint16(0, 28789, true);
27393
+ header3.setUint16(2, 5 + name2.length, true);
27394
+ field2[4] = 1;
27395
+ header3.setUint32(5, crc322(rawName), true);
27396
+ field2.set(name2, 9);
27397
+ fields4.push(field2);
27398
+ }
27399
+ const rebuilt = import_buffer.Buffer.concat(fields4);
27400
+ number3(rebuilt.length, Math.min(limits.maxPaxBytes, 65535), "extra field");
27401
+ metadata3.push(rebuilt);
27402
+ }
27403
+ return { ...entry, comment: new Uint8Array(comment2), flags: flags3, localExtra: metadata3[0], centralExtra: metadata3[1] };
27404
+ }
27334
27405
  async function* streamZipArchive(archive, limits, signal, descriptors = false, forceZip64 = false) {
27335
27406
  const chunkSize2 = admit(limits, signal);
27336
- number3(archive.entries.length, Math.min(limits.maxMembers, 65534), "member");
27407
+ number3(archive.entries.length, limits.maxMembers, "member");
27337
27408
  number3(archive.comment.length, Math.min(limits.maxTextBytes, 65535), "archive comment");
27338
- const wideArchive = forceZip64 || archive.entries.some((entry) => entry.zip64);
27409
+ const wideArchive = forceZip64 || archive.entries.length > 65535 || archive.entries.some((entry) => entry.zip64);
27339
27410
  let length = 22 + archive.comment.length + (wideArchive ? 76 : 0);
27340
27411
  let localLength = 0;
27341
27412
  let total = 0;
@@ -27459,8 +27530,8 @@ async function* streamZipArchive(archive, limits, signal, descriptors = false, f
27459
27530
  const view = new DataView(bytes3.buffer);
27460
27531
  const central = wideArchive ? writeZip64End(view, 0, encoded2.length, centralSize, localLength, localLength + centralSize) : 0;
27461
27532
  view.setUint32(central, 101010256, true);
27462
- view.setUint16(central + 8, encoded2.length, true);
27463
- view.setUint16(central + 10, encoded2.length, true);
27533
+ view.setUint16(central + 8, Math.min(encoded2.length, 65535), true);
27534
+ view.setUint16(central + 10, Math.min(encoded2.length, 65535), true);
27464
27535
  view.setUint32(central + 12, centralSize, true);
27465
27536
  view.setUint32(central + 16, wideArchive ? 4294967295 : localLength, true);
27466
27537
  view.setUint16(central + 20, archive.comment.length, true);
@@ -27867,6 +27938,7 @@ async function parse12(scope, limits) {
27867
27938
  let mustMatch = false;
27868
27939
  let filesync = false;
27869
27940
  let archiveComment = false;
27941
+ let entryComments = false;
27870
27942
  let fromDate;
27871
27943
  let beforeDate;
27872
27944
  let descriptors = false;
@@ -27921,6 +27993,7 @@ async function parse12(scope, limits) {
27921
27993
  offset++;
27922
27994
  } else if (flag === "q") quiet = true;
27923
27995
  else if (flag === "z") archiveComment = true;
27996
+ else if (flag === "c") entryComments = true;
27924
27997
  else if (flag === "j") junkPaths = true;
27925
27998
  else if (flag === "X") {
27926
27999
  metadata3 = argument2[offset + 1] === "-" ? "all" : "strip";
@@ -28039,7 +28112,7 @@ async function parse12(scope, limits) {
28039
28112
  }
28040
28113
  if (recursivePatterns && !names.length && !operands.length) throw new ZipFailure(16, "Invalid command arguments", "nothing to select from");
28041
28114
  if (filesync && action !== "add") throw new ZipFailure(16, "Invalid command arguments", "can't use -d, -f, -u, -U, or -g with filesync -FS\n");
28042
- return { args, action, archive, output: output2, recursive, recursivePatterns, noWild, stopAtDirectories, quiet, junkPaths, omitDirectories, storeLinks, test, mustMatch, filesync, archiveComment, fromDate, beforeDate, descriptors, zip64, metadata: metadata3, includes, excludes, level, method, suffixes, operands: [...names, ...operands], firstOperand };
28115
+ return { args, action, archive, output: output2, recursive, recursivePatterns, noWild, stopAtDirectories, quiet, junkPaths, omitDirectories, storeLinks, test, mustMatch, filesync, archiveComment, entryComments, fromDate, beforeDate, descriptors, zip64, metadata: metadata3, includes, excludes, level, method, suffixes, operands: [...names, ...operands], firstOperand };
28043
28116
  }
28044
28117
  function memberName(path, limits) {
28045
28118
  if (path.startsWith("//") && !path.startsWith("///")) fail("UNC source paths are unsupported");
@@ -28133,6 +28206,7 @@ async function prepare(scope, parsed, budget) {
28133
28206
  const selected = /* @__PURE__ */ new Map();
28134
28207
  const deleted = /* @__PURE__ */ new Set();
28135
28208
  const synchronized = /* @__PURE__ */ new Map();
28209
+ const commentNames = /* @__PURE__ */ new Set();
28136
28210
  const selection = new Selection([...parsed.includes, ...parsed.excludes], limits, context2.signal, { noWild: parsed.noWild, stopAtDirectories: parsed.stopAtDirectories });
28137
28211
  const recursiveSelection = parsed.recursivePatterns ? new Selection(parsed.operands, limits, context2.signal, { noWild: parsed.noWild, stopAtDirectories: parsed.stopAtDirectories, trailingComponents: true }) : void 0;
28138
28212
  let archiveOperandMatches;
@@ -28153,6 +28227,7 @@ async function prepare(scope, parsed, budget) {
28153
28227
  if (entry.data.length > limits.maxArchiveBytes - compressedBytes) fail("archive byte limit exceeded");
28154
28228
  compressedBytes += entry.data.length;
28155
28229
  selected.set(name2, { entry, source: source2 });
28230
+ if (parsed.entryComments) commentNames.add(name2);
28156
28231
  };
28157
28232
  const visit = async (source2, name2, depth) => {
28158
28233
  context2.signal.throwIfAborted();
@@ -28166,6 +28241,7 @@ async function prepare(scope, parsed, budget) {
28166
28241
  if (previous || !await filterName(name2, selection, parsed.includes.length)) return;
28167
28242
  const prior2 = old.get(name2);
28168
28243
  const modified = /* @__PURE__ */ new Date();
28244
+ if (parsed.entryComments && prior2) commentNames.add(name2);
28169
28245
  if (!zipDateMatches(modified, parsed.fromDate, parsed.beforeDate)) return;
28170
28246
  if (parsed.filesync) {
28171
28247
  if (synchronized.has(name2) && synchronized.get(name2) !== source2) throw new ZipFailure(16, "Invalid command arguments", "cannot repeat names in zip file");
@@ -28188,6 +28264,7 @@ async function prepare(scope, parsed, budget) {
28188
28264
  if (typeof error !== "object" || error === null || !("code" in error)) throw error;
28189
28265
  if (parsed.mustMatch && error.code === "EACCES") throw new ZipFailure(18, "File not found or no read permission", source2);
28190
28266
  if (error.code !== "ENOENT") throw error;
28267
+ if (parsed.entryComments && old.has(name2) && await filterName(name2, selection, parsed.includes.length)) commentNames.add(name2);
28191
28268
  if (parsed.mustMatch && !old.has(name2)) {
28192
28269
  if (!archiveOperandMatches) {
28193
28270
  const fallback = new Selection(parsed.operands.map((operand) => {
@@ -28217,10 +28294,13 @@ async function prepare(scope, parsed, budget) {
28217
28294
  if ((existing2 || publication?.existing) && !hasIdentity(stat)) fail("cannot exclude archive aliases when source backing identity is unknown");
28218
28295
  const directory2 = stat.type === "directory";
28219
28296
  if (directory2 && name2 && !name2.endsWith("/")) name2 += "/";
28220
- const included = zipDateMatches(new Date(stat.mtimeMs), parsed.fromDate, parsed.beforeDate) && await filterName(name2, selection, parsed.includes.length) && (!recursiveSelection || await recursiveSelection.matches(name2, true));
28297
+ const dateIncluded = zipDateMatches(new Date(stat.mtimeMs), parsed.fromDate, parsed.beforeDate);
28298
+ const nameIncluded = (dateIncluded || parsed.entryComments) && await filterName(name2, selection, parsed.includes.length) && (!recursiveSelection || await recursiveSelection.matches(name2, true));
28299
+ const included = dateIncluded && nameIncluded;
28221
28300
  const sourceName = name2;
28222
28301
  if (parsed.junkPaths) name2 = directory2 ? "" : name2.slice(name2.lastIndexOf("/") + 1);
28223
28302
  const prior = old.get(name2);
28303
+ if (parsed.entryComments && prior && nameIncluded) commentNames.add(name2);
28224
28304
  if (parsed.filesync && name2 && included && !(directory2 && parsed.omitDirectories)) {
28225
28305
  if (synchronized.has(name2) && synchronized.get(name2) !== source2) throw new ZipFailure(16, "Invalid command arguments", "cannot repeat names in zip file");
28226
28306
  synchronized.set(name2, source2);
@@ -28278,7 +28358,8 @@ async function prepare(scope, parsed, budget) {
28278
28358
  }
28279
28359
  };
28280
28360
  const editComment = parsed.archiveComment && parsed.action !== "delete" && parsed.action !== "copy";
28281
- if (parsed.archiveComment && parsed.action === "copy" && !parsed.quiet) await budget.output(" zip warning: can't set method, move, recurse, or comments with copy mode.\n");
28361
+ const editEntries = parsed.entryComments && parsed.action !== "delete" && parsed.action !== "copy";
28362
+ if ((parsed.archiveComment || parsed.entryComments) && parsed.action === "copy" && !parsed.quiet) await budget.output(" zip warning: can't set method, move, recurse, or comments with copy mode.\n");
28282
28363
  if (parsed.action === "copy") {
28283
28364
  const operands = new Selection(parsed.operands, limits, context2.signal, { noWild: parsed.noWild, stopAtDirectories: parsed.stopAtDirectories });
28284
28365
  for (const entry of archive.entries) {
@@ -28288,7 +28369,7 @@ async function prepare(scope, parsed, budget) {
28288
28369
  }
28289
28370
  }
28290
28371
  } else if (parsed.action === "delete") {
28291
- if (!parsed.quiet && (parsed.recursive || parsed.archiveComment)) await budget.output(" zip warning: invalid option(s) used with -d; ignored.\n");
28372
+ if (!parsed.quiet && (parsed.recursive || parsed.archiveComment || parsed.entryComments)) await budget.output(" zip warning: invalid option(s) used with -d; ignored.\n");
28292
28373
  if (!parsed.quiet && !archive.entries.length) await budget.output(` zip warning: ${parsed.archive} not found or empty
28293
28374
  `);
28294
28375
  const operands = new Selection(parsed.recursivePatterns ? [] : parsed.operands, limits, context2.signal, { noWild: parsed.noWild, stopAtDirectories: parsed.stopAtDirectories });
@@ -28321,8 +28402,8 @@ async function prepare(scope, parsed, budget) {
28321
28402
  return { kind: "current" };
28322
28403
  }
28323
28404
  }
28324
- if (!selected.size && !(editComment && archive.entries.length) && (parsed.action === "freshen" || parsed.action === "update" && (existing2 || !parsed.includes.length))) return void 0;
28325
- if (!selected.size && !deleted.size && !(editComment && archive.entries.length) && (parsed.action === "delete" || parsed.action === "copy" || parsed.recursivePatterns || parsed.fromDate !== void 0 || parsed.beforeDate !== void 0 || !parsed.includes.length)) {
28405
+ if (!selected.size && !((editComment || editEntries) && archive.entries.length) && (parsed.action === "freshen" || parsed.action === "update" && (existing2 || !parsed.includes.length))) return void 0;
28406
+ if (!selected.size && !deleted.size && !((editComment || editEntries) && archive.entries.length) && (parsed.action === "delete" || parsed.action === "copy" || parsed.recursivePatterns || parsed.fromDate !== void 0 || parsed.beforeDate !== void 0 || !parsed.includes.length)) {
28326
28407
  const detail = parsed.action !== "delete" && parsed.recursive && parsed.firstOperand >= 0 ? `try: zip ${parsed.args.slice(0, parsed.firstOperand).join(" ")} . -i ${parsed.args.slice(parsed.firstOperand).join(" ")}` : parsed.archive;
28327
28408
  throw new ZipFailure(12, "Nothing to do!", detail);
28328
28409
  }
@@ -28373,11 +28454,22 @@ async function prepare(scope, parsed, budget) {
28373
28454
  }
28374
28455
  if (!entries2.length) queue(" zip warning: zip file empty\n");
28375
28456
  let comment2 = archive.comment;
28376
- if (editComment) {
28457
+ if (editComment || editEntries && commentNames.size) {
28377
28458
  for (const message3 of progress) await budget.output(message3);
28378
28459
  progress.length = 0;
28379
28460
  progressBytes = 0;
28380
- if (!parsed.quiet) {
28461
+ const commentInput = new ZipCommentInput(scope.stdin, limits, context2.signal);
28462
+ if (editEntries) {
28463
+ for (let index = 0; index < entries2.length; index++) {
28464
+ const entry = entries2[index];
28465
+ if (!commentNames.has(entry.name)) continue;
28466
+ if (!parsed.quiet) await budget.output(`Enter comment for ${entry.name}:
28467
+ `);
28468
+ const line = await commentInput.readLine();
28469
+ if (line !== void 0) entries2[index] = setZipEntryComment(entry, line.at(-1) === 10 ? line.subarray(0, -1) : line, limits);
28470
+ }
28471
+ }
28472
+ if (editComment && !parsed.quiet) {
28381
28473
  if (comment2.length) {
28382
28474
  await budget.output("current zip file comment is:\n");
28383
28475
  await budget.output(comment2);
@@ -28385,7 +28477,7 @@ async function prepare(scope, parsed, budget) {
28385
28477
  }
28386
28478
  await budget.output("enter new zip file comment (end with .):\n");
28387
28479
  }
28388
- comment2 = await readZipComment(scope.stdin, limits, context2.signal);
28480
+ if (editComment) comment2 = await readZipComment(commentInput, limits, context2.signal);
28389
28481
  }
28390
28482
  if (!publication) return { kind: "stream", archive: { entries: entries2, comment: comment2 }, progress };
28391
28483
  const bytes3 = await writeZipArchive({ entries: entries2, comment: comment2 }, limits, context2.signal, false, parsed.zip64 === true);