@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/index.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;
@@ -2756,6 +2759,7 @@ function createWebWorkerInterface(workerData, config) {
2756
2759
  worker,
2757
2760
  workerAlive: false,
2758
2761
  terminated: false,
2762
+ startupError: null,
2759
2763
  interface: {
2760
2764
  run: async () => {
2761
2765
  try {
@@ -2783,6 +2787,13 @@ function createWebWorkerInterface(workerData, config) {
2783
2787
  }
2784
2788
 
2785
2789
  async function runWebWorker(workerData, config) {
2790
+ if (!workerData.worker) {
2791
+ const { startupError } = workerData;
2792
+ workerData.startupError = null;
2793
+ const error = startupError || new Error(ERR_WORKER_STARTUP_TIMEOUT);
2794
+ error.workerStartupFailed = true;
2795
+ throw error;
2796
+ }
2786
2797
  let resolveResult, rejectResult;
2787
2798
  const result = new Promise((resolve, reject) => {
2788
2799
  resolveResult = resolve;
@@ -2996,11 +3007,12 @@ function onWorkerError(event, workerData) {
2996
3007
  if (!workerAlive) {
2997
3008
  workerData.worker = null;
2998
3009
  }
3010
+ let error = event.error || new Error(event.message || ERROR_EVENT_TYPE);
3011
+ if (!workerAlive) {
3012
+ error = Object.assign(new Error(error.message || ERROR_EVENT_TYPE), { workerStartupFailed: true });
3013
+ workerData.startupError = error;
3014
+ }
2999
3015
  if (rejectResult) {
3000
- let error = event.error || new Error(event.message || ERROR_EVENT_TYPE);
3001
- if (!workerAlive) {
3002
- error = Object.assign(new Error(error.message || ERROR_EVENT_TYPE), { workerStartupFailed: true });
3003
- }
3004
3016
  rejectResult(error);
3005
3017
  if (writer) {
3006
3018
  writer.releaseLock();
@@ -4049,9 +4061,8 @@ class SplitDataReader extends Reader {
4049
4061
 
4050
4062
  async init() {
4051
4063
  const reader = this;
4052
- const { readers } = reader;
4053
4064
  reader.lastDiskNumber = 0;
4054
- await Promise.all(readers.map(diskReader => initStream(diskReader)));
4065
+ const readers = reader.readers = await Promise.all(reader.readers.map(initDiskReader));
4055
4066
  reader.diskOffsets = readers.map(diskReader => {
4056
4067
  const diskOffset = reader.size;
4057
4068
  reader.size += diskReader.size;
@@ -4246,6 +4257,16 @@ async function initStream(stream, initSize) {
4246
4257
  }
4247
4258
  }
4248
4259
 
4260
+ async function initDiskReader(diskReader) {
4261
+ diskReader = new GenericReader(diskReader);
4262
+ await initStream(diskReader);
4263
+ if (diskReader.size === UNDEFINED_VALUE || !diskReader.readUint8Array) {
4264
+ diskReader = new BlobReader(await streamToBlob(diskReader.readable));
4265
+ await initStream(diskReader);
4266
+ }
4267
+ return diskReader;
4268
+ }
4269
+
4249
4270
  function readUint8Array(reader, offset, size) {
4250
4271
  return reader.readUint8Array(offset, size);
4251
4272
  }
@@ -4404,6 +4425,10 @@ const PROPERTY_NAME_SETUID = "setuid";
4404
4425
  const PROPERTY_NAME_SETGID = "setgid";
4405
4426
  const PROPERTY_NAME_STICKY = "sticky";
4406
4427
  const PROPERTY_NAME_BITFLAG = "bitFlag";
4428
+ const PROPERTY_NAME_RAW_BITFLAG = "rawBitFlag";
4429
+ const PROPERTY_NAME_FILENAME_LENGTH = "filenameLength";
4430
+ const PROPERTY_NAME_EXTRA_FIELD_LENGTH = "extraFieldLength";
4431
+ const PROPERTY_NAME_UNIX_EXTERNAL_UPPER = "unixExternalUpper";
4407
4432
  const PROPERTY_NAME_FILENAME_UTF8 = "filenameUTF8";
4408
4433
  const PROPERTY_NAME_COMMENT_UTF8 = "commentUTF8";
4409
4434
  const PROPERTY_NAME_RAW_EXTRA_FIELD = "rawExtraField";
@@ -4456,10 +4481,14 @@ const PROPERTY_NAMES = [
4456
4481
  PROPERTY_NAME_UID,
4457
4482
  PROPERTY_NAME_GID,
4458
4483
  PROPERTY_NAME_UNIX_MODE,
4484
+ PROPERTY_NAME_UNIX_EXTERNAL_UPPER,
4459
4485
  PROPERTY_NAME_SETUID,
4460
4486
  PROPERTY_NAME_SETGID,
4461
4487
  PROPERTY_NAME_STICKY,
4462
4488
  PROPERTY_NAME_BITFLAG,
4489
+ PROPERTY_NAME_RAW_BITFLAG,
4490
+ PROPERTY_NAME_FILENAME_LENGTH,
4491
+ PROPERTY_NAME_EXTRA_FIELD_LENGTH,
4463
4492
  PROPERTY_NAME_FILENAME_UTF8,
4464
4493
  PROPERTY_NAME_COMMENT_UTF8,
4465
4494
  PROPERTY_NAME_RAW_EXTRA_FIELD,
@@ -4521,6 +4550,7 @@ const OPTION_CHECK_PASSWORD_ONLY = "checkPasswordOnly";
4521
4550
  const OPTION_CHECK_OVERLAPPING_ENTRY_ONLY = "checkOverlappingEntryOnly";
4522
4551
  const OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
4523
4552
  const OPTION_CHECK_AMBIGUITY = "checkAmbiguity";
4553
+ const OPTION_CHECK_LOCAL_DIRECTORY = "checkLocalDirectory";
4524
4554
  const OPTION_CHECK_SIGNATURE = "checkSignature";
4525
4555
  const OPTION_CHECK_CRC32 = "checkCrc32";
4526
4556
  const OPTION_CHECK_AUTHENTICATION_CODE = "checkAuthenticationCode";
@@ -4652,7 +4682,7 @@ class ZipReader {
4652
4682
  if (reader.size < END_OF_CENTRAL_DIR_LENGTH) {
4653
4683
  throw new Error(ERR_BAD_FORMAT);
4654
4684
  }
4655
- const strictness = getStrictness(getOptionValue$1(zipReader, options, OPTION_STRICTNESS), getOptionValue$1(zipReader, options, OPTION_CHECK_AMBIGUITY));
4685
+ const strictness = getStrictness(options, zipReader.options);
4656
4686
  const checkAmbiguity = strictness == STRICTNESS_STRICT;
4657
4687
  const rejectAmbiguousEndOfDirectory = strictness != STRICTNESS_TOLERANT;
4658
4688
  const maxAppendedDataSize = getMaxAppendedDataSize(getOptionValue$1(zipReader, options, OPTION_MAX_APPENDED_DATA_SIZE), strictness);
@@ -4874,6 +4904,7 @@ class ZipReader {
4874
4904
  index: indexFile,
4875
4905
  versionMadeBy,
4876
4906
  msDosCompatible,
4907
+ zip64: false,
4877
4908
  compressedSize: 0,
4878
4909
  uncompressedSize: 0,
4879
4910
  commentLength,
@@ -5084,9 +5115,12 @@ let ZipEntry$1 = class ZipEntry {
5084
5115
  extraFieldLength,
5085
5116
  filenameLength
5086
5117
  } = localDirectory;
5087
- const checkAmbiguity = getStrictness(getOptionValue$1(zipEntry, options, OPTION_STRICTNESS), getOptionValue$1(zipEntry, options, OPTION_CHECK_AMBIGUITY)) == STRICTNESS_STRICT;
5118
+ const checkLocalDirectoryOption = getOptionValue$1(zipEntry, options, OPTION_CHECK_LOCAL_DIRECTORY);
5119
+ const entryStrictness = getStrictness(options, zipEntry.options);
5120
+ const checkLocalDirectory = getCheckLocalDirectory(checkLocalDirectoryOption, entryStrictness);
5121
+ const checkLocalFilename = getCheckLocalFilename(checkLocalDirectoryOption, entryStrictness);
5088
5122
  let rawLocalFilename = EMPTY_UINT8_ARRAY;
5089
- if (checkAmbiguity && (filenameLength || extraFieldLength)) {
5123
+ if (checkLocalFilename && (filenameLength || extraFieldLength)) {
5090
5124
  const trailingDataArray = await readUint8Array(reader, localHeaderOffset + HEADER_SIZE, filenameLength + extraFieldLength);
5091
5125
  rawLocalFilename = trailingDataArray.subarray(0, filenameLength);
5092
5126
  localDirectory.rawExtraField = trailingDataArray.subarray(filenameLength);
@@ -5095,17 +5129,26 @@ let ZipEntry$1 = class ZipEntry {
5095
5129
  await readUint8Array(reader, localHeaderOffset + HEADER_SIZE + filenameLength, extraFieldLength) :
5096
5130
  EMPTY_UINT8_ARRAY;
5097
5131
  }
5132
+ if (checkLocalFilename) {
5133
+ localDirectory.rawFilename = rawLocalFilename;
5134
+ }
5098
5135
  readCommonFooter(zipEntry, localDirectory, dataView, 4, true);
5099
- if (checkAmbiguity) {
5100
- checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename);
5136
+ if (checkLocalDirectory) {
5137
+ validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename);
5101
5138
  }
5102
- const { lastAccessDate, creationDate } = localDirectory;
5139
+ const { lastAccessDate, creationDate, uid, gid } = localDirectory;
5103
5140
  if (lastAccessDate) {
5104
5141
  fileEntry.lastAccessDate = lastAccessDate;
5105
5142
  }
5106
5143
  if (creationDate) {
5107
5144
  fileEntry.creationDate = creationDate;
5108
5145
  }
5146
+ if (uid !== UNDEFINED_VALUE && fileEntry.uid === UNDEFINED_VALUE) {
5147
+ fileEntry.uid = uid;
5148
+ }
5149
+ if (gid !== UNDEFINED_VALUE && fileEntry.gid === UNDEFINED_VALUE) {
5150
+ fileEntry.gid = gid;
5151
+ }
5109
5152
  const encrypted = zipEntry.encrypted && localDirectory.encrypted && !passThrough;
5110
5153
  const zipCrypto = encrypted && !extraFieldAES;
5111
5154
  if (!passThrough) {
@@ -5341,10 +5384,12 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
5341
5384
  directory.extraFieldNTFS = extraFieldNTFS;
5342
5385
  }
5343
5386
  const extraFieldUnix = extraField.get(EXTRAFIELD_TYPE_UNIX);
5387
+ let unixIdsRead;
5344
5388
  if (extraFieldUnix) {
5345
- readExtraFieldUnix(extraFieldUnix, directory, false);
5389
+ unixIdsRead = readExtraFieldUnix(extraFieldUnix, directory, false);
5346
5390
  directory.extraFieldUnix = extraFieldUnix;
5347
- } else {
5391
+ }
5392
+ if (!unixIdsRead) {
5348
5393
  const extraFieldInfoZip = extraField.get(EXTRAFIELD_TYPE_INFOZIP);
5349
5394
  if (extraFieldInfoZip) {
5350
5395
  readExtraFieldUnix(extraFieldInfoZip, directory, true);
@@ -5447,7 +5492,7 @@ function readExtraFieldNTFS(extraFieldNTFS, directory) {
5447
5492
  const creationDate = getDateNTFS(rawCreationDate);
5448
5493
  const extraFieldData = { lastModDate, lastAccessDate, creationDate };
5449
5494
  Object.assign(extraFieldNTFS, extraFieldData);
5450
- Object.assign(directory, extraFieldData);
5495
+ Object.assign(directory, extraFieldData, { rawLastAccessDate, rawCreationDate });
5451
5496
  }
5452
5497
  }
5453
5498
 
@@ -5491,6 +5536,7 @@ function readExtraFieldUnix(extraField, directory, isInfoZip) {
5491
5536
  if (gid !== UNDEFINED_VALUE) {
5492
5537
  directory.gid = gid;
5493
5538
  }
5539
+ return uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE;
5494
5540
  } catch {
5495
5541
  // ignored
5496
5542
  }
@@ -5563,26 +5609,25 @@ async function detectOverlappingEntry({
5563
5609
  }
5564
5610
  if (dataDescriptorLength) {
5565
5611
  const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH);
5566
- const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
5567
- getUint32(getDataView(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
5568
- if (dataDescriptorSignature) {
5569
- const readCrc32 = getUint32(getDataView(dataDescriptorArray), 4);
5570
- let readCompressedSize;
5571
- let readUncompressedSize;
5572
- if (extraFieldZip64) {
5573
- readCompressedSize = getBigUint64(getDataView(dataDescriptorArray), 8);
5574
- readUncompressedSize = getBigUint64(getDataView(dataDescriptorArray), 16);
5575
- } else {
5576
- readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
5577
- readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
5578
- }
5579
- const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || readCrc32 == crc32;
5612
+ const dataDescriptorView = getDataView(dataDescriptorArray);
5613
+ let signature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
5614
+ getUint32(dataDescriptorView, 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
5615
+ if (signature) {
5616
+ const signedDataDescriptor = readDataDescriptor(dataDescriptorView, DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH, extraFieldZip64);
5617
+ const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || signedDataDescriptor.crc32 == crc32;
5580
5618
  if (matchCrc32 &&
5581
- readCompressedSize == compressedSize &&
5582
- readUncompressedSize == uncompressedSize) {
5619
+ signedDataDescriptor.compressedSize == compressedSize &&
5620
+ signedDataDescriptor.uncompressedSize == uncompressedSize) {
5583
5621
  dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
5622
+ } else {
5623
+ signature = false;
5584
5624
  }
5585
5625
  }
5626
+ if (dataDescriptorArray.length >= dataDescriptorLength) {
5627
+ const localDataDescriptor = readDataDescriptor(dataDescriptorView, signature ? DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH : 0, extraFieldZip64);
5628
+ localDataDescriptor.signature = signature;
5629
+ fileEntry.localDirectory.dataDescriptor = localDataDescriptor;
5630
+ }
5586
5631
  }
5587
5632
  const range = {
5588
5633
  start: offset,
@@ -5599,6 +5644,20 @@ async function detectOverlappingEntry({
5599
5644
  readRanges.set(index, range);
5600
5645
  }
5601
5646
 
5647
+ function readDataDescriptor(dataDescriptorView, offset, extraFieldZip64) {
5648
+ const crc32 = getUint32(dataDescriptorView, offset);
5649
+ let compressedSize;
5650
+ let uncompressedSize;
5651
+ if (extraFieldZip64) {
5652
+ compressedSize = getBigUint64(dataDescriptorView, offset + 4);
5653
+ uncompressedSize = getBigUint64(dataDescriptorView, offset + 12);
5654
+ } else {
5655
+ compressedSize = getUint32(dataDescriptorView, offset + 4);
5656
+ uncompressedSize = getUint32(dataDescriptorView, offset + 8);
5657
+ }
5658
+ return { crc32, compressedSize, uncompressedSize };
5659
+ }
5660
+
5602
5661
  function getDiskOffset$1(reader, diskNumber) {
5603
5662
  return reader.getDiskOffset ? reader.getDiskOffset(diskNumber) : 0;
5604
5663
  }
@@ -5607,14 +5666,40 @@ function isStrictnessValue(value) {
5607
5666
  return value === STRICTNESS_STRICT || value === STRICTNESS_BALANCED || value === STRICTNESS_TOLERANT;
5608
5667
  }
5609
5668
 
5610
- function getStrictness(strictness, checkAmbiguity) {
5611
- if (strictness === UNDEFINED_VALUE) {
5612
- return checkAmbiguity ? STRICTNESS_STRICT : STRICTNESS_BALANCED;
5669
+ function getStrictness(options, inheritedOptions) {
5670
+ return resolveStrictness(options, resolveStrictness(inheritedOptions, STRICTNESS_BALANCED));
5671
+ }
5672
+
5673
+ function resolveStrictness(options, inheritedStrictness) {
5674
+ const strictness = options[OPTION_STRICTNESS];
5675
+ if (strictness !== UNDEFINED_VALUE) {
5676
+ if (!isStrictnessValue(strictness)) {
5677
+ throw new Error(ERR_INVALID_STRICTNESS);
5678
+ }
5679
+ return strictness;
5680
+ }
5681
+ const checkAmbiguity = options[OPTION_CHECK_AMBIGUITY];
5682
+ if (checkAmbiguity === UNDEFINED_VALUE) {
5683
+ return inheritedStrictness;
5684
+ }
5685
+ if (checkAmbiguity) {
5686
+ return STRICTNESS_STRICT;
5687
+ }
5688
+ return inheritedStrictness == STRICTNESS_TOLERANT ? STRICTNESS_TOLERANT : STRICTNESS_BALANCED;
5689
+ }
5690
+
5691
+ function getCheckLocalDirectory(checkLocalDirectory, strictness) {
5692
+ if (checkLocalDirectory === UNDEFINED_VALUE) {
5693
+ return strictness != STRICTNESS_TOLERANT;
5613
5694
  }
5614
- if (!isStrictnessValue(strictness)) {
5615
- throw new Error(ERR_INVALID_STRICTNESS);
5695
+ return Boolean(checkLocalDirectory);
5696
+ }
5697
+
5698
+ function getCheckLocalFilename(checkLocalFilename, strictness) {
5699
+ if (checkLocalFilename === UNDEFINED_VALUE) {
5700
+ return strictness == STRICTNESS_STRICT;
5616
5701
  }
5617
- return strictness;
5702
+ return Boolean(checkLocalFilename);
5618
5703
  }
5619
5704
 
5620
5705
  function getFilenameValidation(filenameValidation, strictness) {
@@ -5762,10 +5847,11 @@ async function readSignature(reader, view, anchoredOffset, signatureOffset, size
5762
5847
  return UNDEFINED_VALUE;
5763
5848
  }
5764
5849
 
5765
- function checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename) {
5850
+ function validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename) {
5766
5851
  const { rawFilename } = zipEntry;
5767
- if (rawLocalFilename.length != rawFilename.length ||
5768
- rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte])) {
5852
+ if (checkLocalFilename &&
5853
+ (rawLocalFilename.length != rawFilename.length ||
5854
+ rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte]))) {
5769
5855
  throwAmbiguousArchive("mismatched local file header (filename)");
5770
5856
  }
5771
5857
  if ((localDirectory.rawBitFlag & BITFLAG_AMBIGUITY_MASK) != (zipEntry.rawBitFlag & BITFLAG_AMBIGUITY_MASK)) {
@@ -5883,6 +5969,7 @@ var zipReader = /*#__PURE__*/Object.freeze({
5883
5969
 
5884
5970
  const ERR_DUPLICATED_NAME = "File already exists";
5885
5971
  const ERR_INVALID_COMMENT = "Zip file comment exceeds 64KB";
5972
+ const ERR_INVALID_COMMENT_TYPE = "Invalid zip file comment (must be a Uint8Array)";
5886
5973
  const ERR_INVALID_ENTRY_COMMENT = "File entry comment exceeds 64KB";
5887
5974
  const ERR_INVALID_ENTRY_NAME = "File entry name exceeds 64KB";
5888
5975
  const ERR_INVALID_VERSION = "Version exceeds 65535";
@@ -5951,6 +6038,10 @@ class ZipWriter {
5951
6038
  }
5952
6039
  reader = new GenericReader(reader);
5953
6040
  await initStream(reader);
6041
+ if (reader.size === UNDEFINED_VALUE || !reader.readUint8Array) {
6042
+ reader = new BlobReader(await streamToBlob(reader.readable));
6043
+ await initStream(reader);
6044
+ }
5954
6045
  const { ZipReader } = await Promise.resolve().then(function () { return zipReader; });
5955
6046
  const zipReader$1 = new ZipReader(reader.readable);
5956
6047
  const entries = await zipReader$1.getEntries();
@@ -6099,6 +6190,9 @@ class ZipWriter {
6099
6190
  const zipWriter = this;
6100
6191
  const { pendingAddFileCalls, writer } = this;
6101
6192
  const { writable } = writer;
6193
+ if (!(comment instanceof Uint8Array)) {
6194
+ throw new Error(ERR_INVALID_COMMENT_TYPE);
6195
+ }
6102
6196
  if (getLength(comment) > MAX_16_BITS) {
6103
6197
  throw new Error(ERR_INVALID_COMMENT);
6104
6198
  }
@@ -6195,8 +6289,6 @@ async function addFile(zipWriter, name, reader, options) {
6195
6289
  const diskOffset = getDiskOffset(zipWriter.writer);
6196
6290
  const diskNumber = getDiskNumber(zipWriter.writer);
6197
6291
  options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
6198
- internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
6199
- externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
6200
6292
  signature: options[PROPERTY_NAME_SIGNATURE],
6201
6293
  crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
6202
6294
  offset: zipWriter.offset - diskOffset,
@@ -6210,14 +6302,20 @@ async function addFile(zipWriter, name, reader, options) {
6210
6302
  zipWriter.files.delete(name);
6211
6303
  throw error;
6212
6304
  }
6213
- Object.assign(fileEntry, { name, comment, extraField });
6305
+ Object.assign(fileEntry, {
6306
+ name,
6307
+ comment,
6308
+ extraField,
6309
+ [PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES]: fileEntry.internalFileAttributes,
6310
+ [PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES]: fileEntry.externalFileAttributes
6311
+ });
6214
6312
  return new Entry(fileEntry);
6215
6313
  }
6216
6314
 
6217
6315
  function resolveAttributes(zipWriter, name, options) {
6218
6316
  name = name.trim();
6219
6317
  let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
6220
- let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
6318
+ let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? VERSION_MADE_BY_MSDOS : VERSION_MADE_BY_UNIX);
6221
6319
  const executable = getOptionValue(zipWriter, options, PROPERTY_NAME_EXECUTABLE);
6222
6320
  const uid = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_UID);
6223
6321
  const gid = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_GID);
@@ -6251,7 +6349,7 @@ function resolveAttributes(zipWriter, name, options) {
6251
6349
  const hasMsDosProvided = msdosAttributesRaw !== UNDEFINED_VALUE || msdosAttributes !== UNDEFINED_VALUE;
6252
6350
  if (hasUnixMetadata) {
6253
6351
  msDosCompatible = false;
6254
- versionMadeBy = (versionMadeBy & MAX_16_BITS) | (3 << 8);
6352
+ versionMadeBy = (versionMadeBy & MAX_8_BITS) | VERSION_MADE_BY_UNIX;
6255
6353
  } else if (hasMsDosProvided) {
6256
6354
  msDosCompatible = true;
6257
6355
  versionMadeBy = (versionMadeBy & MAX_8_BITS);
@@ -6291,11 +6389,10 @@ function resolveAttributes(zipWriter, name, options) {
6291
6389
  externalFileAttributes = FILE_ATTR_UNIX_DEFAULT_MASK << 16;
6292
6390
  }
6293
6391
  }
6294
- let unixExternalUpper;
6295
6392
  if (!msDosCompatible) {
6296
6393
  const unixModeProvided = unixMode !== UNDEFINED_VALUE || Boolean(setuid || setgid || sticky);
6297
- unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
6298
- unixMode = unixMode === UNDEFINED_VALUE ? unixExternalUpper : (unixMode & MAX_16_BITS);
6394
+ const defaultUnixMode = (externalFileAttributes >> 16) & MAX_16_BITS;
6395
+ unixMode = unixMode === UNDEFINED_VALUE ? defaultUnixMode : (unixMode & MAX_16_BITS);
6299
6396
  if (setuid) {
6300
6397
  unixMode |= FILE_ATTR_UNIX_SETUID_MASK;
6301
6398
  } else {
@@ -6324,17 +6421,20 @@ function resolveAttributes(zipWriter, name, options) {
6324
6421
  if (hasMsDosProvided) {
6325
6422
  externalFileAttributes = (externalFileAttributes & MAX_32_BITS) | (msdosAttributesRaw & MAX_8_BITS);
6326
6423
  }
6424
+ const unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
6425
+ const symlink = unixMode !== UNDEFINED_VALUE && ((unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_SYMLINK);
6327
6426
  return {
6328
6427
  name,
6329
6428
  resolvedOptions: {
6330
6429
  versionMadeBy,
6331
- msDosCompatible,
6430
+ msDosCompatible: Boolean(msDosCompatible),
6332
6431
  externalFileAttributes,
6333
6432
  unixExternalUpper,
6334
6433
  uid,
6335
6434
  gid,
6336
6435
  unixMode,
6337
6436
  unixExtraFieldType,
6437
+ symlink,
6338
6438
  setuid,
6339
6439
  setgid,
6340
6440
  sticky,
@@ -6567,6 +6667,9 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
6567
6667
  if (writerOptions[OPTION_SIGN_CENTRAL_DIRECTORY]) {
6568
6668
  throw new Error(ERR_UNDETERMINED_SIZE);
6569
6669
  }
6670
+ if (comment !== UNDEFINED_VALUE && !(comment instanceof Uint8Array)) {
6671
+ throw new Error(ERR_INVALID_COMMENT_TYPE);
6672
+ }
6570
6673
  const commentLength = getLength(comment);
6571
6674
  if (commentLength > MAX_16_BITS) {
6572
6675
  throw new Error(ERR_INVALID_COMMENT);
@@ -6848,6 +6951,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
6848
6951
  uid,
6849
6952
  gid,
6850
6953
  unixMode,
6954
+ symlink,
6851
6955
  setuid,
6852
6956
  setgid,
6853
6957
  sticky,
@@ -6884,6 +6988,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
6884
6988
  uid,
6885
6989
  gid,
6886
6990
  unixMode,
6991
+ symlink: Boolean(symlink),
6887
6992
  setuid,
6888
6993
  setgid,
6889
6994
  sticky,
@@ -6964,8 +7069,8 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
6964
7069
  rawLastModDate,
6965
7070
  creationDate,
6966
7071
  lastAccessDate,
6967
- encrypted,
6968
- zipCrypto,
7072
+ encrypted: Boolean(encrypted),
7073
+ zipCrypto: Boolean(zipCrypto),
6969
7074
  size: metadataSize + compressedSize,
6970
7075
  compressionMethod,
6971
7076
  version,
@@ -10107,6 +10212,7 @@ exports.ERR_INVALID_AUTHENTICATION_CODE = ERR_INVALID_AUTHENTICATION_CODE;
10107
10212
  exports.ERR_INVALID_CODEC_DEFINITION = ERR_INVALID_CODEC_DEFINITION;
10108
10213
  exports.ERR_INVALID_CODEC_MODULE = ERR_INVALID_CODEC_MODULE;
10109
10214
  exports.ERR_INVALID_COMMENT = ERR_INVALID_COMMENT;
10215
+ exports.ERR_INVALID_COMMENT_TYPE = ERR_INVALID_COMMENT_TYPE;
10110
10216
  exports.ERR_INVALID_COMPRESSED_DATA = ERR_INVALID_COMPRESSED_DATA;
10111
10217
  exports.ERR_INVALID_CRC32 = ERR_INVALID_CRC32;
10112
10218
  exports.ERR_INVALID_ENCRYPTION_STRENGTH = ERR_INVALID_ENCRYPTION_STRENGTH;