@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.
@@ -102,6 +102,9 @@
102
102
  const VERSION_ZIP64 = 0x2D;
103
103
  const VERSION_AES = 0x33;
104
104
 
105
+ const VERSION_MADE_BY_MSDOS = 0x0014;
106
+ const VERSION_MADE_BY_UNIX = 0x0300;
107
+
105
108
  const DIRECTORY_SIGNATURE = "/";
106
109
 
107
110
  const HEADER_SIZE = 30;
@@ -2758,6 +2761,7 @@
2758
2761
  worker,
2759
2762
  workerAlive: false,
2760
2763
  terminated: false,
2764
+ startupError: null,
2761
2765
  interface: {
2762
2766
  run: async () => {
2763
2767
  try {
@@ -2785,6 +2789,13 @@
2785
2789
  }
2786
2790
 
2787
2791
  async function runWebWorker(workerData, config) {
2792
+ if (!workerData.worker) {
2793
+ const { startupError } = workerData;
2794
+ workerData.startupError = null;
2795
+ const error = startupError || new Error(ERR_WORKER_STARTUP_TIMEOUT);
2796
+ error.workerStartupFailed = true;
2797
+ throw error;
2798
+ }
2788
2799
  let resolveResult, rejectResult;
2789
2800
  const result = new Promise((resolve, reject) => {
2790
2801
  resolveResult = resolve;
@@ -2998,11 +3009,12 @@
2998
3009
  if (!workerAlive) {
2999
3010
  workerData.worker = null;
3000
3011
  }
3012
+ let error = event.error || new Error(event.message || ERROR_EVENT_TYPE);
3013
+ if (!workerAlive) {
3014
+ error = Object.assign(new Error(error.message || ERROR_EVENT_TYPE), { workerStartupFailed: true });
3015
+ workerData.startupError = error;
3016
+ }
3001
3017
  if (rejectResult) {
3002
- let error = event.error || new Error(event.message || ERROR_EVENT_TYPE);
3003
- if (!workerAlive) {
3004
- error = Object.assign(new Error(error.message || ERROR_EVENT_TYPE), { workerStartupFailed: true });
3005
- }
3006
3018
  rejectResult(error);
3007
3019
  if (writer) {
3008
3020
  writer.releaseLock();
@@ -4051,9 +4063,8 @@
4051
4063
 
4052
4064
  async init() {
4053
4065
  const reader = this;
4054
- const { readers } = reader;
4055
4066
  reader.lastDiskNumber = 0;
4056
- await Promise.all(readers.map(diskReader => initStream(diskReader)));
4067
+ const readers = reader.readers = await Promise.all(reader.readers.map(initDiskReader));
4057
4068
  reader.diskOffsets = readers.map(diskReader => {
4058
4069
  const diskOffset = reader.size;
4059
4070
  reader.size += diskReader.size;
@@ -4248,6 +4259,16 @@
4248
4259
  }
4249
4260
  }
4250
4261
 
4262
+ async function initDiskReader(diskReader) {
4263
+ diskReader = new GenericReader(diskReader);
4264
+ await initStream(diskReader);
4265
+ if (diskReader.size === UNDEFINED_VALUE || !diskReader.readUint8Array) {
4266
+ diskReader = new BlobReader(await streamToBlob(diskReader.readable));
4267
+ await initStream(diskReader);
4268
+ }
4269
+ return diskReader;
4270
+ }
4271
+
4251
4272
  function readUint8Array(reader, offset, size) {
4252
4273
  return reader.readUint8Array(offset, size);
4253
4274
  }
@@ -4406,6 +4427,10 @@
4406
4427
  const PROPERTY_NAME_SETGID = "setgid";
4407
4428
  const PROPERTY_NAME_STICKY = "sticky";
4408
4429
  const PROPERTY_NAME_BITFLAG = "bitFlag";
4430
+ const PROPERTY_NAME_RAW_BITFLAG = "rawBitFlag";
4431
+ const PROPERTY_NAME_FILENAME_LENGTH = "filenameLength";
4432
+ const PROPERTY_NAME_EXTRA_FIELD_LENGTH = "extraFieldLength";
4433
+ const PROPERTY_NAME_UNIX_EXTERNAL_UPPER = "unixExternalUpper";
4409
4434
  const PROPERTY_NAME_FILENAME_UTF8 = "filenameUTF8";
4410
4435
  const PROPERTY_NAME_COMMENT_UTF8 = "commentUTF8";
4411
4436
  const PROPERTY_NAME_RAW_EXTRA_FIELD = "rawExtraField";
@@ -4458,10 +4483,14 @@
4458
4483
  PROPERTY_NAME_UID,
4459
4484
  PROPERTY_NAME_GID,
4460
4485
  PROPERTY_NAME_UNIX_MODE,
4486
+ PROPERTY_NAME_UNIX_EXTERNAL_UPPER,
4461
4487
  PROPERTY_NAME_SETUID,
4462
4488
  PROPERTY_NAME_SETGID,
4463
4489
  PROPERTY_NAME_STICKY,
4464
4490
  PROPERTY_NAME_BITFLAG,
4491
+ PROPERTY_NAME_RAW_BITFLAG,
4492
+ PROPERTY_NAME_FILENAME_LENGTH,
4493
+ PROPERTY_NAME_EXTRA_FIELD_LENGTH,
4465
4494
  PROPERTY_NAME_FILENAME_UTF8,
4466
4495
  PROPERTY_NAME_COMMENT_UTF8,
4467
4496
  PROPERTY_NAME_RAW_EXTRA_FIELD,
@@ -4523,6 +4552,7 @@
4523
4552
  const OPTION_CHECK_OVERLAPPING_ENTRY_ONLY = "checkOverlappingEntryOnly";
4524
4553
  const OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
4525
4554
  const OPTION_CHECK_AMBIGUITY = "checkAmbiguity";
4555
+ const OPTION_CHECK_LOCAL_DIRECTORY = "checkLocalDirectory";
4526
4556
  const OPTION_CHECK_SIGNATURE = "checkSignature";
4527
4557
  const OPTION_CHECK_CRC32 = "checkCrc32";
4528
4558
  const OPTION_CHECK_AUTHENTICATION_CODE = "checkAuthenticationCode";
@@ -4654,7 +4684,7 @@
4654
4684
  if (reader.size < END_OF_CENTRAL_DIR_LENGTH) {
4655
4685
  throw new Error(ERR_BAD_FORMAT);
4656
4686
  }
4657
- const strictness = getStrictness(getOptionValue$1(zipReader, options, OPTION_STRICTNESS), getOptionValue$1(zipReader, options, OPTION_CHECK_AMBIGUITY));
4687
+ const strictness = getStrictness(options, zipReader.options);
4658
4688
  const checkAmbiguity = strictness == STRICTNESS_STRICT;
4659
4689
  const rejectAmbiguousEndOfDirectory = strictness != STRICTNESS_TOLERANT;
4660
4690
  const maxAppendedDataSize = getMaxAppendedDataSize(getOptionValue$1(zipReader, options, OPTION_MAX_APPENDED_DATA_SIZE), strictness);
@@ -4876,6 +4906,7 @@
4876
4906
  index: indexFile,
4877
4907
  versionMadeBy,
4878
4908
  msDosCompatible,
4909
+ zip64: false,
4879
4910
  compressedSize: 0,
4880
4911
  uncompressedSize: 0,
4881
4912
  commentLength,
@@ -5086,9 +5117,12 @@
5086
5117
  extraFieldLength,
5087
5118
  filenameLength
5088
5119
  } = localDirectory;
5089
- const checkAmbiguity = getStrictness(getOptionValue$1(zipEntry, options, OPTION_STRICTNESS), getOptionValue$1(zipEntry, options, OPTION_CHECK_AMBIGUITY)) == STRICTNESS_STRICT;
5120
+ const checkLocalDirectoryOption = getOptionValue$1(zipEntry, options, OPTION_CHECK_LOCAL_DIRECTORY);
5121
+ const entryStrictness = getStrictness(options, zipEntry.options);
5122
+ const checkLocalDirectory = getCheckLocalDirectory(checkLocalDirectoryOption, entryStrictness);
5123
+ const checkLocalFilename = getCheckLocalFilename(checkLocalDirectoryOption, entryStrictness);
5090
5124
  let rawLocalFilename = EMPTY_UINT8_ARRAY;
5091
- if (checkAmbiguity && (filenameLength || extraFieldLength)) {
5125
+ if (checkLocalFilename && (filenameLength || extraFieldLength)) {
5092
5126
  const trailingDataArray = await readUint8Array(reader, localHeaderOffset + HEADER_SIZE, filenameLength + extraFieldLength);
5093
5127
  rawLocalFilename = trailingDataArray.subarray(0, filenameLength);
5094
5128
  localDirectory.rawExtraField = trailingDataArray.subarray(filenameLength);
@@ -5097,17 +5131,26 @@
5097
5131
  await readUint8Array(reader, localHeaderOffset + HEADER_SIZE + filenameLength, extraFieldLength) :
5098
5132
  EMPTY_UINT8_ARRAY;
5099
5133
  }
5134
+ if (checkLocalFilename) {
5135
+ localDirectory.rawFilename = rawLocalFilename;
5136
+ }
5100
5137
  readCommonFooter(zipEntry, localDirectory, dataView, 4, true);
5101
- if (checkAmbiguity) {
5102
- checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename);
5138
+ if (checkLocalDirectory) {
5139
+ validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename);
5103
5140
  }
5104
- const { lastAccessDate, creationDate } = localDirectory;
5141
+ const { lastAccessDate, creationDate, uid, gid } = localDirectory;
5105
5142
  if (lastAccessDate) {
5106
5143
  fileEntry.lastAccessDate = lastAccessDate;
5107
5144
  }
5108
5145
  if (creationDate) {
5109
5146
  fileEntry.creationDate = creationDate;
5110
5147
  }
5148
+ if (uid !== UNDEFINED_VALUE && fileEntry.uid === UNDEFINED_VALUE) {
5149
+ fileEntry.uid = uid;
5150
+ }
5151
+ if (gid !== UNDEFINED_VALUE && fileEntry.gid === UNDEFINED_VALUE) {
5152
+ fileEntry.gid = gid;
5153
+ }
5111
5154
  const encrypted = zipEntry.encrypted && localDirectory.encrypted && !passThrough;
5112
5155
  const zipCrypto = encrypted && !extraFieldAES;
5113
5156
  if (!passThrough) {
@@ -5343,10 +5386,12 @@
5343
5386
  directory.extraFieldNTFS = extraFieldNTFS;
5344
5387
  }
5345
5388
  const extraFieldUnix = extraField.get(EXTRAFIELD_TYPE_UNIX);
5389
+ let unixIdsRead;
5346
5390
  if (extraFieldUnix) {
5347
- readExtraFieldUnix(extraFieldUnix, directory, false);
5391
+ unixIdsRead = readExtraFieldUnix(extraFieldUnix, directory, false);
5348
5392
  directory.extraFieldUnix = extraFieldUnix;
5349
- } else {
5393
+ }
5394
+ if (!unixIdsRead) {
5350
5395
  const extraFieldInfoZip = extraField.get(EXTRAFIELD_TYPE_INFOZIP);
5351
5396
  if (extraFieldInfoZip) {
5352
5397
  readExtraFieldUnix(extraFieldInfoZip, directory, true);
@@ -5449,7 +5494,7 @@
5449
5494
  const creationDate = getDateNTFS(rawCreationDate);
5450
5495
  const extraFieldData = { lastModDate, lastAccessDate, creationDate };
5451
5496
  Object.assign(extraFieldNTFS, extraFieldData);
5452
- Object.assign(directory, extraFieldData);
5497
+ Object.assign(directory, extraFieldData, { rawLastAccessDate, rawCreationDate });
5453
5498
  }
5454
5499
  }
5455
5500
 
@@ -5493,6 +5538,7 @@
5493
5538
  if (gid !== UNDEFINED_VALUE) {
5494
5539
  directory.gid = gid;
5495
5540
  }
5541
+ return uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE;
5496
5542
  } catch {
5497
5543
  // ignored
5498
5544
  }
@@ -5565,26 +5611,25 @@
5565
5611
  }
5566
5612
  if (dataDescriptorLength) {
5567
5613
  const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH);
5568
- const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
5569
- getUint32(getDataView(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
5570
- if (dataDescriptorSignature) {
5571
- const readCrc32 = getUint32(getDataView(dataDescriptorArray), 4);
5572
- let readCompressedSize;
5573
- let readUncompressedSize;
5574
- if (extraFieldZip64) {
5575
- readCompressedSize = getBigUint64(getDataView(dataDescriptorArray), 8);
5576
- readUncompressedSize = getBigUint64(getDataView(dataDescriptorArray), 16);
5577
- } else {
5578
- readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
5579
- readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
5580
- }
5581
- const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || readCrc32 == crc32;
5614
+ const dataDescriptorView = getDataView(dataDescriptorArray);
5615
+ let signature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
5616
+ getUint32(dataDescriptorView, 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
5617
+ if (signature) {
5618
+ const signedDataDescriptor = readDataDescriptor(dataDescriptorView, DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH, extraFieldZip64);
5619
+ const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || signedDataDescriptor.crc32 == crc32;
5582
5620
  if (matchCrc32 &&
5583
- readCompressedSize == compressedSize &&
5584
- readUncompressedSize == uncompressedSize) {
5621
+ signedDataDescriptor.compressedSize == compressedSize &&
5622
+ signedDataDescriptor.uncompressedSize == uncompressedSize) {
5585
5623
  dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
5624
+ } else {
5625
+ signature = false;
5586
5626
  }
5587
5627
  }
5628
+ if (dataDescriptorArray.length >= dataDescriptorLength) {
5629
+ const localDataDescriptor = readDataDescriptor(dataDescriptorView, signature ? DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH : 0, extraFieldZip64);
5630
+ localDataDescriptor.signature = signature;
5631
+ fileEntry.localDirectory.dataDescriptor = localDataDescriptor;
5632
+ }
5588
5633
  }
5589
5634
  const range = {
5590
5635
  start: offset,
@@ -5601,6 +5646,20 @@
5601
5646
  readRanges.set(index, range);
5602
5647
  }
5603
5648
 
5649
+ function readDataDescriptor(dataDescriptorView, offset, extraFieldZip64) {
5650
+ const crc32 = getUint32(dataDescriptorView, offset);
5651
+ let compressedSize;
5652
+ let uncompressedSize;
5653
+ if (extraFieldZip64) {
5654
+ compressedSize = getBigUint64(dataDescriptorView, offset + 4);
5655
+ uncompressedSize = getBigUint64(dataDescriptorView, offset + 12);
5656
+ } else {
5657
+ compressedSize = getUint32(dataDescriptorView, offset + 4);
5658
+ uncompressedSize = getUint32(dataDescriptorView, offset + 8);
5659
+ }
5660
+ return { crc32, compressedSize, uncompressedSize };
5661
+ }
5662
+
5604
5663
  function getDiskOffset$1(reader, diskNumber) {
5605
5664
  return reader.getDiskOffset ? reader.getDiskOffset(diskNumber) : 0;
5606
5665
  }
@@ -5609,14 +5668,40 @@
5609
5668
  return value === STRICTNESS_STRICT || value === STRICTNESS_BALANCED || value === STRICTNESS_TOLERANT;
5610
5669
  }
5611
5670
 
5612
- function getStrictness(strictness, checkAmbiguity) {
5613
- if (strictness === UNDEFINED_VALUE) {
5614
- return checkAmbiguity ? STRICTNESS_STRICT : STRICTNESS_BALANCED;
5671
+ function getStrictness(options, inheritedOptions) {
5672
+ return resolveStrictness(options, resolveStrictness(inheritedOptions, STRICTNESS_BALANCED));
5673
+ }
5674
+
5675
+ function resolveStrictness(options, inheritedStrictness) {
5676
+ const strictness = options[OPTION_STRICTNESS];
5677
+ if (strictness !== UNDEFINED_VALUE) {
5678
+ if (!isStrictnessValue(strictness)) {
5679
+ throw new Error(ERR_INVALID_STRICTNESS);
5680
+ }
5681
+ return strictness;
5682
+ }
5683
+ const checkAmbiguity = options[OPTION_CHECK_AMBIGUITY];
5684
+ if (checkAmbiguity === UNDEFINED_VALUE) {
5685
+ return inheritedStrictness;
5686
+ }
5687
+ if (checkAmbiguity) {
5688
+ return STRICTNESS_STRICT;
5689
+ }
5690
+ return inheritedStrictness == STRICTNESS_TOLERANT ? STRICTNESS_TOLERANT : STRICTNESS_BALANCED;
5691
+ }
5692
+
5693
+ function getCheckLocalDirectory(checkLocalDirectory, strictness) {
5694
+ if (checkLocalDirectory === UNDEFINED_VALUE) {
5695
+ return strictness != STRICTNESS_TOLERANT;
5615
5696
  }
5616
- if (!isStrictnessValue(strictness)) {
5617
- throw new Error(ERR_INVALID_STRICTNESS);
5697
+ return Boolean(checkLocalDirectory);
5698
+ }
5699
+
5700
+ function getCheckLocalFilename(checkLocalFilename, strictness) {
5701
+ if (checkLocalFilename === UNDEFINED_VALUE) {
5702
+ return strictness == STRICTNESS_STRICT;
5618
5703
  }
5619
- return strictness;
5704
+ return Boolean(checkLocalFilename);
5620
5705
  }
5621
5706
 
5622
5707
  function getFilenameValidation(filenameValidation, strictness) {
@@ -5764,10 +5849,11 @@
5764
5849
  return UNDEFINED_VALUE;
5765
5850
  }
5766
5851
 
5767
- function checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename) {
5852
+ function validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename) {
5768
5853
  const { rawFilename } = zipEntry;
5769
- if (rawLocalFilename.length != rawFilename.length ||
5770
- rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte])) {
5854
+ if (checkLocalFilename &&
5855
+ (rawLocalFilename.length != rawFilename.length ||
5856
+ rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte]))) {
5771
5857
  throwAmbiguousArchive("mismatched local file header (filename)");
5772
5858
  }
5773
5859
  if ((localDirectory.rawBitFlag & BITFLAG_AMBIGUITY_MASK) != (zipEntry.rawBitFlag & BITFLAG_AMBIGUITY_MASK)) {
@@ -5885,6 +5971,7 @@
5885
5971
 
5886
5972
  const ERR_DUPLICATED_NAME = "File already exists";
5887
5973
  const ERR_INVALID_COMMENT = "Zip file comment exceeds 64KB";
5974
+ const ERR_INVALID_COMMENT_TYPE = "Invalid zip file comment (must be a Uint8Array)";
5888
5975
  const ERR_INVALID_ENTRY_COMMENT = "File entry comment exceeds 64KB";
5889
5976
  const ERR_INVALID_ENTRY_NAME = "File entry name exceeds 64KB";
5890
5977
  const ERR_INVALID_VERSION = "Version exceeds 65535";
@@ -5953,6 +6040,10 @@
5953
6040
  }
5954
6041
  reader = new GenericReader(reader);
5955
6042
  await initStream(reader);
6043
+ if (reader.size === UNDEFINED_VALUE || !reader.readUint8Array) {
6044
+ reader = new BlobReader(await streamToBlob(reader.readable));
6045
+ await initStream(reader);
6046
+ }
5956
6047
  const { ZipReader } = await Promise.resolve().then(function () { return zipReader; });
5957
6048
  const zipReader$1 = new ZipReader(reader.readable);
5958
6049
  const entries = await zipReader$1.getEntries();
@@ -6101,6 +6192,9 @@
6101
6192
  const zipWriter = this;
6102
6193
  const { pendingAddFileCalls, writer } = this;
6103
6194
  const { writable } = writer;
6195
+ if (!(comment instanceof Uint8Array)) {
6196
+ throw new Error(ERR_INVALID_COMMENT_TYPE);
6197
+ }
6104
6198
  if (getLength(comment) > MAX_16_BITS) {
6105
6199
  throw new Error(ERR_INVALID_COMMENT);
6106
6200
  }
@@ -6197,8 +6291,6 @@
6197
6291
  const diskOffset = getDiskOffset(zipWriter.writer);
6198
6292
  const diskNumber = getDiskNumber(zipWriter.writer);
6199
6293
  options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
6200
- internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
6201
- externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
6202
6294
  signature: options[PROPERTY_NAME_SIGNATURE],
6203
6295
  crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
6204
6296
  offset: zipWriter.offset - diskOffset,
@@ -6212,14 +6304,20 @@
6212
6304
  zipWriter.files.delete(name);
6213
6305
  throw error;
6214
6306
  }
6215
- Object.assign(fileEntry, { name, comment, extraField });
6307
+ Object.assign(fileEntry, {
6308
+ name,
6309
+ comment,
6310
+ extraField,
6311
+ [PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES]: fileEntry.internalFileAttributes,
6312
+ [PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES]: fileEntry.externalFileAttributes
6313
+ });
6216
6314
  return new Entry(fileEntry);
6217
6315
  }
6218
6316
 
6219
6317
  function resolveAttributes(zipWriter, name, options) {
6220
6318
  name = name.trim();
6221
6319
  let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
6222
- let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
6320
+ let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? VERSION_MADE_BY_MSDOS : VERSION_MADE_BY_UNIX);
6223
6321
  const executable = getOptionValue(zipWriter, options, PROPERTY_NAME_EXECUTABLE);
6224
6322
  const uid = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_UID);
6225
6323
  const gid = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_GID);
@@ -6253,7 +6351,7 @@
6253
6351
  const hasMsDosProvided = msdosAttributesRaw !== UNDEFINED_VALUE || msdosAttributes !== UNDEFINED_VALUE;
6254
6352
  if (hasUnixMetadata) {
6255
6353
  msDosCompatible = false;
6256
- versionMadeBy = (versionMadeBy & MAX_16_BITS) | (3 << 8);
6354
+ versionMadeBy = (versionMadeBy & MAX_8_BITS) | VERSION_MADE_BY_UNIX;
6257
6355
  } else if (hasMsDosProvided) {
6258
6356
  msDosCompatible = true;
6259
6357
  versionMadeBy = (versionMadeBy & MAX_8_BITS);
@@ -6293,11 +6391,10 @@
6293
6391
  externalFileAttributes = FILE_ATTR_UNIX_DEFAULT_MASK << 16;
6294
6392
  }
6295
6393
  }
6296
- let unixExternalUpper;
6297
6394
  if (!msDosCompatible) {
6298
6395
  const unixModeProvided = unixMode !== UNDEFINED_VALUE || Boolean(setuid || setgid || sticky);
6299
- unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
6300
- unixMode = unixMode === UNDEFINED_VALUE ? unixExternalUpper : (unixMode & MAX_16_BITS);
6396
+ const defaultUnixMode = (externalFileAttributes >> 16) & MAX_16_BITS;
6397
+ unixMode = unixMode === UNDEFINED_VALUE ? defaultUnixMode : (unixMode & MAX_16_BITS);
6301
6398
  if (setuid) {
6302
6399
  unixMode |= FILE_ATTR_UNIX_SETUID_MASK;
6303
6400
  } else {
@@ -6326,17 +6423,20 @@
6326
6423
  if (hasMsDosProvided) {
6327
6424
  externalFileAttributes = (externalFileAttributes & MAX_32_BITS) | (msdosAttributesRaw & MAX_8_BITS);
6328
6425
  }
6426
+ const unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
6427
+ const symlink = unixMode !== UNDEFINED_VALUE && ((unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_SYMLINK);
6329
6428
  return {
6330
6429
  name,
6331
6430
  resolvedOptions: {
6332
6431
  versionMadeBy,
6333
- msDosCompatible,
6432
+ msDosCompatible: Boolean(msDosCompatible),
6334
6433
  externalFileAttributes,
6335
6434
  unixExternalUpper,
6336
6435
  uid,
6337
6436
  gid,
6338
6437
  unixMode,
6339
6438
  unixExtraFieldType,
6439
+ symlink,
6340
6440
  setuid,
6341
6441
  setgid,
6342
6442
  sticky,
@@ -6569,6 +6669,9 @@
6569
6669
  if (writerOptions[OPTION_SIGN_CENTRAL_DIRECTORY]) {
6570
6670
  throw new Error(ERR_UNDETERMINED_SIZE);
6571
6671
  }
6672
+ if (comment !== UNDEFINED_VALUE && !(comment instanceof Uint8Array)) {
6673
+ throw new Error(ERR_INVALID_COMMENT_TYPE);
6674
+ }
6572
6675
  const commentLength = getLength(comment);
6573
6676
  if (commentLength > MAX_16_BITS) {
6574
6677
  throw new Error(ERR_INVALID_COMMENT);
@@ -6850,6 +6953,7 @@
6850
6953
  uid,
6851
6954
  gid,
6852
6955
  unixMode,
6956
+ symlink,
6853
6957
  setuid,
6854
6958
  setgid,
6855
6959
  sticky,
@@ -6886,6 +6990,7 @@
6886
6990
  uid,
6887
6991
  gid,
6888
6992
  unixMode,
6993
+ symlink: Boolean(symlink),
6889
6994
  setuid,
6890
6995
  setgid,
6891
6996
  sticky,
@@ -6966,8 +7071,8 @@
6966
7071
  rawLastModDate,
6967
7072
  creationDate,
6968
7073
  lastAccessDate,
6969
- encrypted,
6970
- zipCrypto,
7074
+ encrypted: Boolean(encrypted),
7075
+ zipCrypto: Boolean(zipCrypto),
6971
7076
  size: metadataSize + compressedSize,
6972
7077
  compressionMethod,
6973
7078
  version,
@@ -9744,6 +9849,7 @@
9744
9849
  exports.ERR_INVALID_CODEC_DEFINITION = ERR_INVALID_CODEC_DEFINITION;
9745
9850
  exports.ERR_INVALID_CODEC_MODULE = ERR_INVALID_CODEC_MODULE;
9746
9851
  exports.ERR_INVALID_COMMENT = ERR_INVALID_COMMENT;
9852
+ exports.ERR_INVALID_COMMENT_TYPE = ERR_INVALID_COMMENT_TYPE;
9747
9853
  exports.ERR_INVALID_COMPRESSED_DATA = ERR_INVALID_COMPRESSED_DATA;
9748
9854
  exports.ERR_INVALID_CRC32 = ERR_INVALID_CRC32;
9749
9855
  exports.ERR_INVALID_ENCRYPTION_STRENGTH = ERR_INVALID_ENCRYPTION_STRENGTH;