@zip.js/zip.js 2.8.52 → 2.8.53

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/eslint.config.mjs CHANGED
@@ -53,7 +53,7 @@ export default [
53
53
  }
54
54
  },
55
55
  {
56
- files: ["benchmarks/**/*.js", "benchmarks/**/*.mjs", "tests/browser-runner.js", "tests/fidelity/**/*.js"],
56
+ files: ["benchmarks/**/*.js", "benchmarks/**/*.mjs", "tests/browser-runner.js", "tests/fidelity/**/*.js", "tests/api-symmetry/**/*.js"],
57
57
  languageOptions: {
58
58
  ecmaVersion: "latest",
59
59
  globals: {
package/index-native.cjs CHANGED
@@ -96,6 +96,9 @@ const VERSION_DEFLATE = 0x14;
96
96
  const VERSION_ZIP64 = 0x2D;
97
97
  const VERSION_AES = 0x33;
98
98
 
99
+ const VERSION_MADE_BY_MSDOS = 0x0014;
100
+ const VERSION_MADE_BY_UNIX = 0x0300;
101
+
99
102
  const DIRECTORY_SIGNATURE = "/";
100
103
 
101
104
  const HEADER_SIZE = 30;
@@ -2752,6 +2755,7 @@ function createWebWorkerInterface(workerData, config) {
2752
2755
  worker,
2753
2756
  workerAlive: false,
2754
2757
  terminated: false,
2758
+ startupError: null,
2755
2759
  interface: {
2756
2760
  run: async () => {
2757
2761
  try {
@@ -2779,6 +2783,13 @@ function createWebWorkerInterface(workerData, config) {
2779
2783
  }
2780
2784
 
2781
2785
  async function runWebWorker(workerData, config) {
2786
+ if (!workerData.worker) {
2787
+ const { startupError } = workerData;
2788
+ workerData.startupError = null;
2789
+ const error = startupError || new Error(ERR_WORKER_STARTUP_TIMEOUT);
2790
+ error.workerStartupFailed = true;
2791
+ throw error;
2792
+ }
2782
2793
  let resolveResult, rejectResult;
2783
2794
  const result = new Promise((resolve, reject) => {
2784
2795
  resolveResult = resolve;
@@ -2992,11 +3003,12 @@ function onWorkerError(event, workerData) {
2992
3003
  if (!workerAlive) {
2993
3004
  workerData.worker = null;
2994
3005
  }
3006
+ let error = event.error || new Error(event.message || ERROR_EVENT_TYPE);
3007
+ if (!workerAlive) {
3008
+ error = Object.assign(new Error(error.message || ERROR_EVENT_TYPE), { workerStartupFailed: true });
3009
+ workerData.startupError = error;
3010
+ }
2995
3011
  if (rejectResult) {
2996
- let error = event.error || new Error(event.message || ERROR_EVENT_TYPE);
2997
- if (!workerAlive) {
2998
- error = Object.assign(new Error(error.message || ERROR_EVENT_TYPE), { workerStartupFailed: true });
2999
- }
3000
3012
  rejectResult(error);
3001
3013
  if (writer) {
3002
3014
  writer.releaseLock();
@@ -4045,9 +4057,8 @@ class SplitDataReader extends Reader {
4045
4057
 
4046
4058
  async init() {
4047
4059
  const reader = this;
4048
- const { readers } = reader;
4049
4060
  reader.lastDiskNumber = 0;
4050
- await Promise.all(readers.map(diskReader => initStream(diskReader)));
4061
+ const readers = reader.readers = await Promise.all(reader.readers.map(initDiskReader));
4051
4062
  reader.diskOffsets = readers.map(diskReader => {
4052
4063
  const diskOffset = reader.size;
4053
4064
  reader.size += diskReader.size;
@@ -4242,6 +4253,16 @@ async function initStream(stream, initSize) {
4242
4253
  }
4243
4254
  }
4244
4255
 
4256
+ async function initDiskReader(diskReader) {
4257
+ diskReader = new GenericReader(diskReader);
4258
+ await initStream(diskReader);
4259
+ if (diskReader.size === UNDEFINED_VALUE || !diskReader.readUint8Array) {
4260
+ diskReader = new BlobReader(await streamToBlob(diskReader.readable));
4261
+ await initStream(diskReader);
4262
+ }
4263
+ return diskReader;
4264
+ }
4265
+
4245
4266
  function readUint8Array(reader, offset, size) {
4246
4267
  return reader.readUint8Array(offset, size);
4247
4268
  }
@@ -4400,6 +4421,10 @@ const PROPERTY_NAME_SETUID = "setuid";
4400
4421
  const PROPERTY_NAME_SETGID = "setgid";
4401
4422
  const PROPERTY_NAME_STICKY = "sticky";
4402
4423
  const PROPERTY_NAME_BITFLAG = "bitFlag";
4424
+ const PROPERTY_NAME_RAW_BITFLAG = "rawBitFlag";
4425
+ const PROPERTY_NAME_FILENAME_LENGTH = "filenameLength";
4426
+ const PROPERTY_NAME_EXTRA_FIELD_LENGTH = "extraFieldLength";
4427
+ const PROPERTY_NAME_UNIX_EXTERNAL_UPPER = "unixExternalUpper";
4403
4428
  const PROPERTY_NAME_FILENAME_UTF8 = "filenameUTF8";
4404
4429
  const PROPERTY_NAME_COMMENT_UTF8 = "commentUTF8";
4405
4430
  const PROPERTY_NAME_RAW_EXTRA_FIELD = "rawExtraField";
@@ -4452,10 +4477,14 @@ const PROPERTY_NAMES = [
4452
4477
  PROPERTY_NAME_UID,
4453
4478
  PROPERTY_NAME_GID,
4454
4479
  PROPERTY_NAME_UNIX_MODE,
4480
+ PROPERTY_NAME_UNIX_EXTERNAL_UPPER,
4455
4481
  PROPERTY_NAME_SETUID,
4456
4482
  PROPERTY_NAME_SETGID,
4457
4483
  PROPERTY_NAME_STICKY,
4458
4484
  PROPERTY_NAME_BITFLAG,
4485
+ PROPERTY_NAME_RAW_BITFLAG,
4486
+ PROPERTY_NAME_FILENAME_LENGTH,
4487
+ PROPERTY_NAME_EXTRA_FIELD_LENGTH,
4459
4488
  PROPERTY_NAME_FILENAME_UTF8,
4460
4489
  PROPERTY_NAME_COMMENT_UTF8,
4461
4490
  PROPERTY_NAME_RAW_EXTRA_FIELD,
@@ -4517,6 +4546,7 @@ const OPTION_CHECK_PASSWORD_ONLY = "checkPasswordOnly";
4517
4546
  const OPTION_CHECK_OVERLAPPING_ENTRY_ONLY = "checkOverlappingEntryOnly";
4518
4547
  const OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
4519
4548
  const OPTION_CHECK_AMBIGUITY = "checkAmbiguity";
4549
+ const OPTION_CHECK_LOCAL_DIRECTORY = "checkLocalDirectory";
4520
4550
  const OPTION_CHECK_SIGNATURE = "checkSignature";
4521
4551
  const OPTION_CHECK_CRC32 = "checkCrc32";
4522
4552
  const OPTION_CHECK_AUTHENTICATION_CODE = "checkAuthenticationCode";
@@ -4648,7 +4678,7 @@ class ZipReader {
4648
4678
  if (reader.size < END_OF_CENTRAL_DIR_LENGTH) {
4649
4679
  throw new Error(ERR_BAD_FORMAT);
4650
4680
  }
4651
- const strictness = getStrictness(getOptionValue$1(zipReader, options, OPTION_STRICTNESS), getOptionValue$1(zipReader, options, OPTION_CHECK_AMBIGUITY));
4681
+ const strictness = getStrictness(options, zipReader.options);
4652
4682
  const checkAmbiguity = strictness == STRICTNESS_STRICT;
4653
4683
  const rejectAmbiguousEndOfDirectory = strictness != STRICTNESS_TOLERANT;
4654
4684
  const maxAppendedDataSize = getMaxAppendedDataSize(getOptionValue$1(zipReader, options, OPTION_MAX_APPENDED_DATA_SIZE), strictness);
@@ -4870,6 +4900,7 @@ class ZipReader {
4870
4900
  index: indexFile,
4871
4901
  versionMadeBy,
4872
4902
  msDosCompatible,
4903
+ zip64: false,
4873
4904
  compressedSize: 0,
4874
4905
  uncompressedSize: 0,
4875
4906
  commentLength,
@@ -5080,9 +5111,12 @@ let ZipEntry$1 = class ZipEntry {
5080
5111
  extraFieldLength,
5081
5112
  filenameLength
5082
5113
  } = localDirectory;
5083
- const checkAmbiguity = getStrictness(getOptionValue$1(zipEntry, options, OPTION_STRICTNESS), getOptionValue$1(zipEntry, options, OPTION_CHECK_AMBIGUITY)) == STRICTNESS_STRICT;
5114
+ const checkLocalDirectoryOption = getOptionValue$1(zipEntry, options, OPTION_CHECK_LOCAL_DIRECTORY);
5115
+ const entryStrictness = getStrictness(options, zipEntry.options);
5116
+ const checkLocalDirectory = getCheckLocalDirectory(checkLocalDirectoryOption, entryStrictness);
5117
+ const checkLocalFilename = getCheckLocalFilename(checkLocalDirectoryOption, entryStrictness);
5084
5118
  let rawLocalFilename = EMPTY_UINT8_ARRAY;
5085
- if (checkAmbiguity && (filenameLength || extraFieldLength)) {
5119
+ if (checkLocalFilename && (filenameLength || extraFieldLength)) {
5086
5120
  const trailingDataArray = await readUint8Array(reader, localHeaderOffset + HEADER_SIZE, filenameLength + extraFieldLength);
5087
5121
  rawLocalFilename = trailingDataArray.subarray(0, filenameLength);
5088
5122
  localDirectory.rawExtraField = trailingDataArray.subarray(filenameLength);
@@ -5091,17 +5125,26 @@ let ZipEntry$1 = class ZipEntry {
5091
5125
  await readUint8Array(reader, localHeaderOffset + HEADER_SIZE + filenameLength, extraFieldLength) :
5092
5126
  EMPTY_UINT8_ARRAY;
5093
5127
  }
5128
+ if (checkLocalFilename) {
5129
+ localDirectory.rawFilename = rawLocalFilename;
5130
+ }
5094
5131
  readCommonFooter(zipEntry, localDirectory, dataView, 4, true);
5095
- if (checkAmbiguity) {
5096
- checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename);
5132
+ if (checkLocalDirectory) {
5133
+ validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename);
5097
5134
  }
5098
- const { lastAccessDate, creationDate } = localDirectory;
5135
+ const { lastAccessDate, creationDate, uid, gid } = localDirectory;
5099
5136
  if (lastAccessDate) {
5100
5137
  fileEntry.lastAccessDate = lastAccessDate;
5101
5138
  }
5102
5139
  if (creationDate) {
5103
5140
  fileEntry.creationDate = creationDate;
5104
5141
  }
5142
+ if (uid !== UNDEFINED_VALUE && fileEntry.uid === UNDEFINED_VALUE) {
5143
+ fileEntry.uid = uid;
5144
+ }
5145
+ if (gid !== UNDEFINED_VALUE && fileEntry.gid === UNDEFINED_VALUE) {
5146
+ fileEntry.gid = gid;
5147
+ }
5105
5148
  const encrypted = zipEntry.encrypted && localDirectory.encrypted && !passThrough;
5106
5149
  const zipCrypto = encrypted && !extraFieldAES;
5107
5150
  if (!passThrough) {
@@ -5337,10 +5380,12 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
5337
5380
  directory.extraFieldNTFS = extraFieldNTFS;
5338
5381
  }
5339
5382
  const extraFieldUnix = extraField.get(EXTRAFIELD_TYPE_UNIX);
5383
+ let unixIdsRead;
5340
5384
  if (extraFieldUnix) {
5341
- readExtraFieldUnix(extraFieldUnix, directory, false);
5385
+ unixIdsRead = readExtraFieldUnix(extraFieldUnix, directory, false);
5342
5386
  directory.extraFieldUnix = extraFieldUnix;
5343
- } else {
5387
+ }
5388
+ if (!unixIdsRead) {
5344
5389
  const extraFieldInfoZip = extraField.get(EXTRAFIELD_TYPE_INFOZIP);
5345
5390
  if (extraFieldInfoZip) {
5346
5391
  readExtraFieldUnix(extraFieldInfoZip, directory, true);
@@ -5443,7 +5488,7 @@ function readExtraFieldNTFS(extraFieldNTFS, directory) {
5443
5488
  const creationDate = getDateNTFS(rawCreationDate);
5444
5489
  const extraFieldData = { lastModDate, lastAccessDate, creationDate };
5445
5490
  Object.assign(extraFieldNTFS, extraFieldData);
5446
- Object.assign(directory, extraFieldData);
5491
+ Object.assign(directory, extraFieldData, { rawLastAccessDate, rawCreationDate });
5447
5492
  }
5448
5493
  }
5449
5494
 
@@ -5487,6 +5532,7 @@ function readExtraFieldUnix(extraField, directory, isInfoZip) {
5487
5532
  if (gid !== UNDEFINED_VALUE) {
5488
5533
  directory.gid = gid;
5489
5534
  }
5535
+ return uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE;
5490
5536
  } catch {
5491
5537
  // ignored
5492
5538
  }
@@ -5559,26 +5605,25 @@ async function detectOverlappingEntry({
5559
5605
  }
5560
5606
  if (dataDescriptorLength) {
5561
5607
  const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH);
5562
- const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
5563
- getUint32(getDataView(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
5564
- if (dataDescriptorSignature) {
5565
- const readCrc32 = getUint32(getDataView(dataDescriptorArray), 4);
5566
- let readCompressedSize;
5567
- let readUncompressedSize;
5568
- if (extraFieldZip64) {
5569
- readCompressedSize = getBigUint64(getDataView(dataDescriptorArray), 8);
5570
- readUncompressedSize = getBigUint64(getDataView(dataDescriptorArray), 16);
5571
- } else {
5572
- readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
5573
- readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
5574
- }
5575
- const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || readCrc32 == crc32;
5608
+ const dataDescriptorView = getDataView(dataDescriptorArray);
5609
+ let signature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
5610
+ getUint32(dataDescriptorView, 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
5611
+ if (signature) {
5612
+ const signedDataDescriptor = readDataDescriptor(dataDescriptorView, DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH, extraFieldZip64);
5613
+ const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || signedDataDescriptor.crc32 == crc32;
5576
5614
  if (matchCrc32 &&
5577
- readCompressedSize == compressedSize &&
5578
- readUncompressedSize == uncompressedSize) {
5615
+ signedDataDescriptor.compressedSize == compressedSize &&
5616
+ signedDataDescriptor.uncompressedSize == uncompressedSize) {
5579
5617
  dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
5618
+ } else {
5619
+ signature = false;
5580
5620
  }
5581
5621
  }
5622
+ if (dataDescriptorArray.length >= dataDescriptorLength) {
5623
+ const localDataDescriptor = readDataDescriptor(dataDescriptorView, signature ? DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH : 0, extraFieldZip64);
5624
+ localDataDescriptor.signature = signature;
5625
+ fileEntry.localDirectory.dataDescriptor = localDataDescriptor;
5626
+ }
5582
5627
  }
5583
5628
  const range = {
5584
5629
  start: offset,
@@ -5595,6 +5640,20 @@ async function detectOverlappingEntry({
5595
5640
  readRanges.set(index, range);
5596
5641
  }
5597
5642
 
5643
+ function readDataDescriptor(dataDescriptorView, offset, extraFieldZip64) {
5644
+ const crc32 = getUint32(dataDescriptorView, offset);
5645
+ let compressedSize;
5646
+ let uncompressedSize;
5647
+ if (extraFieldZip64) {
5648
+ compressedSize = getBigUint64(dataDescriptorView, offset + 4);
5649
+ uncompressedSize = getBigUint64(dataDescriptorView, offset + 12);
5650
+ } else {
5651
+ compressedSize = getUint32(dataDescriptorView, offset + 4);
5652
+ uncompressedSize = getUint32(dataDescriptorView, offset + 8);
5653
+ }
5654
+ return { crc32, compressedSize, uncompressedSize };
5655
+ }
5656
+
5598
5657
  function getDiskOffset$1(reader, diskNumber) {
5599
5658
  return reader.getDiskOffset ? reader.getDiskOffset(diskNumber) : 0;
5600
5659
  }
@@ -5603,14 +5662,40 @@ function isStrictnessValue(value) {
5603
5662
  return value === STRICTNESS_STRICT || value === STRICTNESS_BALANCED || value === STRICTNESS_TOLERANT;
5604
5663
  }
5605
5664
 
5606
- function getStrictness(strictness, checkAmbiguity) {
5607
- if (strictness === UNDEFINED_VALUE) {
5608
- return checkAmbiguity ? STRICTNESS_STRICT : STRICTNESS_BALANCED;
5665
+ function getStrictness(options, inheritedOptions) {
5666
+ return resolveStrictness(options, resolveStrictness(inheritedOptions, STRICTNESS_BALANCED));
5667
+ }
5668
+
5669
+ function resolveStrictness(options, inheritedStrictness) {
5670
+ const strictness = options[OPTION_STRICTNESS];
5671
+ if (strictness !== UNDEFINED_VALUE) {
5672
+ if (!isStrictnessValue(strictness)) {
5673
+ throw new Error(ERR_INVALID_STRICTNESS);
5674
+ }
5675
+ return strictness;
5676
+ }
5677
+ const checkAmbiguity = options[OPTION_CHECK_AMBIGUITY];
5678
+ if (checkAmbiguity === UNDEFINED_VALUE) {
5679
+ return inheritedStrictness;
5680
+ }
5681
+ if (checkAmbiguity) {
5682
+ return STRICTNESS_STRICT;
5683
+ }
5684
+ return inheritedStrictness == STRICTNESS_TOLERANT ? STRICTNESS_TOLERANT : STRICTNESS_BALANCED;
5685
+ }
5686
+
5687
+ function getCheckLocalDirectory(checkLocalDirectory, strictness) {
5688
+ if (checkLocalDirectory === UNDEFINED_VALUE) {
5689
+ return strictness != STRICTNESS_TOLERANT;
5609
5690
  }
5610
- if (!isStrictnessValue(strictness)) {
5611
- throw new Error(ERR_INVALID_STRICTNESS);
5691
+ return Boolean(checkLocalDirectory);
5692
+ }
5693
+
5694
+ function getCheckLocalFilename(checkLocalFilename, strictness) {
5695
+ if (checkLocalFilename === UNDEFINED_VALUE) {
5696
+ return strictness == STRICTNESS_STRICT;
5612
5697
  }
5613
- return strictness;
5698
+ return Boolean(checkLocalFilename);
5614
5699
  }
5615
5700
 
5616
5701
  function getFilenameValidation(filenameValidation, strictness) {
@@ -5758,10 +5843,11 @@ async function readSignature(reader, view, anchoredOffset, signatureOffset, size
5758
5843
  return UNDEFINED_VALUE;
5759
5844
  }
5760
5845
 
5761
- function checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename) {
5846
+ function validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename) {
5762
5847
  const { rawFilename } = zipEntry;
5763
- if (rawLocalFilename.length != rawFilename.length ||
5764
- rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte])) {
5848
+ if (checkLocalFilename &&
5849
+ (rawLocalFilename.length != rawFilename.length ||
5850
+ rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte]))) {
5765
5851
  throwAmbiguousArchive("mismatched local file header (filename)");
5766
5852
  }
5767
5853
  if ((localDirectory.rawBitFlag & BITFLAG_AMBIGUITY_MASK) != (zipEntry.rawBitFlag & BITFLAG_AMBIGUITY_MASK)) {
@@ -5879,6 +5965,7 @@ var zipReader = /*#__PURE__*/Object.freeze({
5879
5965
 
5880
5966
  const ERR_DUPLICATED_NAME = "File already exists";
5881
5967
  const ERR_INVALID_COMMENT = "Zip file comment exceeds 64KB";
5968
+ const ERR_INVALID_COMMENT_TYPE = "Invalid zip file comment (must be a Uint8Array)";
5882
5969
  const ERR_INVALID_ENTRY_COMMENT = "File entry comment exceeds 64KB";
5883
5970
  const ERR_INVALID_ENTRY_NAME = "File entry name exceeds 64KB";
5884
5971
  const ERR_INVALID_VERSION = "Version exceeds 65535";
@@ -5947,6 +6034,10 @@ class ZipWriter {
5947
6034
  }
5948
6035
  reader = new GenericReader(reader);
5949
6036
  await initStream(reader);
6037
+ if (reader.size === UNDEFINED_VALUE || !reader.readUint8Array) {
6038
+ reader = new BlobReader(await streamToBlob(reader.readable));
6039
+ await initStream(reader);
6040
+ }
5950
6041
  const { ZipReader } = await Promise.resolve().then(function () { return zipReader; });
5951
6042
  const zipReader$1 = new ZipReader(reader.readable);
5952
6043
  const entries = await zipReader$1.getEntries();
@@ -6095,6 +6186,9 @@ class ZipWriter {
6095
6186
  const zipWriter = this;
6096
6187
  const { pendingAddFileCalls, writer } = this;
6097
6188
  const { writable } = writer;
6189
+ if (!(comment instanceof Uint8Array)) {
6190
+ throw new Error(ERR_INVALID_COMMENT_TYPE);
6191
+ }
6098
6192
  if (getLength(comment) > MAX_16_BITS) {
6099
6193
  throw new Error(ERR_INVALID_COMMENT);
6100
6194
  }
@@ -6191,8 +6285,6 @@ async function addFile(zipWriter, name, reader, options) {
6191
6285
  const diskOffset = getDiskOffset(zipWriter.writer);
6192
6286
  const diskNumber = getDiskNumber(zipWriter.writer);
6193
6287
  options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
6194
- internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
6195
- externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
6196
6288
  signature: options[PROPERTY_NAME_SIGNATURE],
6197
6289
  crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
6198
6290
  offset: zipWriter.offset - diskOffset,
@@ -6206,14 +6298,20 @@ async function addFile(zipWriter, name, reader, options) {
6206
6298
  zipWriter.files.delete(name);
6207
6299
  throw error;
6208
6300
  }
6209
- Object.assign(fileEntry, { name, comment, extraField });
6301
+ Object.assign(fileEntry, {
6302
+ name,
6303
+ comment,
6304
+ extraField,
6305
+ [PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES]: fileEntry.internalFileAttributes,
6306
+ [PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES]: fileEntry.externalFileAttributes
6307
+ });
6210
6308
  return new Entry(fileEntry);
6211
6309
  }
6212
6310
 
6213
6311
  function resolveAttributes(zipWriter, name, options) {
6214
6312
  name = name.trim();
6215
6313
  let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
6216
- let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
6314
+ let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? VERSION_MADE_BY_MSDOS : VERSION_MADE_BY_UNIX);
6217
6315
  const executable = getOptionValue(zipWriter, options, PROPERTY_NAME_EXECUTABLE);
6218
6316
  const uid = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_UID);
6219
6317
  const gid = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_GID);
@@ -6247,7 +6345,7 @@ function resolveAttributes(zipWriter, name, options) {
6247
6345
  const hasMsDosProvided = msdosAttributesRaw !== UNDEFINED_VALUE || msdosAttributes !== UNDEFINED_VALUE;
6248
6346
  if (hasUnixMetadata) {
6249
6347
  msDosCompatible = false;
6250
- versionMadeBy = (versionMadeBy & MAX_16_BITS) | (3 << 8);
6348
+ versionMadeBy = (versionMadeBy & MAX_8_BITS) | VERSION_MADE_BY_UNIX;
6251
6349
  } else if (hasMsDosProvided) {
6252
6350
  msDosCompatible = true;
6253
6351
  versionMadeBy = (versionMadeBy & MAX_8_BITS);
@@ -6287,11 +6385,10 @@ function resolveAttributes(zipWriter, name, options) {
6287
6385
  externalFileAttributes = FILE_ATTR_UNIX_DEFAULT_MASK << 16;
6288
6386
  }
6289
6387
  }
6290
- let unixExternalUpper;
6291
6388
  if (!msDosCompatible) {
6292
6389
  const unixModeProvided = unixMode !== UNDEFINED_VALUE || Boolean(setuid || setgid || sticky);
6293
- unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
6294
- unixMode = unixMode === UNDEFINED_VALUE ? unixExternalUpper : (unixMode & MAX_16_BITS);
6390
+ const defaultUnixMode = (externalFileAttributes >> 16) & MAX_16_BITS;
6391
+ unixMode = unixMode === UNDEFINED_VALUE ? defaultUnixMode : (unixMode & MAX_16_BITS);
6295
6392
  if (setuid) {
6296
6393
  unixMode |= FILE_ATTR_UNIX_SETUID_MASK;
6297
6394
  } else {
@@ -6320,17 +6417,20 @@ function resolveAttributes(zipWriter, name, options) {
6320
6417
  if (hasMsDosProvided) {
6321
6418
  externalFileAttributes = (externalFileAttributes & MAX_32_BITS) | (msdosAttributesRaw & MAX_8_BITS);
6322
6419
  }
6420
+ const unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
6421
+ const symlink = unixMode !== UNDEFINED_VALUE && ((unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_SYMLINK);
6323
6422
  return {
6324
6423
  name,
6325
6424
  resolvedOptions: {
6326
6425
  versionMadeBy,
6327
- msDosCompatible,
6426
+ msDosCompatible: Boolean(msDosCompatible),
6328
6427
  externalFileAttributes,
6329
6428
  unixExternalUpper,
6330
6429
  uid,
6331
6430
  gid,
6332
6431
  unixMode,
6333
6432
  unixExtraFieldType,
6433
+ symlink,
6334
6434
  setuid,
6335
6435
  setgid,
6336
6436
  sticky,
@@ -6563,6 +6663,9 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
6563
6663
  if (writerOptions[OPTION_SIGN_CENTRAL_DIRECTORY]) {
6564
6664
  throw new Error(ERR_UNDETERMINED_SIZE);
6565
6665
  }
6666
+ if (comment !== UNDEFINED_VALUE && !(comment instanceof Uint8Array)) {
6667
+ throw new Error(ERR_INVALID_COMMENT_TYPE);
6668
+ }
6566
6669
  const commentLength = getLength(comment);
6567
6670
  if (commentLength > MAX_16_BITS) {
6568
6671
  throw new Error(ERR_INVALID_COMMENT);
@@ -6844,6 +6947,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
6844
6947
  uid,
6845
6948
  gid,
6846
6949
  unixMode,
6950
+ symlink,
6847
6951
  setuid,
6848
6952
  setgid,
6849
6953
  sticky,
@@ -6880,6 +6984,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
6880
6984
  uid,
6881
6985
  gid,
6882
6986
  unixMode,
6987
+ symlink: Boolean(symlink),
6883
6988
  setuid,
6884
6989
  setgid,
6885
6990
  sticky,
@@ -6960,8 +7065,8 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
6960
7065
  rawLastModDate,
6961
7066
  creationDate,
6962
7067
  lastAccessDate,
6963
- encrypted,
6964
- zipCrypto,
7068
+ encrypted: Boolean(encrypted),
7069
+ zipCrypto: Boolean(zipCrypto),
6965
7070
  size: metadataSize + compressedSize,
6966
7071
  compressionMethod,
6967
7072
  version,
@@ -9738,6 +9843,7 @@ exports.ERR_INVALID_AUTHENTICATION_CODE = ERR_INVALID_AUTHENTICATION_CODE;
9738
9843
  exports.ERR_INVALID_CODEC_DEFINITION = ERR_INVALID_CODEC_DEFINITION;
9739
9844
  exports.ERR_INVALID_CODEC_MODULE = ERR_INVALID_CODEC_MODULE;
9740
9845
  exports.ERR_INVALID_COMMENT = ERR_INVALID_COMMENT;
9846
+ exports.ERR_INVALID_COMMENT_TYPE = ERR_INVALID_COMMENT_TYPE;
9741
9847
  exports.ERR_INVALID_COMPRESSED_DATA = ERR_INVALID_COMPRESSED_DATA;
9742
9848
  exports.ERR_INVALID_CRC32 = ERR_INVALID_CRC32;
9743
9849
  exports.ERR_INVALID_ENCRYPTION_STRENGTH = ERR_INVALID_ENCRYPTION_STRENGTH;