@zip.js/zip.js 2.8.6 → 2.8.8

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.
@@ -36,6 +36,7 @@
36
36
 
37
37
  const MAX_32_BITS = 0xffffffff;
38
38
  const MAX_16_BITS = 0xffff;
39
+ const MAX_8_BITS = 0xff;
39
40
  const COMPRESSION_METHOD_DEFLATE = 0x08;
40
41
  const COMPRESSION_METHOD_DEFLATE_64 = 0x09;
41
42
  const COMPRESSION_METHOD_STORE = 0x00;
@@ -65,6 +66,8 @@
65
66
  const EXTRAFIELD_TYPE_UNICODE_PATH = 0x7075;
66
67
  const EXTRAFIELD_TYPE_UNICODE_COMMENT = 0x6375;
67
68
  const EXTRAFIELD_TYPE_USDZ = 0x1986;
69
+ const EXTRAFIELD_TYPE_INFOZIP = 0x7875;
70
+ const EXTRAFIELD_TYPE_UNIX = 0x7855;
68
71
 
69
72
  const BITFLAG_ENCRYPTED = 0b1;
70
73
  const BITFLAG_LEVEL = 0b0110;
@@ -74,10 +77,17 @@
74
77
  const BITFLAG_DATA_DESCRIPTOR = 0b1000;
75
78
  const BITFLAG_LANG_ENCODING_FLAG = 0b100000000000;
76
79
  const FILE_ATTR_MSDOS_DIR_MASK = 0b10000;
80
+ const FILE_ATTR_MSDOS_READONLY_MASK = 0x01;
81
+ const FILE_ATTR_MSDOS_HIDDEN_MASK = 0x02;
82
+ const FILE_ATTR_MSDOS_SYSTEM_MASK = 0x04;
83
+ const FILE_ATTR_MSDOS_ARCHIVE_MASK = 0x20;
77
84
  const FILE_ATTR_UNIX_TYPE_MASK = 0o170000;
78
85
  const FILE_ATTR_UNIX_TYPE_DIR = 0o040000;
79
86
  const FILE_ATTR_UNIX_EXECUTABLE_MASK = 0o111;
80
87
  const FILE_ATTR_UNIX_DEFAULT_MASK = 0o644;
88
+ const FILE_ATTR_UNIX_SETUID_MASK = 0o4000;
89
+ const FILE_ATTR_UNIX_SETGID_MASK = 0o2000;
90
+ const FILE_ATTR_UNIX_STICKY_MASK = 0o1000;
81
91
 
82
92
  const VERSION_DEFLATE = 0x14;
83
93
  const VERSION_ZIP64 = 0x2D;
@@ -96,6 +106,7 @@
96
106
  const UNDEFINED_VALUE = undefined;
97
107
  const UNDEFINED_TYPE = "undefined";
98
108
  const FUNCTION_TYPE = "function";
109
+ const OBJECT_TYPE = "object";
99
110
 
100
111
  /*
101
112
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
@@ -201,6 +212,7 @@
201
212
  const HTTP_METHOD_GET = "GET";
202
213
  const HTTP_RANGE_UNIT = "bytes";
203
214
  const DEFAULT_CHUNK_SIZE = 64 * 1024;
215
+ const DEFAULT_BUFFER_SIZE = 256 * 1024;
204
216
 
205
217
  const PROPERTY_NAME_WRITABLE = "writable";
206
218
 
@@ -685,19 +697,29 @@
685
697
 
686
698
  class Uint8ArrayWriter extends Writer {
687
699
 
700
+ constructor(defaultBufferSize) {
701
+ super();
702
+ this.defaultBufferSize = defaultBufferSize || DEFAULT_BUFFER_SIZE;
703
+ }
704
+
688
705
  init(initSize = 0) {
689
706
  Object.assign(this, {
690
707
  offset: 0,
691
- array: new Uint8Array(initSize)
708
+ array: new Uint8Array(initSize > 0 ? initSize : this.defaultBufferSize)
692
709
  });
693
710
  super.init();
694
711
  }
695
712
 
696
713
  writeUint8Array(array) {
697
714
  const writer = this;
698
- if (writer.offset + array.length > writer.array.length) {
715
+ const requiredLength = writer.offset + array.length;
716
+ if (requiredLength > writer.array.length) {
717
+ let newLength = writer.array.length ? writer.array.length * 2 : writer.defaultBufferSize;
718
+ while (newLength < requiredLength) {
719
+ newLength *= 2;
720
+ }
699
721
  const previousArray = writer.array;
700
- writer.array = new Uint8Array(previousArray.length + array.length);
722
+ writer.array = new Uint8Array(newLength);
701
723
  writer.array.set(previousArray);
702
724
  }
703
725
  writer.array.set(array, writer.offset);
@@ -705,7 +727,11 @@
705
727
  }
706
728
 
707
729
  getData() {
708
- return this.array;
730
+ if (this.offset === this.array.length) {
731
+ return this.array;
732
+ } else {
733
+ return this.array.slice(0, this.offset);
734
+ }
709
735
  }
710
736
  }
711
737
 
@@ -2892,13 +2918,8 @@
2892
2918
  const { value, readable, writable } = message;
2893
2919
  const transferables = [];
2894
2920
  if (value) {
2895
- if (value.byteLength < value.buffer.byteLength) {
2896
- message.value = value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength);
2897
- }
2898
- else {
2899
- message.value = value.buffer;
2900
- }
2901
- transferables.push(message.value);
2921
+ message.value = value;
2922
+ transferables.push(message.value.buffer);
2902
2923
  }
2903
2924
  if (transferStreams && transferStreamsSupported) {
2904
2925
  if (readable) {
@@ -3199,6 +3220,8 @@
3199
3220
  const PROPERTY_NAME_RAW_CREATION_DATE = "rawCreationDate";
3200
3221
  const PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES = "internalFileAttributes";
3201
3222
  const PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES = "externalFileAttributes";
3223
+ const PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW = "msdosAttributesRaw";
3224
+ const PROPERTY_NAME_MSDOS_ATTRIBUTES = "msdosAttributes";
3202
3225
  const PROPERTY_NAME_MS_DOS_COMPATIBLE = "msDosCompatible";
3203
3226
  const PROPERTY_NAME_ZIP64 = "zip64";
3204
3227
  const PROPERTY_NAME_ENCRYPTED = "encrypted";
@@ -3210,17 +3233,73 @@
3210
3233
  const PROPERTY_NAME_COMPRESSION_METHOD = "compressionMethod";
3211
3234
  const PROPERTY_NAME_SIGNATURE = "signature";
3212
3235
  const PROPERTY_NAME_EXTRA_FIELD = "extraField";
3236
+ const PROPERTY_NAME_EXTRA_FIELD_INFOZIP = "extraFieldInfoZip";
3237
+ const PROPERTY_NAME_EXTRA_FIELD_UNIX = "extraFieldUnix";
3238
+ const PROPERTY_NAME_UID = "uid";
3239
+ const PROPERTY_NAME_GID = "gid";
3240
+ const PROPERTY_NAME_UNIX_MODE = "unixMode";
3241
+ const PROPERTY_NAME_SETUID = "setuid";
3242
+ const PROPERTY_NAME_SETGID = "setgid";
3243
+ const PROPERTY_NAME_STICKY = "sticky";
3244
+ const PROPERTY_NAME_BITFLAG = "bitFlag";
3245
+ const PROPERTY_NAME_FILENAME_UTF8 = "filenameUTF8";
3246
+ const PROPERTY_NAME_COMMENT_UTF8 = "commentUTF8";
3247
+ const PROPERTY_NAME_RAW_EXTRA_FIELD = "rawExtraField";
3248
+ const PROPERTY_NAME_EXTRA_FIELD_ZIP64 = "extraFieldZip64";
3249
+ const PROPERTY_NAME_EXTRA_FIELD_UNICODE_PATH = "extraFieldUnicodePath";
3250
+ const PROPERTY_NAME_EXTRA_FIELD_UNICODE_COMMENT = "extraFieldUnicodeComment";
3251
+ const PROPERTY_NAME_EXTRA_FIELD_AES = "extraFieldAES";
3252
+ const PROPERTY_NAME_EXTRA_FIELD_NTFS = "extraFieldNTFS";
3253
+ const PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP = "extraFieldExtendedTimestamp";
3213
3254
 
3214
3255
  const PROPERTY_NAMES = [
3215
- PROPERTY_NAME_FILENAME, PROPERTY_NAME_RAW_FILENAME, PROPERTY_NAME_COMPRESSED_SIZE, PROPERTY_NAME_UNCOMPRESSED_SIZE,
3216
- PROPERTY_NAME_LAST_MODIFICATION_DATE, PROPERTY_NAME_RAW_LAST_MODIFICATION_DATE, PROPERTY_NAME_COMMENT, PROPERTY_NAME_RAW_COMMENT,
3217
- PROPERTY_NAME_LAST_ACCESS_DATE, PROPERTY_NAME_CREATION_DATE, PROPERTY_NAME_OFFSET, PROPERTY_NAME_DISK_NUMBER_START,
3218
- PROPERTY_NAME_DISK_NUMBER_START, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES,
3219
- PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES, PROPERTY_NAME_MS_DOS_COMPATIBLE, PROPERTY_NAME_ZIP64,
3220
- PROPERTY_NAME_ENCRYPTED, PROPERTY_NAME_VERSION, PROPERTY_NAME_VERSION_MADE_BY, PROPERTY_NAME_ZIPCRYPTO, PROPERTY_NAME_DIRECTORY,
3221
- PROPERTY_NAME_EXECUTABLE, PROPERTY_NAME_COMPRESSION_METHOD, PROPERTY_NAME_SIGNATURE, PROPERTY_NAME_EXTRA_FIELD,
3222
- "bitFlag", "filenameUTF8", "commentUTF8", "rawExtraField", "extraFieldZip64", "extraFieldUnicodePath", "extraFieldUnicodeComment",
3223
- "extraFieldAES", "extraFieldNTFS", "extraFieldExtendedTimestamp"];
3256
+ PROPERTY_NAME_FILENAME,
3257
+ PROPERTY_NAME_RAW_FILENAME,
3258
+ PROPERTY_NAME_UNCOMPRESSED_SIZE,
3259
+ PROPERTY_NAME_COMPRESSED_SIZE,
3260
+ PROPERTY_NAME_LAST_MODIFICATION_DATE,
3261
+ PROPERTY_NAME_RAW_LAST_MODIFICATION_DATE,
3262
+ PROPERTY_NAME_COMMENT,
3263
+ PROPERTY_NAME_RAW_COMMENT,
3264
+ PROPERTY_NAME_LAST_ACCESS_DATE,
3265
+ PROPERTY_NAME_CREATION_DATE,
3266
+ PROPERTY_NAME_RAW_CREATION_DATE,
3267
+ PROPERTY_NAME_OFFSET,
3268
+ PROPERTY_NAME_DISK_NUMBER_START,
3269
+ PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES,
3270
+ PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES,
3271
+ PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW,
3272
+ PROPERTY_NAME_MSDOS_ATTRIBUTES,
3273
+ PROPERTY_NAME_MS_DOS_COMPATIBLE,
3274
+ PROPERTY_NAME_ZIP64,
3275
+ PROPERTY_NAME_ENCRYPTED,
3276
+ PROPERTY_NAME_VERSION,
3277
+ PROPERTY_NAME_VERSION_MADE_BY,
3278
+ PROPERTY_NAME_ZIPCRYPTO,
3279
+ PROPERTY_NAME_DIRECTORY,
3280
+ PROPERTY_NAME_EXECUTABLE,
3281
+ PROPERTY_NAME_COMPRESSION_METHOD,
3282
+ PROPERTY_NAME_SIGNATURE,
3283
+ PROPERTY_NAME_EXTRA_FIELD,
3284
+ PROPERTY_NAME_EXTRA_FIELD_UNIX,
3285
+ PROPERTY_NAME_EXTRA_FIELD_INFOZIP,
3286
+ PROPERTY_NAME_UID,
3287
+ PROPERTY_NAME_GID,
3288
+ PROPERTY_NAME_UNIX_MODE,
3289
+ PROPERTY_NAME_SETUID,
3290
+ PROPERTY_NAME_SETGID,
3291
+ PROPERTY_NAME_STICKY,
3292
+ PROPERTY_NAME_BITFLAG,
3293
+ PROPERTY_NAME_FILENAME_UTF8,
3294
+ PROPERTY_NAME_COMMENT_UTF8,
3295
+ PROPERTY_NAME_RAW_EXTRA_FIELD,
3296
+ PROPERTY_NAME_EXTRA_FIELD_ZIP64,
3297
+ PROPERTY_NAME_EXTRA_FIELD_UNICODE_PATH,
3298
+ PROPERTY_NAME_EXTRA_FIELD_UNICODE_COMMENT,
3299
+ PROPERTY_NAME_EXTRA_FIELD_AES,
3300
+ PROPERTY_NAME_EXTRA_FIELD_NTFS,
3301
+ PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP
3302
+ ];
3224
3303
 
3225
3304
  class Entry {
3226
3305
 
@@ -3287,6 +3366,7 @@
3287
3366
  const OPTION_ENCODE_TEXT = "encodeText";
3288
3367
  const OPTION_OFFSET = "offset";
3289
3368
  const OPTION_USDZ = "usdz";
3369
+ const OPTION_UNIX_EXTRA_FIELD_TYPE = "unixExtraFieldType";
3290
3370
 
3291
3371
  /*
3292
3372
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
@@ -3329,6 +3409,7 @@
3329
3409
  const ERR_SPLIT_ZIP_FILE = "Split zip file";
3330
3410
  const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
3331
3411
  const CHARSET_UTF8 = "utf-8";
3412
+ const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
3332
3413
  const CHARSET_CP437 = "cp437";
3333
3414
  const ZIP64_PROPERTIES = [
3334
3415
  [PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
@@ -3484,51 +3565,71 @@
3484
3565
  const filenameUTF8 = languageEncodingFlag;
3485
3566
  const commentUTF8 = languageEncodingFlag;
3486
3567
  const externalFileAttributes = getUint32(directoryView, offset + 38);
3487
- const directory =
3488
- (msDosCompatible && ((getUint8(directoryView, offset + 38) & FILE_ATTR_MSDOS_DIR_MASK) == FILE_ATTR_MSDOS_DIR_MASK)) ||
3489
- (unixCompatible && (((externalFileAttributes >> 16) & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR)) ||
3490
- (rawFilename.length && rawFilename.at(-1) == DIRECTORY_SIGNATURE.charCodeAt(0));
3491
- const executable = (unixCompatible && (((externalFileAttributes >> 16) & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0));
3568
+ const msdosAttributesRaw = externalFileAttributes & MAX_8_BITS;
3569
+ const msdosAttributes = {
3570
+ readOnly: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_READONLY_MASK),
3571
+ hidden: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_HIDDEN_MASK),
3572
+ system: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_SYSTEM_MASK),
3573
+ directory: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_DIR_MASK),
3574
+ archive: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_ARCHIVE_MASK)
3575
+ };
3492
3576
  const offsetFileEntry = getUint32(directoryView, offset + 42) + prependedDataLength;
3577
+ const decode = getOptionValue$1(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
3578
+ const rawFilenameEncoding = filenameUTF8 ? CHARSET_UTF8 : filenameEncoding || CHARSET_CP437;
3579
+ const rawCommentEncoding = commentUTF8 ? CHARSET_UTF8 : commentEncoding || CHARSET_CP437;
3580
+ let filename = decode(rawFilename, rawFilenameEncoding);
3581
+ if (filename === UNDEFINED_VALUE) {
3582
+ filename = decodeText(rawFilename, rawFilenameEncoding);
3583
+ }
3584
+ let comment = decode(rawComment, rawCommentEncoding);
3585
+ if (comment === UNDEFINED_VALUE) {
3586
+ comment = decodeText(rawComment, rawCommentEncoding);
3587
+ }
3493
3588
  Object.assign(fileEntry, {
3494
3589
  versionMadeBy,
3495
3590
  msDosCompatible,
3496
3591
  compressedSize: 0,
3497
3592
  uncompressedSize: 0,
3498
3593
  commentLength,
3499
- directory,
3500
3594
  offset: offsetFileEntry,
3501
3595
  diskNumberStart: getUint16(directoryView, offset + 34),
3502
3596
  internalFileAttributes: getUint16(directoryView, offset + 36),
3503
3597
  externalFileAttributes,
3598
+ msdosAttributesRaw,
3599
+ msdosAttributes,
3504
3600
  rawFilename,
3505
3601
  filenameUTF8,
3506
3602
  commentUTF8,
3507
3603
  rawExtraField: directoryArray.subarray(extraFieldOffset, commentOffset),
3508
- executable
3509
- });
3510
- fileEntry.internalFileAttribute = fileEntry.internalFileAttributes;
3511
- fileEntry.externalFileAttribute = fileEntry.externalFileAttributes;
3512
- const decode = getOptionValue$1(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
3513
- const rawFilenameEncoding = filenameUTF8 ? CHARSET_UTF8 : filenameEncoding || CHARSET_CP437;
3514
- const rawCommentEncoding = commentUTF8 ? CHARSET_UTF8 : commentEncoding || CHARSET_CP437;
3515
- let filename = decode(rawFilename, rawFilenameEncoding);
3516
- if (filename === UNDEFINED_VALUE) {
3517
- filename = decodeText(rawFilename, rawFilenameEncoding);
3518
- }
3519
- let comment = decode(rawComment, rawCommentEncoding);
3520
- if (comment === UNDEFINED_VALUE) {
3521
- comment = decodeText(rawComment, rawCommentEncoding);
3522
- }
3523
- Object.assign(fileEntry, {
3524
3604
  rawComment,
3525
3605
  filename,
3526
- comment,
3527
- directory: directory || filename.endsWith(DIRECTORY_SIGNATURE)
3606
+ comment
3528
3607
  });
3529
3608
  startOffset = Math.max(offsetFileEntry, startOffset);
3530
3609
  readCommonFooter(fileEntry, fileEntry, directoryView, offset + 6);
3531
- fileEntry.zipCrypto = fileEntry.encrypted && !fileEntry.extraFieldAES;
3610
+ const unixExternalUpper = (fileEntry.externalFileAttributes >> 16) & MAX_16_BITS;
3611
+ if (fileEntry.unixMode === UNDEFINED_VALUE && (unixExternalUpper & (FILE_ATTR_UNIX_DEFAULT_MASK | FILE_ATTR_UNIX_EXECUTABLE_MASK | FILE_ATTR_UNIX_TYPE_DIR)) != 0) {
3612
+ fileEntry.unixMode = unixExternalUpper;
3613
+ }
3614
+ const setuid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETUID_MASK);
3615
+ const setgid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETGID_MASK);
3616
+ const sticky = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_STICKY_MASK);
3617
+ const executable = (fileEntry.unixMode !== UNDEFINED_VALUE)
3618
+ ? ((fileEntry.unixMode & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)
3619
+ : (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0));
3620
+ const modeIsDir = fileEntry.unixMode !== UNDEFINED_VALUE && ((fileEntry.unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
3621
+ const upperIsDir = ((unixExternalUpper & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
3622
+ Object.assign(fileEntry, {
3623
+ setuid,
3624
+ setgid,
3625
+ sticky,
3626
+ unixExternalUpper,
3627
+ internalFileAttribute: fileEntry.internalFileAttributes,
3628
+ externalFileAttribute: fileEntry.externalFileAttributes,
3629
+ executable,
3630
+ directory: modeIsDir || upperIsDir || (msDosCompatible && msdosAttributes.directory) || (filename.endsWith(DIRECTORY_SIGNATURE) && !fileEntry.uncompressedSize),
3631
+ zipCrypto: fileEntry.encrypted && !fileEntry.extraFieldAES
3632
+ });
3532
3633
  const entry = new Entry(fileEntry);
3533
3634
  entry.getData = (writer, options) => fileEntry.getData(writer, entry, zipReader.readRanges, options);
3534
3635
  entry.arrayBuffer = async options => {
@@ -3674,7 +3775,7 @@
3674
3775
  zipCrypto,
3675
3776
  encryptionStrength: extraFieldAES && extraFieldAES.strength,
3676
3777
  signed: getOptionValue$1(zipEntry, options, OPTION_CHECK_SIGNATURE) && !passThrough,
3677
- passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & 0xFF) : ((signature >>> 24) & 0xFF)),
3778
+ passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((signature >>> 24) & MAX_8_BITS)),
3678
3779
  outputSize: passThrough ? compressedSize : uncompressedSize,
3679
3780
  signature,
3680
3781
  compressed: compressionMethod != 0 && !passThrough,
@@ -3805,6 +3906,17 @@
3805
3906
  readExtraFieldNTFS(extraFieldNTFS, directory);
3806
3907
  directory.extraFieldNTFS = extraFieldNTFS;
3807
3908
  }
3909
+ const extraFieldUnix = extraField.get(EXTRAFIELD_TYPE_UNIX);
3910
+ if (extraFieldUnix) {
3911
+ readExtraFieldUnix(extraFieldUnix, directory, false);
3912
+ directory.extraFieldUnix = extraFieldUnix;
3913
+ } else {
3914
+ const extraFieldInfoZip = extraField.get(EXTRAFIELD_TYPE_INFOZIP);
3915
+ if (extraFieldInfoZip) {
3916
+ readExtraFieldUnix(extraFieldInfoZip, directory, true);
3917
+ directory.extraFieldInfoZip = extraFieldInfoZip;
3918
+ }
3919
+ }
3808
3920
  const extraFieldExtendedTimestamp = extraField.get(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
3809
3921
  if (extraFieldExtendedTimestamp) {
3810
3922
  readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory, localDirectory);
@@ -3846,7 +3958,7 @@
3846
3958
  });
3847
3959
  if (extraFieldUnicode.valid) {
3848
3960
  directory[propertyName] = extraFieldUnicode[propertyName];
3849
- directory[propertyName + "UTF8"] = true;
3961
+ directory[propertyName + PROPERTY_NAME_UTF8_SUFFIX] = true;
3850
3962
  }
3851
3963
  }
3852
3964
 
@@ -3902,6 +4014,47 @@
3902
4014
  }
3903
4015
  }
3904
4016
 
4017
+ function readExtraFieldUnix(extraField, directory, isInfoZip) {
4018
+ try {
4019
+ const view = getDataView$1(new Uint8Array(extraField.data));
4020
+ let offset = 0;
4021
+ const version = getUint8(view, offset++);
4022
+ const uidSize = getUint8(view, offset++);
4023
+ const uidBytes = extraField.data.subarray(offset, offset + uidSize);
4024
+ offset += uidSize;
4025
+ const uid = unpackUnixId(uidBytes);
4026
+ const gidSize = getUint8(view, offset++);
4027
+ const gidBytes = extraField.data.subarray(offset, offset + gidSize);
4028
+ offset += gidSize;
4029
+ const gid = unpackUnixId(gidBytes);
4030
+ let unixMode = UNDEFINED_VALUE;
4031
+ if (!isInfoZip && offset + 2 <= extraField.data.length) {
4032
+ const base = extraField.data;
4033
+ const modeView = new DataView(base.buffer, base.byteOffset + offset, 2);
4034
+ unixMode = modeView.getUint16(0, true);
4035
+ }
4036
+ Object.assign(extraField, { version, uid, gid, unixMode });
4037
+ if (uid !== UNDEFINED_VALUE) {
4038
+ directory.uid = uid;
4039
+ }
4040
+ if (gid !== UNDEFINED_VALUE) {
4041
+ directory.gid = gid;
4042
+ }
4043
+ if (unixMode !== UNDEFINED_VALUE) {
4044
+ directory.unixMode = unixMode;
4045
+ }
4046
+ } catch {
4047
+ // ignored
4048
+ }
4049
+ }
4050
+
4051
+ function unpackUnixId(bytes) {
4052
+ const buffer = new Uint8Array(4);
4053
+ buffer.set(bytes, 0);
4054
+ const view = new DataView(buffer.buffer, buffer.byteOffset, 4);
4055
+ return view.getUint32(0, true);
4056
+ }
4057
+
3905
4058
  function readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory, localDirectory) {
3906
4059
  const extraFieldView = getDataView$1(extraFieldExtendedTimestamp.data);
3907
4060
  const flags = getUint8(extraFieldView, 0);
@@ -4028,7 +4181,7 @@
4028
4181
  }
4029
4182
 
4030
4183
  function getDate(timeRaw) {
4031
- const date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & 0x0000ffff;
4184
+ const date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & MAX_16_BITS;
4032
4185
  try {
4033
4186
  return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
4034
4187
  } catch {
@@ -4104,8 +4257,16 @@
4104
4257
  const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (make sure 'keepOrder' is set to 'true')";
4105
4258
  const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
4106
4259
  const ERR_ZIP_NOT_EMPTY = "Zip file not empty";
4260
+ const ERR_INVALID_UID = "Invalid uid (must be integer 0..2^32-1)";
4261
+ const ERR_INVALID_GID = "Invalid gid (must be integer 0..2^32-1)";
4262
+ const ERR_INVALID_UNIX_MODE = "Invalid UNIX mode (must be integer 0..65535)";
4263
+ const ERR_INVALID_UNIX_EXTRA_FIELD_TYPE = "Invalid unixExtraFieldType (must be 'infozip' or 'unix')";
4264
+ const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be integer 0..255)";
4265
+ const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
4107
4266
 
4108
4267
  const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
4268
+ const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
4269
+ const UNIX_EXTRA_FIELD_TYPE = "unix";
4109
4270
 
4110
4271
  let workers = 0;
4111
4272
  const pendingEntries = [];
@@ -4163,15 +4324,17 @@
4163
4324
  rawExtraFieldAES,
4164
4325
  rawExtraFieldExtendedTimestamp,
4165
4326
  rawExtraFieldNTFS,
4166
- rawExtraField
4327
+ rawExtraFieldUnix,
4328
+ rawExtraField,
4167
4329
  } = entry;
4168
4330
  const { level, languageEncodingFlag, dataDescriptor } = bitFlag;
4169
4331
  rawExtraFieldZip64 = rawExtraFieldZip64 || new Uint8Array();
4170
4332
  rawExtraFieldAES = rawExtraFieldAES || new Uint8Array();
4171
4333
  rawExtraFieldExtendedTimestamp = rawExtraFieldExtendedTimestamp || new Uint8Array();
4172
4334
  rawExtraFieldNTFS = rawExtraFieldNTFS || new Uint8Array();
4335
+ rawExtraFieldUnix = entry.rawExtraFieldUnix || new Uint8Array();
4173
4336
  rawExtraField = rawExtraField || new Uint8Array();
4174
- const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
4337
+ const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
4175
4338
  const zip64UncompressedSize = zip64 && uncompressedSize > MAX_32_BITS;
4176
4339
  const zip64CompressedSize = zip64 && compressedSize > MAX_32_BITS;
4177
4340
  const {
@@ -4198,6 +4361,7 @@
4198
4361
  rawExtraFieldAES,
4199
4362
  rawExtraFieldExtendedTimestamp,
4200
4363
  rawExtraFieldNTFS,
4364
+ rawExtraFieldUnix,
4201
4365
  rawExtraField,
4202
4366
  extendedTimestamp: rawExtraFieldExtendedTimestamp.length > 0 || rawExtraFieldNTFS.length > 0,
4203
4367
  extraFieldExtendedTimestampFlag: 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0),
@@ -4266,7 +4430,7 @@
4266
4430
  while (pendingAddFileCalls.size) {
4267
4431
  await Promise.allSettled(Array.from(pendingAddFileCalls));
4268
4432
  }
4269
- await closeFile(this, comment, options);
4433
+ await closeFile(zipWriter, comment, options);
4270
4434
  const preventClose = getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
4271
4435
  if (!preventClose) {
4272
4436
  await writable.getWriter().close();
@@ -4277,9 +4441,45 @@
4277
4441
 
4278
4442
  async function addFile(zipWriter, name, reader, options) {
4279
4443
  name = name.trim();
4280
- const msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
4281
- const versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
4444
+ let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
4445
+ let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
4282
4446
  const executable = getOptionValue(zipWriter, options, PROPERTY_NAME_EXECUTABLE);
4447
+ const uid = getOptionValue(zipWriter, options, PROPERTY_NAME_UID);
4448
+ const gid = getOptionValue(zipWriter, options, PROPERTY_NAME_GID);
4449
+ let unixMode = getOptionValue(zipWriter, options, PROPERTY_NAME_UNIX_MODE);
4450
+ const unixExtraFieldType = getOptionValue(zipWriter, options, OPTION_UNIX_EXTRA_FIELD_TYPE);
4451
+ let setuid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETUID);
4452
+ let setgid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETGID);
4453
+ let sticky = getOptionValue(zipWriter, options, PROPERTY_NAME_STICKY);
4454
+ if (uid !== UNDEFINED_VALUE && (uid < 0 || uid > MAX_32_BITS)) {
4455
+ throw new Error(ERR_INVALID_UID);
4456
+ }
4457
+ if (gid !== UNDEFINED_VALUE && (gid < 0 || gid > MAX_32_BITS)) {
4458
+ throw new Error(ERR_INVALID_GID);
4459
+ }
4460
+ if (unixMode !== UNDEFINED_VALUE && (unixMode < 0 || unixMode > MAX_16_BITS)) {
4461
+ throw new Error(ERR_INVALID_UNIX_MODE);
4462
+ }
4463
+ if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
4464
+ throw new Error(ERR_INVALID_UNIX_EXTRA_FIELD_TYPE);
4465
+ }
4466
+ let msdosAttributesRaw = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
4467
+ let msdosAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES);
4468
+ const hasUnixMetadata = uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE || unixExtraFieldType;
4469
+ const hasMsDosProvided = msdosAttributesRaw !== UNDEFINED_VALUE || msdosAttributes !== UNDEFINED_VALUE;
4470
+ if (hasUnixMetadata) {
4471
+ msDosCompatible = false;
4472
+ versionMadeBy = (versionMadeBy & MAX_16_BITS) | (3 << 8);
4473
+ } else if (hasMsDosProvided) {
4474
+ msDosCompatible = true;
4475
+ versionMadeBy = (versionMadeBy & MAX_8_BITS);
4476
+ }
4477
+ if (msdosAttributesRaw !== UNDEFINED_VALUE && (msdosAttributesRaw < 0 || msdosAttributesRaw > MAX_8_BITS)) {
4478
+ throw new Error(ERR_INVALID_MSDOS_ATTRIBUTES);
4479
+ }
4480
+ if (msdosAttributes && typeof msdosAttributes !== OBJECT_TYPE) {
4481
+ throw new Error(ERR_INVALID_MSDOS_DATA);
4482
+ }
4283
4483
  if (versionMadeBy > MAX_16_BITS) {
4284
4484
  throw new Error(ERR_INVALID_VERSION);
4285
4485
  }
@@ -4305,6 +4505,34 @@
4305
4505
  externalFileAttributes = FILE_ATTR_UNIX_DEFAULT_MASK << 16;
4306
4506
  }
4307
4507
  }
4508
+ let unixExternalUpper;
4509
+ if (!msDosCompatible) {
4510
+ unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
4511
+ unixMode = unixMode === UNDEFINED_VALUE ? unixExternalUpper : (unixMode & MAX_16_BITS);
4512
+ if (setuid) {
4513
+ unixMode |= FILE_ATTR_UNIX_SETUID_MASK;
4514
+ } else {
4515
+ setuid = Boolean(unixMode & FILE_ATTR_UNIX_SETUID_MASK);
4516
+ }
4517
+ if (setgid) {
4518
+ unixMode |= FILE_ATTR_UNIX_SETGID_MASK;
4519
+ } else {
4520
+ setgid = Boolean(unixMode & FILE_ATTR_UNIX_SETGID_MASK);
4521
+ }
4522
+ if (sticky) {
4523
+ unixMode |= FILE_ATTR_UNIX_STICKY_MASK;
4524
+ } else {
4525
+ sticky = Boolean(unixMode & FILE_ATTR_UNIX_STICKY_MASK);
4526
+ }
4527
+ if (directory) {
4528
+ unixMode |= FILE_ATTR_UNIX_TYPE_DIR;
4529
+ }
4530
+ externalFileAttributes = ((unixMode & MAX_16_BITS) << 16) | (externalFileAttributes & MAX_8_BITS);
4531
+ }
4532
+ ({ msdosAttributesRaw, msdosAttributes } = normalizeMsdosAttributes(msdosAttributesRaw, msdosAttributes));
4533
+ if (hasMsDosProvided) {
4534
+ externalFileAttributes = (externalFileAttributes & MAX_32_BITS) | (msdosAttributesRaw & MAX_8_BITS);
4535
+ }
4308
4536
  const encode = getOptionValue(zipWriter, options, OPTION_ENCODE_TEXT, encodeText);
4309
4537
  let rawFilename = encode(name);
4310
4538
  if (rawFilename === UNDEFINED_VALUE) {
@@ -4467,7 +4695,16 @@
4467
4695
  compressionMethod,
4468
4696
  uncompressedSize,
4469
4697
  offset: zipWriter.offset - diskOffset,
4470
- diskNumberStart: diskNumber
4698
+ diskNumberStart: diskNumber,
4699
+ uid,
4700
+ gid,
4701
+ setuid,
4702
+ setgid,
4703
+ sticky,
4704
+ unixMode,
4705
+ msdosAttributesRaw,
4706
+ msdosAttributes,
4707
+ unixExternalUpper
4471
4708
  });
4472
4709
  const headerInfo = getHeaderInfo(options);
4473
4710
  const dataDescriptorInfo = getDataDescriptorInfo(options);
@@ -4659,7 +4896,8 @@
4659
4896
  rawExtraFieldExtendedTimestamp,
4660
4897
  extraFieldExtendedTimestampFlag,
4661
4898
  rawExtraFieldNTFS,
4662
- rawExtraFieldAES
4899
+ rawExtraFieldUnix,
4900
+ rawExtraFieldAES,
4663
4901
  } = headerInfo;
4664
4902
  const { dataDescriptorArray } = dataDescriptorInfo;
4665
4903
  const {
@@ -4691,6 +4929,15 @@
4691
4929
  msDosCompatible,
4692
4930
  internalFileAttributes,
4693
4931
  externalFileAttributes,
4932
+ uid,
4933
+ gid,
4934
+ unixMode,
4935
+ setuid,
4936
+ setgid,
4937
+ sticky,
4938
+ unixExternalUpper,
4939
+ msdosAttributesRaw,
4940
+ msdosAttributes,
4694
4941
  useCompressionStream,
4695
4942
  passThrough
4696
4943
  } = options;
@@ -4708,13 +4955,23 @@
4708
4955
  localExtraFieldZip64Length,
4709
4956
  rawExtraFieldExtendedTimestamp,
4710
4957
  rawExtraFieldNTFS,
4958
+ rawExtraFieldUnix,
4711
4959
  rawExtraFieldAES,
4712
4960
  rawExtraField,
4713
4961
  extendedTimestamp,
4714
4962
  msDosCompatible,
4715
4963
  internalFileAttributes,
4716
4964
  externalFileAttributes,
4717
- diskNumberStart
4965
+ diskNumberStart,
4966
+ uid,
4967
+ gid,
4968
+ unixMode,
4969
+ setuid,
4970
+ setgid,
4971
+ sticky,
4972
+ unixExternalUpper,
4973
+ msdosAttributesRaw,
4974
+ msdosAttributes
4718
4975
  };
4719
4976
  let {
4720
4977
  signature,
@@ -4737,7 +4994,7 @@
4737
4994
  password,
4738
4995
  encryptionStrength,
4739
4996
  zipCrypto: encrypted && zipCrypto,
4740
- passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & 0xFF,
4997
+ passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & MAX_8_BITS,
4741
4998
  signed: !passThrough,
4742
4999
  compressed: compressed && !passThrough,
4743
5000
  encrypted: encrypted && !passThrough,
@@ -4916,6 +5173,49 @@
4916
5173
  } else {
4917
5174
  rawExtraFieldNTFS = rawExtraFieldExtendedTimestamp = new Uint8Array();
4918
5175
  }
5176
+ let rawExtraFieldUnix;
5177
+ try {
5178
+ const { uid, gid, unixMode, setuid, setgid, sticky, unixExtraFieldType } = options;
5179
+ if (unixExtraFieldType && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE)) {
5180
+ const uidBytes = packUnixId(uid);
5181
+ const gidBytes = packUnixId(gid);
5182
+ let modeArray = new Uint8Array();
5183
+ if (unixExtraFieldType == UNIX_EXTRA_FIELD_TYPE && unixMode !== UNDEFINED_VALUE) {
5184
+ let modeToWrite = unixMode & MAX_16_BITS;
5185
+ if (setuid) {
5186
+ modeToWrite |= FILE_ATTR_UNIX_SETUID_MASK;
5187
+ }
5188
+ if (setgid) {
5189
+ modeToWrite |= FILE_ATTR_UNIX_SETGID_MASK;
5190
+ }
5191
+ if (sticky) {
5192
+ modeToWrite |= FILE_ATTR_UNIX_STICKY_MASK;
5193
+ }
5194
+ modeArray = new Uint8Array(2);
5195
+ const modeDataView = new DataView(modeArray.buffer);
5196
+ modeDataView.setUint16(0, modeToWrite, true);
5197
+ }
5198
+ const payloadLength = 3 + uidBytes.length + gidBytes.length + modeArray.length;
5199
+ rawExtraFieldUnix = new Uint8Array(4 + payloadLength);
5200
+ const rawExtraFieldUnixView = getDataView(rawExtraFieldUnix);
5201
+ setUint16(rawExtraFieldUnixView, 0, unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE ? EXTRAFIELD_TYPE_INFOZIP : EXTRAFIELD_TYPE_UNIX);
5202
+ setUint16(rawExtraFieldUnixView, 2, payloadLength);
5203
+ setUint8(rawExtraFieldUnixView, 4, 1);
5204
+ setUint8(rawExtraFieldUnixView, 5, uidBytes.length);
5205
+ let offset = 6;
5206
+ arraySet(rawExtraFieldUnix, uidBytes, offset);
5207
+ offset += uidBytes.length;
5208
+ setUint8(rawExtraFieldUnixView, offset, gidBytes.length);
5209
+ offset++;
5210
+ arraySet(rawExtraFieldUnix, gidBytes, offset);
5211
+ offset += gidBytes.length;
5212
+ arraySet(rawExtraFieldUnix, modeArray, offset);
5213
+ } else {
5214
+ rawExtraFieldUnix = new Uint8Array();
5215
+ }
5216
+ } catch {
5217
+ rawExtraFieldUnix = new Uint8Array();
5218
+ }
4919
5219
  if (compressionMethod === UNDEFINED_VALUE) {
4920
5220
  compressionMethod = compressed ? COMPRESSION_METHOD_DEFLATE : COMPRESSION_METHOD_STORE;
4921
5221
  }
@@ -4928,7 +5228,7 @@
4928
5228
  compressionMethod = COMPRESSION_METHOD_AES;
4929
5229
  }
4930
5230
  const localExtraFieldZip64Length = zip64ExtraFieldComplete ? getLength(rawExtraFieldZip64) : 0;
4931
- const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
5231
+ const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
4932
5232
  const {
4933
5233
  headerArray,
4934
5234
  headerView,
@@ -4961,6 +5261,8 @@
4961
5261
  localHeaderOffset += getLength(rawExtraFieldExtendedTimestamp);
4962
5262
  arraySet(localHeaderArray, rawExtraFieldNTFS, localHeaderOffset);
4963
5263
  localHeaderOffset += getLength(rawExtraFieldNTFS);
5264
+ arraySet(localHeaderArray, rawExtraFieldUnix, localHeaderOffset);
5265
+ localHeaderOffset += getLength(rawExtraFieldUnix);
4964
5266
  arraySet(localHeaderArray, rawExtraField, localHeaderOffset);
4965
5267
  if (dataDescriptor) {
4966
5268
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + 4, 0);
@@ -4982,6 +5284,7 @@
4982
5284
  localExtraFieldZip64Length,
4983
5285
  rawExtraFieldExtendedTimestamp,
4984
5286
  rawExtraFieldNTFS,
5287
+ rawExtraFieldUnix,
4985
5288
  rawExtraFieldAES,
4986
5289
  extraFieldLength
4987
5290
  };
@@ -5008,6 +5311,46 @@
5008
5311
  entryInfo.metadataSize += extraBytesLength;
5009
5312
  }
5010
5313
 
5314
+ function packUnixId(id) {
5315
+ if (id === UNDEFINED_VALUE) {
5316
+ return new Uint8Array();
5317
+ } else {
5318
+ const dataArray = new Uint8Array(4);
5319
+ const dataView = getDataView(dataArray);
5320
+ dataView.setUint32(0, id, true);
5321
+ let length = 4;
5322
+ while (length > 1 && dataArray[length - 1] === 0) {
5323
+ length--;
5324
+ }
5325
+ return dataArray.subarray(0, length);
5326
+ }
5327
+ }
5328
+
5329
+ function normalizeMsdosAttributes(msdosAttributesRaw, msdosAttributes) {
5330
+ if (msdosAttributesRaw !== UNDEFINED_VALUE) {
5331
+ msdosAttributesRaw = msdosAttributesRaw & MAX_8_BITS;
5332
+ } else if (msdosAttributes !== UNDEFINED_VALUE) {
5333
+ const { readOnly, hidden, system, directory: msdDir, archive } = msdosAttributes;
5334
+ let raw = 0;
5335
+ if (readOnly) raw |= FILE_ATTR_MSDOS_READONLY_MASK;
5336
+ if (hidden) raw |= FILE_ATTR_MSDOS_HIDDEN_MASK;
5337
+ if (system) raw |= FILE_ATTR_MSDOS_SYSTEM_MASK;
5338
+ if (msdDir) raw |= FILE_ATTR_MSDOS_DIR_MASK;
5339
+ if (archive) raw |= FILE_ATTR_MSDOS_ARCHIVE_MASK;
5340
+ msdosAttributesRaw = raw & MAX_8_BITS;
5341
+ }
5342
+ if (msdosAttributes === UNDEFINED_VALUE) {
5343
+ msdosAttributes = {
5344
+ readOnly: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_READONLY_MASK),
5345
+ hidden: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_HIDDEN_MASK),
5346
+ system: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_SYSTEM_MASK),
5347
+ directory: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_DIR_MASK),
5348
+ archive: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_ARCHIVE_MASK)
5349
+ };
5350
+ }
5351
+ return { msdosAttributesRaw, msdosAttributes };
5352
+ }
5353
+
5011
5354
  function getDataDescriptorInfo({
5012
5355
  zip64,
5013
5356
  dataDescriptor,
@@ -5165,6 +5508,7 @@
5165
5508
  rawExtraFieldAES,
5166
5509
  rawComment,
5167
5510
  rawExtraFieldNTFS,
5511
+ rawExtraFieldUnix,
5168
5512
  rawExtraField,
5169
5513
  extendedTimestamp,
5170
5514
  extraFieldExtendedTimestampFlag,
@@ -5189,6 +5533,7 @@
5189
5533
  rawExtraFieldZip64,
5190
5534
  rawExtraFieldAES,
5191
5535
  rawExtraFieldNTFS,
5536
+ rawExtraFieldUnix,
5192
5537
  rawExtraFieldTimestamp,
5193
5538
  rawExtraField);
5194
5539
  }
@@ -5204,6 +5549,7 @@
5204
5549
  rawExtraFieldAES,
5205
5550
  rawExtraFieldExtendedTimestamp,
5206
5551
  rawExtraFieldNTFS,
5552
+ rawExtraFieldUnix,
5207
5553
  rawExtraField,
5208
5554
  rawComment,
5209
5555
  versionMadeBy,
@@ -5220,7 +5566,7 @@
5220
5566
  uncompressedSize,
5221
5567
  compressedSize
5222
5568
  } = fileEntry;
5223
- const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
5569
+ const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
5224
5570
  setUint32(directoryView, offset, CENTRAL_FILE_HEADER_SIGNATURE);
5225
5571
  setUint16(directoryView, offset + 4, versionMadeBy);
5226
5572
  if (!zip64UncompressedSize) {
@@ -5255,9 +5601,12 @@
5255
5601
  directoryOffset += getLength(rawExtraFieldExtendedTimestamp);
5256
5602
  arraySet(directoryArray, rawExtraFieldNTFS, directoryOffset);
5257
5603
  directoryOffset += getLength(rawExtraFieldNTFS);
5604
+ arraySet(directoryArray, rawExtraFieldUnix, directoryOffset);
5605
+ directoryOffset += getLength(rawExtraFieldUnix);
5258
5606
  arraySet(directoryArray, rawExtraField, directoryOffset);
5259
5607
  directoryOffset += getLength(rawExtraField);
5260
5608
  arraySet(directoryArray, rawComment, directoryOffset);
5609
+ directoryOffset += getLength(rawComment);
5261
5610
  if (offset - directoryDiskOffset > writer.availableSize) {
5262
5611
  writer.availableSize = 0;
5263
5612
  await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));