@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.
package/dist/zip-core.js CHANGED
@@ -37,6 +37,7 @@
37
37
 
38
38
  const MAX_32_BITS = 0xffffffff;
39
39
  const MAX_16_BITS = 0xffff;
40
+ const MAX_8_BITS = 0xff;
40
41
  const COMPRESSION_METHOD_DEFLATE = 0x08;
41
42
  const COMPRESSION_METHOD_DEFLATE_64 = 0x09;
42
43
  const COMPRESSION_METHOD_STORE = 0x00;
@@ -66,6 +67,8 @@
66
67
  const EXTRAFIELD_TYPE_UNICODE_PATH = 0x7075;
67
68
  const EXTRAFIELD_TYPE_UNICODE_COMMENT = 0x6375;
68
69
  const EXTRAFIELD_TYPE_USDZ = 0x1986;
70
+ const EXTRAFIELD_TYPE_INFOZIP = 0x7875;
71
+ const EXTRAFIELD_TYPE_UNIX = 0x7855;
69
72
 
70
73
  const BITFLAG_ENCRYPTED = 0b1;
71
74
  const BITFLAG_LEVEL = 0b0110;
@@ -75,10 +78,17 @@
75
78
  const BITFLAG_DATA_DESCRIPTOR = 0b1000;
76
79
  const BITFLAG_LANG_ENCODING_FLAG = 0b100000000000;
77
80
  const FILE_ATTR_MSDOS_DIR_MASK = 0b10000;
81
+ const FILE_ATTR_MSDOS_READONLY_MASK = 0x01;
82
+ const FILE_ATTR_MSDOS_HIDDEN_MASK = 0x02;
83
+ const FILE_ATTR_MSDOS_SYSTEM_MASK = 0x04;
84
+ const FILE_ATTR_MSDOS_ARCHIVE_MASK = 0x20;
78
85
  const FILE_ATTR_UNIX_TYPE_MASK = 0o170000;
79
86
  const FILE_ATTR_UNIX_TYPE_DIR = 0o040000;
80
87
  const FILE_ATTR_UNIX_EXECUTABLE_MASK = 0o111;
81
88
  const FILE_ATTR_UNIX_DEFAULT_MASK = 0o644;
89
+ const FILE_ATTR_UNIX_SETUID_MASK = 0o4000;
90
+ const FILE_ATTR_UNIX_SETGID_MASK = 0o2000;
91
+ const FILE_ATTR_UNIX_STICKY_MASK = 0o1000;
82
92
 
83
93
  const VERSION_DEFLATE = 0x14;
84
94
  const VERSION_ZIP64 = 0x2D;
@@ -97,6 +107,7 @@
97
107
  const UNDEFINED_VALUE = undefined;
98
108
  const UNDEFINED_TYPE = "undefined";
99
109
  const FUNCTION_TYPE = "function";
110
+ const OBJECT_TYPE = "object";
100
111
 
101
112
  /*
102
113
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
@@ -2187,13 +2198,8 @@
2187
2198
  const { value, readable, writable } = message;
2188
2199
  const transferables = [];
2189
2200
  if (value) {
2190
- if (value.byteLength < value.buffer.byteLength) {
2191
- message.value = value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength);
2192
- }
2193
- else {
2194
- message.value = value.buffer;
2195
- }
2196
- transferables.push(message.value);
2201
+ message.value = value;
2202
+ transferables.push(message.value.buffer);
2197
2203
  }
2198
2204
  if (transferStreams && transferStreamsSupported) {
2199
2205
  if (readable) {
@@ -2419,6 +2425,7 @@
2419
2425
  const HTTP_METHOD_GET = "GET";
2420
2426
  const HTTP_RANGE_UNIT = "bytes";
2421
2427
  const DEFAULT_CHUNK_SIZE = 64 * 1024;
2428
+ const DEFAULT_BUFFER_SIZE = 256 * 1024;
2422
2429
 
2423
2430
  const PROPERTY_NAME_WRITABLE = "writable";
2424
2431
 
@@ -2911,19 +2918,29 @@
2911
2918
 
2912
2919
  class Uint8ArrayWriter extends Writer {
2913
2920
 
2921
+ constructor(defaultBufferSize) {
2922
+ super();
2923
+ this.defaultBufferSize = defaultBufferSize || DEFAULT_BUFFER_SIZE;
2924
+ }
2925
+
2914
2926
  init(initSize = 0) {
2915
2927
  Object.assign(this, {
2916
2928
  offset: 0,
2917
- array: new Uint8Array(initSize)
2929
+ array: new Uint8Array(initSize > 0 ? initSize : this.defaultBufferSize)
2918
2930
  });
2919
2931
  super.init();
2920
2932
  }
2921
2933
 
2922
2934
  writeUint8Array(array) {
2923
2935
  const writer = this;
2924
- if (writer.offset + array.length > writer.array.length) {
2936
+ const requiredLength = writer.offset + array.length;
2937
+ if (requiredLength > writer.array.length) {
2938
+ let newLength = writer.array.length ? writer.array.length * 2 : writer.defaultBufferSize;
2939
+ while (newLength < requiredLength) {
2940
+ newLength *= 2;
2941
+ }
2925
2942
  const previousArray = writer.array;
2926
- writer.array = new Uint8Array(previousArray.length + array.length);
2943
+ writer.array = new Uint8Array(newLength);
2927
2944
  writer.array.set(previousArray);
2928
2945
  }
2929
2946
  writer.array.set(array, writer.offset);
@@ -2931,7 +2948,11 @@
2931
2948
  }
2932
2949
 
2933
2950
  getData() {
2934
- return this.array;
2951
+ if (this.offset === this.array.length) {
2952
+ return this.array;
2953
+ } else {
2954
+ return this.array.slice(0, this.offset);
2955
+ }
2935
2956
  }
2936
2957
  }
2937
2958
 
@@ -3250,6 +3271,8 @@
3250
3271
  const PROPERTY_NAME_RAW_CREATION_DATE = "rawCreationDate";
3251
3272
  const PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES = "internalFileAttributes";
3252
3273
  const PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES = "externalFileAttributes";
3274
+ const PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW = "msdosAttributesRaw";
3275
+ const PROPERTY_NAME_MSDOS_ATTRIBUTES = "msdosAttributes";
3253
3276
  const PROPERTY_NAME_MS_DOS_COMPATIBLE = "msDosCompatible";
3254
3277
  const PROPERTY_NAME_ZIP64 = "zip64";
3255
3278
  const PROPERTY_NAME_ENCRYPTED = "encrypted";
@@ -3261,17 +3284,73 @@
3261
3284
  const PROPERTY_NAME_COMPRESSION_METHOD = "compressionMethod";
3262
3285
  const PROPERTY_NAME_SIGNATURE = "signature";
3263
3286
  const PROPERTY_NAME_EXTRA_FIELD = "extraField";
3287
+ const PROPERTY_NAME_EXTRA_FIELD_INFOZIP = "extraFieldInfoZip";
3288
+ const PROPERTY_NAME_EXTRA_FIELD_UNIX = "extraFieldUnix";
3289
+ const PROPERTY_NAME_UID = "uid";
3290
+ const PROPERTY_NAME_GID = "gid";
3291
+ const PROPERTY_NAME_UNIX_MODE = "unixMode";
3292
+ const PROPERTY_NAME_SETUID = "setuid";
3293
+ const PROPERTY_NAME_SETGID = "setgid";
3294
+ const PROPERTY_NAME_STICKY = "sticky";
3295
+ const PROPERTY_NAME_BITFLAG = "bitFlag";
3296
+ const PROPERTY_NAME_FILENAME_UTF8 = "filenameUTF8";
3297
+ const PROPERTY_NAME_COMMENT_UTF8 = "commentUTF8";
3298
+ const PROPERTY_NAME_RAW_EXTRA_FIELD = "rawExtraField";
3299
+ const PROPERTY_NAME_EXTRA_FIELD_ZIP64 = "extraFieldZip64";
3300
+ const PROPERTY_NAME_EXTRA_FIELD_UNICODE_PATH = "extraFieldUnicodePath";
3301
+ const PROPERTY_NAME_EXTRA_FIELD_UNICODE_COMMENT = "extraFieldUnicodeComment";
3302
+ const PROPERTY_NAME_EXTRA_FIELD_AES = "extraFieldAES";
3303
+ const PROPERTY_NAME_EXTRA_FIELD_NTFS = "extraFieldNTFS";
3304
+ const PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP = "extraFieldExtendedTimestamp";
3264
3305
 
3265
3306
  const PROPERTY_NAMES = [
3266
- PROPERTY_NAME_FILENAME, PROPERTY_NAME_RAW_FILENAME, PROPERTY_NAME_COMPRESSED_SIZE, PROPERTY_NAME_UNCOMPRESSED_SIZE,
3267
- PROPERTY_NAME_LAST_MODIFICATION_DATE, PROPERTY_NAME_RAW_LAST_MODIFICATION_DATE, PROPERTY_NAME_COMMENT, PROPERTY_NAME_RAW_COMMENT,
3268
- PROPERTY_NAME_LAST_ACCESS_DATE, PROPERTY_NAME_CREATION_DATE, PROPERTY_NAME_OFFSET, PROPERTY_NAME_DISK_NUMBER_START,
3269
- PROPERTY_NAME_DISK_NUMBER_START, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES,
3270
- PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES, PROPERTY_NAME_MS_DOS_COMPATIBLE, PROPERTY_NAME_ZIP64,
3271
- PROPERTY_NAME_ENCRYPTED, PROPERTY_NAME_VERSION, PROPERTY_NAME_VERSION_MADE_BY, PROPERTY_NAME_ZIPCRYPTO, PROPERTY_NAME_DIRECTORY,
3272
- PROPERTY_NAME_EXECUTABLE, PROPERTY_NAME_COMPRESSION_METHOD, PROPERTY_NAME_SIGNATURE, PROPERTY_NAME_EXTRA_FIELD,
3273
- "bitFlag", "filenameUTF8", "commentUTF8", "rawExtraField", "extraFieldZip64", "extraFieldUnicodePath", "extraFieldUnicodeComment",
3274
- "extraFieldAES", "extraFieldNTFS", "extraFieldExtendedTimestamp"];
3307
+ PROPERTY_NAME_FILENAME,
3308
+ PROPERTY_NAME_RAW_FILENAME,
3309
+ PROPERTY_NAME_UNCOMPRESSED_SIZE,
3310
+ PROPERTY_NAME_COMPRESSED_SIZE,
3311
+ PROPERTY_NAME_LAST_MODIFICATION_DATE,
3312
+ PROPERTY_NAME_RAW_LAST_MODIFICATION_DATE,
3313
+ PROPERTY_NAME_COMMENT,
3314
+ PROPERTY_NAME_RAW_COMMENT,
3315
+ PROPERTY_NAME_LAST_ACCESS_DATE,
3316
+ PROPERTY_NAME_CREATION_DATE,
3317
+ PROPERTY_NAME_RAW_CREATION_DATE,
3318
+ PROPERTY_NAME_OFFSET,
3319
+ PROPERTY_NAME_DISK_NUMBER_START,
3320
+ PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES,
3321
+ PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES,
3322
+ PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW,
3323
+ PROPERTY_NAME_MSDOS_ATTRIBUTES,
3324
+ PROPERTY_NAME_MS_DOS_COMPATIBLE,
3325
+ PROPERTY_NAME_ZIP64,
3326
+ PROPERTY_NAME_ENCRYPTED,
3327
+ PROPERTY_NAME_VERSION,
3328
+ PROPERTY_NAME_VERSION_MADE_BY,
3329
+ PROPERTY_NAME_ZIPCRYPTO,
3330
+ PROPERTY_NAME_DIRECTORY,
3331
+ PROPERTY_NAME_EXECUTABLE,
3332
+ PROPERTY_NAME_COMPRESSION_METHOD,
3333
+ PROPERTY_NAME_SIGNATURE,
3334
+ PROPERTY_NAME_EXTRA_FIELD,
3335
+ PROPERTY_NAME_EXTRA_FIELD_UNIX,
3336
+ PROPERTY_NAME_EXTRA_FIELD_INFOZIP,
3337
+ PROPERTY_NAME_UID,
3338
+ PROPERTY_NAME_GID,
3339
+ PROPERTY_NAME_UNIX_MODE,
3340
+ PROPERTY_NAME_SETUID,
3341
+ PROPERTY_NAME_SETGID,
3342
+ PROPERTY_NAME_STICKY,
3343
+ PROPERTY_NAME_BITFLAG,
3344
+ PROPERTY_NAME_FILENAME_UTF8,
3345
+ PROPERTY_NAME_COMMENT_UTF8,
3346
+ PROPERTY_NAME_RAW_EXTRA_FIELD,
3347
+ PROPERTY_NAME_EXTRA_FIELD_ZIP64,
3348
+ PROPERTY_NAME_EXTRA_FIELD_UNICODE_PATH,
3349
+ PROPERTY_NAME_EXTRA_FIELD_UNICODE_COMMENT,
3350
+ PROPERTY_NAME_EXTRA_FIELD_AES,
3351
+ PROPERTY_NAME_EXTRA_FIELD_NTFS,
3352
+ PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP
3353
+ ];
3275
3354
 
3276
3355
  class Entry {
3277
3356
 
@@ -3338,6 +3417,7 @@
3338
3417
  const OPTION_ENCODE_TEXT = "encodeText";
3339
3418
  const OPTION_OFFSET = "offset";
3340
3419
  const OPTION_USDZ = "usdz";
3420
+ const OPTION_UNIX_EXTRA_FIELD_TYPE = "unixExtraFieldType";
3341
3421
 
3342
3422
  /*
3343
3423
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
@@ -3380,6 +3460,7 @@
3380
3460
  const ERR_SPLIT_ZIP_FILE = "Split zip file";
3381
3461
  const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
3382
3462
  const CHARSET_UTF8 = "utf-8";
3463
+ const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
3383
3464
  const CHARSET_CP437 = "cp437";
3384
3465
  const ZIP64_PROPERTIES = [
3385
3466
  [PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
@@ -3535,51 +3616,71 @@
3535
3616
  const filenameUTF8 = languageEncodingFlag;
3536
3617
  const commentUTF8 = languageEncodingFlag;
3537
3618
  const externalFileAttributes = getUint32(directoryView, offset + 38);
3538
- const directory =
3539
- (msDosCompatible && ((getUint8(directoryView, offset + 38) & FILE_ATTR_MSDOS_DIR_MASK) == FILE_ATTR_MSDOS_DIR_MASK)) ||
3540
- (unixCompatible && (((externalFileAttributes >> 16) & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR)) ||
3541
- (rawFilename.length && rawFilename.at(-1) == DIRECTORY_SIGNATURE.charCodeAt(0));
3542
- const executable = (unixCompatible && (((externalFileAttributes >> 16) & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0));
3619
+ const msdosAttributesRaw = externalFileAttributes & MAX_8_BITS;
3620
+ const msdosAttributes = {
3621
+ readOnly: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_READONLY_MASK),
3622
+ hidden: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_HIDDEN_MASK),
3623
+ system: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_SYSTEM_MASK),
3624
+ directory: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_DIR_MASK),
3625
+ archive: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_ARCHIVE_MASK)
3626
+ };
3543
3627
  const offsetFileEntry = getUint32(directoryView, offset + 42) + prependedDataLength;
3628
+ const decode = getOptionValue$1(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
3629
+ const rawFilenameEncoding = filenameUTF8 ? CHARSET_UTF8 : filenameEncoding || CHARSET_CP437;
3630
+ const rawCommentEncoding = commentUTF8 ? CHARSET_UTF8 : commentEncoding || CHARSET_CP437;
3631
+ let filename = decode(rawFilename, rawFilenameEncoding);
3632
+ if (filename === UNDEFINED_VALUE) {
3633
+ filename = decodeText(rawFilename, rawFilenameEncoding);
3634
+ }
3635
+ let comment = decode(rawComment, rawCommentEncoding);
3636
+ if (comment === UNDEFINED_VALUE) {
3637
+ comment = decodeText(rawComment, rawCommentEncoding);
3638
+ }
3544
3639
  Object.assign(fileEntry, {
3545
3640
  versionMadeBy,
3546
3641
  msDosCompatible,
3547
3642
  compressedSize: 0,
3548
3643
  uncompressedSize: 0,
3549
3644
  commentLength,
3550
- directory,
3551
3645
  offset: offsetFileEntry,
3552
3646
  diskNumberStart: getUint16(directoryView, offset + 34),
3553
3647
  internalFileAttributes: getUint16(directoryView, offset + 36),
3554
3648
  externalFileAttributes,
3649
+ msdosAttributesRaw,
3650
+ msdosAttributes,
3555
3651
  rawFilename,
3556
3652
  filenameUTF8,
3557
3653
  commentUTF8,
3558
3654
  rawExtraField: directoryArray.subarray(extraFieldOffset, commentOffset),
3559
- executable
3560
- });
3561
- fileEntry.internalFileAttribute = fileEntry.internalFileAttributes;
3562
- fileEntry.externalFileAttribute = fileEntry.externalFileAttributes;
3563
- const decode = getOptionValue$1(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
3564
- const rawFilenameEncoding = filenameUTF8 ? CHARSET_UTF8 : filenameEncoding || CHARSET_CP437;
3565
- const rawCommentEncoding = commentUTF8 ? CHARSET_UTF8 : commentEncoding || CHARSET_CP437;
3566
- let filename = decode(rawFilename, rawFilenameEncoding);
3567
- if (filename === UNDEFINED_VALUE) {
3568
- filename = decodeText(rawFilename, rawFilenameEncoding);
3569
- }
3570
- let comment = decode(rawComment, rawCommentEncoding);
3571
- if (comment === UNDEFINED_VALUE) {
3572
- comment = decodeText(rawComment, rawCommentEncoding);
3573
- }
3574
- Object.assign(fileEntry, {
3575
3655
  rawComment,
3576
3656
  filename,
3577
- comment,
3578
- directory: directory || filename.endsWith(DIRECTORY_SIGNATURE)
3657
+ comment
3579
3658
  });
3580
3659
  startOffset = Math.max(offsetFileEntry, startOffset);
3581
3660
  readCommonFooter(fileEntry, fileEntry, directoryView, offset + 6);
3582
- fileEntry.zipCrypto = fileEntry.encrypted && !fileEntry.extraFieldAES;
3661
+ const unixExternalUpper = (fileEntry.externalFileAttributes >> 16) & MAX_16_BITS;
3662
+ if (fileEntry.unixMode === UNDEFINED_VALUE && (unixExternalUpper & (FILE_ATTR_UNIX_DEFAULT_MASK | FILE_ATTR_UNIX_EXECUTABLE_MASK | FILE_ATTR_UNIX_TYPE_DIR)) != 0) {
3663
+ fileEntry.unixMode = unixExternalUpper;
3664
+ }
3665
+ const setuid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETUID_MASK);
3666
+ const setgid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETGID_MASK);
3667
+ const sticky = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_STICKY_MASK);
3668
+ const executable = (fileEntry.unixMode !== UNDEFINED_VALUE)
3669
+ ? ((fileEntry.unixMode & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)
3670
+ : (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0));
3671
+ const modeIsDir = fileEntry.unixMode !== UNDEFINED_VALUE && ((fileEntry.unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
3672
+ const upperIsDir = ((unixExternalUpper & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
3673
+ Object.assign(fileEntry, {
3674
+ setuid,
3675
+ setgid,
3676
+ sticky,
3677
+ unixExternalUpper,
3678
+ internalFileAttribute: fileEntry.internalFileAttributes,
3679
+ externalFileAttribute: fileEntry.externalFileAttributes,
3680
+ executable,
3681
+ directory: modeIsDir || upperIsDir || (msDosCompatible && msdosAttributes.directory) || (filename.endsWith(DIRECTORY_SIGNATURE) && !fileEntry.uncompressedSize),
3682
+ zipCrypto: fileEntry.encrypted && !fileEntry.extraFieldAES
3683
+ });
3583
3684
  const entry = new Entry(fileEntry);
3584
3685
  entry.getData = (writer, options) => fileEntry.getData(writer, entry, zipReader.readRanges, options);
3585
3686
  entry.arrayBuffer = async options => {
@@ -3753,7 +3854,7 @@
3753
3854
  zipCrypto,
3754
3855
  encryptionStrength: extraFieldAES && extraFieldAES.strength,
3755
3856
  signed: getOptionValue$1(zipEntry, options, OPTION_CHECK_SIGNATURE) && !passThrough,
3756
- passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & 0xFF) : ((signature >>> 24) & 0xFF)),
3857
+ passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((signature >>> 24) & MAX_8_BITS)),
3757
3858
  outputSize: passThrough ? compressedSize : uncompressedSize,
3758
3859
  signature,
3759
3860
  compressed: compressionMethod != 0 && !passThrough,
@@ -3884,6 +3985,17 @@
3884
3985
  readExtraFieldNTFS(extraFieldNTFS, directory);
3885
3986
  directory.extraFieldNTFS = extraFieldNTFS;
3886
3987
  }
3988
+ const extraFieldUnix = extraField.get(EXTRAFIELD_TYPE_UNIX);
3989
+ if (extraFieldUnix) {
3990
+ readExtraFieldUnix(extraFieldUnix, directory, false);
3991
+ directory.extraFieldUnix = extraFieldUnix;
3992
+ } else {
3993
+ const extraFieldInfoZip = extraField.get(EXTRAFIELD_TYPE_INFOZIP);
3994
+ if (extraFieldInfoZip) {
3995
+ readExtraFieldUnix(extraFieldInfoZip, directory, true);
3996
+ directory.extraFieldInfoZip = extraFieldInfoZip;
3997
+ }
3998
+ }
3887
3999
  const extraFieldExtendedTimestamp = extraField.get(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
3888
4000
  if (extraFieldExtendedTimestamp) {
3889
4001
  readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory, localDirectory);
@@ -3925,7 +4037,7 @@
3925
4037
  });
3926
4038
  if (extraFieldUnicode.valid) {
3927
4039
  directory[propertyName] = extraFieldUnicode[propertyName];
3928
- directory[propertyName + "UTF8"] = true;
4040
+ directory[propertyName + PROPERTY_NAME_UTF8_SUFFIX] = true;
3929
4041
  }
3930
4042
  }
3931
4043
 
@@ -3981,6 +4093,47 @@
3981
4093
  }
3982
4094
  }
3983
4095
 
4096
+ function readExtraFieldUnix(extraField, directory, isInfoZip) {
4097
+ try {
4098
+ const view = getDataView$1(new Uint8Array(extraField.data));
4099
+ let offset = 0;
4100
+ const version = getUint8(view, offset++);
4101
+ const uidSize = getUint8(view, offset++);
4102
+ const uidBytes = extraField.data.subarray(offset, offset + uidSize);
4103
+ offset += uidSize;
4104
+ const uid = unpackUnixId(uidBytes);
4105
+ const gidSize = getUint8(view, offset++);
4106
+ const gidBytes = extraField.data.subarray(offset, offset + gidSize);
4107
+ offset += gidSize;
4108
+ const gid = unpackUnixId(gidBytes);
4109
+ let unixMode = UNDEFINED_VALUE;
4110
+ if (!isInfoZip && offset + 2 <= extraField.data.length) {
4111
+ const base = extraField.data;
4112
+ const modeView = new DataView(base.buffer, base.byteOffset + offset, 2);
4113
+ unixMode = modeView.getUint16(0, true);
4114
+ }
4115
+ Object.assign(extraField, { version, uid, gid, unixMode });
4116
+ if (uid !== UNDEFINED_VALUE) {
4117
+ directory.uid = uid;
4118
+ }
4119
+ if (gid !== UNDEFINED_VALUE) {
4120
+ directory.gid = gid;
4121
+ }
4122
+ if (unixMode !== UNDEFINED_VALUE) {
4123
+ directory.unixMode = unixMode;
4124
+ }
4125
+ } catch {
4126
+ // ignored
4127
+ }
4128
+ }
4129
+
4130
+ function unpackUnixId(bytes) {
4131
+ const buffer = new Uint8Array(4);
4132
+ buffer.set(bytes, 0);
4133
+ const view = new DataView(buffer.buffer, buffer.byteOffset, 4);
4134
+ return view.getUint32(0, true);
4135
+ }
4136
+
3984
4137
  function readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory, localDirectory) {
3985
4138
  const extraFieldView = getDataView$1(extraFieldExtendedTimestamp.data);
3986
4139
  const flags = getUint8(extraFieldView, 0);
@@ -4107,7 +4260,7 @@
4107
4260
  }
4108
4261
 
4109
4262
  function getDate(timeRaw) {
4110
- const date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & 0x0000ffff;
4263
+ const date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & MAX_16_BITS;
4111
4264
  try {
4112
4265
  return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
4113
4266
  } catch {
@@ -4183,8 +4336,16 @@
4183
4336
  const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (make sure 'keepOrder' is set to 'true')";
4184
4337
  const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
4185
4338
  const ERR_ZIP_NOT_EMPTY = "Zip file not empty";
4339
+ const ERR_INVALID_UID = "Invalid uid (must be integer 0..2^32-1)";
4340
+ const ERR_INVALID_GID = "Invalid gid (must be integer 0..2^32-1)";
4341
+ const ERR_INVALID_UNIX_MODE = "Invalid UNIX mode (must be integer 0..65535)";
4342
+ const ERR_INVALID_UNIX_EXTRA_FIELD_TYPE = "Invalid unixExtraFieldType (must be 'infozip' or 'unix')";
4343
+ const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be integer 0..255)";
4344
+ const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
4186
4345
 
4187
4346
  const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
4347
+ const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
4348
+ const UNIX_EXTRA_FIELD_TYPE = "unix";
4188
4349
 
4189
4350
  let workers = 0;
4190
4351
  const pendingEntries = [];
@@ -4242,15 +4403,17 @@
4242
4403
  rawExtraFieldAES,
4243
4404
  rawExtraFieldExtendedTimestamp,
4244
4405
  rawExtraFieldNTFS,
4245
- rawExtraField
4406
+ rawExtraFieldUnix,
4407
+ rawExtraField,
4246
4408
  } = entry;
4247
4409
  const { level, languageEncodingFlag, dataDescriptor } = bitFlag;
4248
4410
  rawExtraFieldZip64 = rawExtraFieldZip64 || new Uint8Array();
4249
4411
  rawExtraFieldAES = rawExtraFieldAES || new Uint8Array();
4250
4412
  rawExtraFieldExtendedTimestamp = rawExtraFieldExtendedTimestamp || new Uint8Array();
4251
4413
  rawExtraFieldNTFS = rawExtraFieldNTFS || new Uint8Array();
4414
+ rawExtraFieldUnix = entry.rawExtraFieldUnix || new Uint8Array();
4252
4415
  rawExtraField = rawExtraField || new Uint8Array();
4253
- const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
4416
+ const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
4254
4417
  const zip64UncompressedSize = zip64 && uncompressedSize > MAX_32_BITS;
4255
4418
  const zip64CompressedSize = zip64 && compressedSize > MAX_32_BITS;
4256
4419
  const {
@@ -4277,6 +4440,7 @@
4277
4440
  rawExtraFieldAES,
4278
4441
  rawExtraFieldExtendedTimestamp,
4279
4442
  rawExtraFieldNTFS,
4443
+ rawExtraFieldUnix,
4280
4444
  rawExtraField,
4281
4445
  extendedTimestamp: rawExtraFieldExtendedTimestamp.length > 0 || rawExtraFieldNTFS.length > 0,
4282
4446
  extraFieldExtendedTimestampFlag: 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0),
@@ -4345,7 +4509,7 @@
4345
4509
  while (pendingAddFileCalls.size) {
4346
4510
  await Promise.allSettled(Array.from(pendingAddFileCalls));
4347
4511
  }
4348
- await closeFile(this, comment, options);
4512
+ await closeFile(zipWriter, comment, options);
4349
4513
  const preventClose = getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
4350
4514
  if (!preventClose) {
4351
4515
  await writable.getWriter().close();
@@ -4376,16 +4540,52 @@
4376
4540
  return writable;
4377
4541
  }
4378
4542
 
4379
- close(comment = undefined, options = {}) {
4543
+ close(comment = UNDEFINED_VALUE, options = {}) {
4380
4544
  return this.zipWriter.close(comment, options);
4381
4545
  }
4382
4546
  }
4383
4547
 
4384
4548
  async function addFile(zipWriter, name, reader, options) {
4385
4549
  name = name.trim();
4386
- const msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
4387
- const versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
4550
+ let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
4551
+ let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
4388
4552
  const executable = getOptionValue(zipWriter, options, PROPERTY_NAME_EXECUTABLE);
4553
+ const uid = getOptionValue(zipWriter, options, PROPERTY_NAME_UID);
4554
+ const gid = getOptionValue(zipWriter, options, PROPERTY_NAME_GID);
4555
+ let unixMode = getOptionValue(zipWriter, options, PROPERTY_NAME_UNIX_MODE);
4556
+ const unixExtraFieldType = getOptionValue(zipWriter, options, OPTION_UNIX_EXTRA_FIELD_TYPE);
4557
+ let setuid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETUID);
4558
+ let setgid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETGID);
4559
+ let sticky = getOptionValue(zipWriter, options, PROPERTY_NAME_STICKY);
4560
+ if (uid !== UNDEFINED_VALUE && (uid < 0 || uid > MAX_32_BITS)) {
4561
+ throw new Error(ERR_INVALID_UID);
4562
+ }
4563
+ if (gid !== UNDEFINED_VALUE && (gid < 0 || gid > MAX_32_BITS)) {
4564
+ throw new Error(ERR_INVALID_GID);
4565
+ }
4566
+ if (unixMode !== UNDEFINED_VALUE && (unixMode < 0 || unixMode > MAX_16_BITS)) {
4567
+ throw new Error(ERR_INVALID_UNIX_MODE);
4568
+ }
4569
+ if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
4570
+ throw new Error(ERR_INVALID_UNIX_EXTRA_FIELD_TYPE);
4571
+ }
4572
+ let msdosAttributesRaw = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
4573
+ let msdosAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES);
4574
+ const hasUnixMetadata = uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE || unixExtraFieldType;
4575
+ const hasMsDosProvided = msdosAttributesRaw !== UNDEFINED_VALUE || msdosAttributes !== UNDEFINED_VALUE;
4576
+ if (hasUnixMetadata) {
4577
+ msDosCompatible = false;
4578
+ versionMadeBy = (versionMadeBy & MAX_16_BITS) | (3 << 8);
4579
+ } else if (hasMsDosProvided) {
4580
+ msDosCompatible = true;
4581
+ versionMadeBy = (versionMadeBy & MAX_8_BITS);
4582
+ }
4583
+ if (msdosAttributesRaw !== UNDEFINED_VALUE && (msdosAttributesRaw < 0 || msdosAttributesRaw > MAX_8_BITS)) {
4584
+ throw new Error(ERR_INVALID_MSDOS_ATTRIBUTES);
4585
+ }
4586
+ if (msdosAttributes && typeof msdosAttributes !== OBJECT_TYPE) {
4587
+ throw new Error(ERR_INVALID_MSDOS_DATA);
4588
+ }
4389
4589
  if (versionMadeBy > MAX_16_BITS) {
4390
4590
  throw new Error(ERR_INVALID_VERSION);
4391
4591
  }
@@ -4411,6 +4611,34 @@
4411
4611
  externalFileAttributes = FILE_ATTR_UNIX_DEFAULT_MASK << 16;
4412
4612
  }
4413
4613
  }
4614
+ let unixExternalUpper;
4615
+ if (!msDosCompatible) {
4616
+ unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
4617
+ unixMode = unixMode === UNDEFINED_VALUE ? unixExternalUpper : (unixMode & MAX_16_BITS);
4618
+ if (setuid) {
4619
+ unixMode |= FILE_ATTR_UNIX_SETUID_MASK;
4620
+ } else {
4621
+ setuid = Boolean(unixMode & FILE_ATTR_UNIX_SETUID_MASK);
4622
+ }
4623
+ if (setgid) {
4624
+ unixMode |= FILE_ATTR_UNIX_SETGID_MASK;
4625
+ } else {
4626
+ setgid = Boolean(unixMode & FILE_ATTR_UNIX_SETGID_MASK);
4627
+ }
4628
+ if (sticky) {
4629
+ unixMode |= FILE_ATTR_UNIX_STICKY_MASK;
4630
+ } else {
4631
+ sticky = Boolean(unixMode & FILE_ATTR_UNIX_STICKY_MASK);
4632
+ }
4633
+ if (directory) {
4634
+ unixMode |= FILE_ATTR_UNIX_TYPE_DIR;
4635
+ }
4636
+ externalFileAttributes = ((unixMode & MAX_16_BITS) << 16) | (externalFileAttributes & MAX_8_BITS);
4637
+ }
4638
+ ({ msdosAttributesRaw, msdosAttributes } = normalizeMsdosAttributes(msdosAttributesRaw, msdosAttributes));
4639
+ if (hasMsDosProvided) {
4640
+ externalFileAttributes = (externalFileAttributes & MAX_32_BITS) | (msdosAttributesRaw & MAX_8_BITS);
4641
+ }
4414
4642
  const encode = getOptionValue(zipWriter, options, OPTION_ENCODE_TEXT, encodeText);
4415
4643
  let rawFilename = encode(name);
4416
4644
  if (rawFilename === UNDEFINED_VALUE) {
@@ -4573,7 +4801,16 @@
4573
4801
  compressionMethod,
4574
4802
  uncompressedSize,
4575
4803
  offset: zipWriter.offset - diskOffset,
4576
- diskNumberStart: diskNumber
4804
+ diskNumberStart: diskNumber,
4805
+ uid,
4806
+ gid,
4807
+ setuid,
4808
+ setgid,
4809
+ sticky,
4810
+ unixMode,
4811
+ msdosAttributesRaw,
4812
+ msdosAttributes,
4813
+ unixExternalUpper
4577
4814
  });
4578
4815
  const headerInfo = getHeaderInfo(options);
4579
4816
  const dataDescriptorInfo = getDataDescriptorInfo(options);
@@ -4765,7 +5002,8 @@
4765
5002
  rawExtraFieldExtendedTimestamp,
4766
5003
  extraFieldExtendedTimestampFlag,
4767
5004
  rawExtraFieldNTFS,
4768
- rawExtraFieldAES
5005
+ rawExtraFieldUnix,
5006
+ rawExtraFieldAES,
4769
5007
  } = headerInfo;
4770
5008
  const { dataDescriptorArray } = dataDescriptorInfo;
4771
5009
  const {
@@ -4797,6 +5035,15 @@
4797
5035
  msDosCompatible,
4798
5036
  internalFileAttributes,
4799
5037
  externalFileAttributes,
5038
+ uid,
5039
+ gid,
5040
+ unixMode,
5041
+ setuid,
5042
+ setgid,
5043
+ sticky,
5044
+ unixExternalUpper,
5045
+ msdosAttributesRaw,
5046
+ msdosAttributes,
4800
5047
  useCompressionStream,
4801
5048
  passThrough
4802
5049
  } = options;
@@ -4814,13 +5061,23 @@
4814
5061
  localExtraFieldZip64Length,
4815
5062
  rawExtraFieldExtendedTimestamp,
4816
5063
  rawExtraFieldNTFS,
5064
+ rawExtraFieldUnix,
4817
5065
  rawExtraFieldAES,
4818
5066
  rawExtraField,
4819
5067
  extendedTimestamp,
4820
5068
  msDosCompatible,
4821
5069
  internalFileAttributes,
4822
5070
  externalFileAttributes,
4823
- diskNumberStart
5071
+ diskNumberStart,
5072
+ uid,
5073
+ gid,
5074
+ unixMode,
5075
+ setuid,
5076
+ setgid,
5077
+ sticky,
5078
+ unixExternalUpper,
5079
+ msdosAttributesRaw,
5080
+ msdosAttributes
4824
5081
  };
4825
5082
  let {
4826
5083
  signature,
@@ -4843,7 +5100,7 @@
4843
5100
  password,
4844
5101
  encryptionStrength,
4845
5102
  zipCrypto: encrypted && zipCrypto,
4846
- passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & 0xFF,
5103
+ passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & MAX_8_BITS,
4847
5104
  signed: !passThrough,
4848
5105
  compressed: compressed && !passThrough,
4849
5106
  encrypted: encrypted && !passThrough,
@@ -5022,6 +5279,49 @@
5022
5279
  } else {
5023
5280
  rawExtraFieldNTFS = rawExtraFieldExtendedTimestamp = new Uint8Array();
5024
5281
  }
5282
+ let rawExtraFieldUnix;
5283
+ try {
5284
+ const { uid, gid, unixMode, setuid, setgid, sticky, unixExtraFieldType } = options;
5285
+ if (unixExtraFieldType && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE)) {
5286
+ const uidBytes = packUnixId(uid);
5287
+ const gidBytes = packUnixId(gid);
5288
+ let modeArray = new Uint8Array();
5289
+ if (unixExtraFieldType == UNIX_EXTRA_FIELD_TYPE && unixMode !== UNDEFINED_VALUE) {
5290
+ let modeToWrite = unixMode & MAX_16_BITS;
5291
+ if (setuid) {
5292
+ modeToWrite |= FILE_ATTR_UNIX_SETUID_MASK;
5293
+ }
5294
+ if (setgid) {
5295
+ modeToWrite |= FILE_ATTR_UNIX_SETGID_MASK;
5296
+ }
5297
+ if (sticky) {
5298
+ modeToWrite |= FILE_ATTR_UNIX_STICKY_MASK;
5299
+ }
5300
+ modeArray = new Uint8Array(2);
5301
+ const modeDataView = new DataView(modeArray.buffer);
5302
+ modeDataView.setUint16(0, modeToWrite, true);
5303
+ }
5304
+ const payloadLength = 3 + uidBytes.length + gidBytes.length + modeArray.length;
5305
+ rawExtraFieldUnix = new Uint8Array(4 + payloadLength);
5306
+ const rawExtraFieldUnixView = getDataView(rawExtraFieldUnix);
5307
+ setUint16(rawExtraFieldUnixView, 0, unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE ? EXTRAFIELD_TYPE_INFOZIP : EXTRAFIELD_TYPE_UNIX);
5308
+ setUint16(rawExtraFieldUnixView, 2, payloadLength);
5309
+ setUint8(rawExtraFieldUnixView, 4, 1);
5310
+ setUint8(rawExtraFieldUnixView, 5, uidBytes.length);
5311
+ let offset = 6;
5312
+ arraySet(rawExtraFieldUnix, uidBytes, offset);
5313
+ offset += uidBytes.length;
5314
+ setUint8(rawExtraFieldUnixView, offset, gidBytes.length);
5315
+ offset++;
5316
+ arraySet(rawExtraFieldUnix, gidBytes, offset);
5317
+ offset += gidBytes.length;
5318
+ arraySet(rawExtraFieldUnix, modeArray, offset);
5319
+ } else {
5320
+ rawExtraFieldUnix = new Uint8Array();
5321
+ }
5322
+ } catch {
5323
+ rawExtraFieldUnix = new Uint8Array();
5324
+ }
5025
5325
  if (compressionMethod === UNDEFINED_VALUE) {
5026
5326
  compressionMethod = compressed ? COMPRESSION_METHOD_DEFLATE : COMPRESSION_METHOD_STORE;
5027
5327
  }
@@ -5034,7 +5334,7 @@
5034
5334
  compressionMethod = COMPRESSION_METHOD_AES;
5035
5335
  }
5036
5336
  const localExtraFieldZip64Length = zip64ExtraFieldComplete ? getLength(rawExtraFieldZip64) : 0;
5037
- const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
5337
+ const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
5038
5338
  const {
5039
5339
  headerArray,
5040
5340
  headerView,
@@ -5067,6 +5367,8 @@
5067
5367
  localHeaderOffset += getLength(rawExtraFieldExtendedTimestamp);
5068
5368
  arraySet(localHeaderArray, rawExtraFieldNTFS, localHeaderOffset);
5069
5369
  localHeaderOffset += getLength(rawExtraFieldNTFS);
5370
+ arraySet(localHeaderArray, rawExtraFieldUnix, localHeaderOffset);
5371
+ localHeaderOffset += getLength(rawExtraFieldUnix);
5070
5372
  arraySet(localHeaderArray, rawExtraField, localHeaderOffset);
5071
5373
  if (dataDescriptor) {
5072
5374
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + 4, 0);
@@ -5088,6 +5390,7 @@
5088
5390
  localExtraFieldZip64Length,
5089
5391
  rawExtraFieldExtendedTimestamp,
5090
5392
  rawExtraFieldNTFS,
5393
+ rawExtraFieldUnix,
5091
5394
  rawExtraFieldAES,
5092
5395
  extraFieldLength
5093
5396
  };
@@ -5114,6 +5417,46 @@
5114
5417
  entryInfo.metadataSize += extraBytesLength;
5115
5418
  }
5116
5419
 
5420
+ function packUnixId(id) {
5421
+ if (id === UNDEFINED_VALUE) {
5422
+ return new Uint8Array();
5423
+ } else {
5424
+ const dataArray = new Uint8Array(4);
5425
+ const dataView = getDataView(dataArray);
5426
+ dataView.setUint32(0, id, true);
5427
+ let length = 4;
5428
+ while (length > 1 && dataArray[length - 1] === 0) {
5429
+ length--;
5430
+ }
5431
+ return dataArray.subarray(0, length);
5432
+ }
5433
+ }
5434
+
5435
+ function normalizeMsdosAttributes(msdosAttributesRaw, msdosAttributes) {
5436
+ if (msdosAttributesRaw !== UNDEFINED_VALUE) {
5437
+ msdosAttributesRaw = msdosAttributesRaw & MAX_8_BITS;
5438
+ } else if (msdosAttributes !== UNDEFINED_VALUE) {
5439
+ const { readOnly, hidden, system, directory: msdDir, archive } = msdosAttributes;
5440
+ let raw = 0;
5441
+ if (readOnly) raw |= FILE_ATTR_MSDOS_READONLY_MASK;
5442
+ if (hidden) raw |= FILE_ATTR_MSDOS_HIDDEN_MASK;
5443
+ if (system) raw |= FILE_ATTR_MSDOS_SYSTEM_MASK;
5444
+ if (msdDir) raw |= FILE_ATTR_MSDOS_DIR_MASK;
5445
+ if (archive) raw |= FILE_ATTR_MSDOS_ARCHIVE_MASK;
5446
+ msdosAttributesRaw = raw & MAX_8_BITS;
5447
+ }
5448
+ if (msdosAttributes === UNDEFINED_VALUE) {
5449
+ msdosAttributes = {
5450
+ readOnly: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_READONLY_MASK),
5451
+ hidden: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_HIDDEN_MASK),
5452
+ system: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_SYSTEM_MASK),
5453
+ directory: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_DIR_MASK),
5454
+ archive: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_ARCHIVE_MASK)
5455
+ };
5456
+ }
5457
+ return { msdosAttributesRaw, msdosAttributes };
5458
+ }
5459
+
5117
5460
  function getDataDescriptorInfo({
5118
5461
  zip64,
5119
5462
  dataDescriptor,
@@ -5271,6 +5614,7 @@
5271
5614
  rawExtraFieldAES,
5272
5615
  rawComment,
5273
5616
  rawExtraFieldNTFS,
5617
+ rawExtraFieldUnix,
5274
5618
  rawExtraField,
5275
5619
  extendedTimestamp,
5276
5620
  extraFieldExtendedTimestampFlag,
@@ -5295,6 +5639,7 @@
5295
5639
  rawExtraFieldZip64,
5296
5640
  rawExtraFieldAES,
5297
5641
  rawExtraFieldNTFS,
5642
+ rawExtraFieldUnix,
5298
5643
  rawExtraFieldTimestamp,
5299
5644
  rawExtraField);
5300
5645
  }
@@ -5310,6 +5655,7 @@
5310
5655
  rawExtraFieldAES,
5311
5656
  rawExtraFieldExtendedTimestamp,
5312
5657
  rawExtraFieldNTFS,
5658
+ rawExtraFieldUnix,
5313
5659
  rawExtraField,
5314
5660
  rawComment,
5315
5661
  versionMadeBy,
@@ -5326,7 +5672,7 @@
5326
5672
  uncompressedSize,
5327
5673
  compressedSize
5328
5674
  } = fileEntry;
5329
- const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
5675
+ const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
5330
5676
  setUint32(directoryView, offset, CENTRAL_FILE_HEADER_SIGNATURE);
5331
5677
  setUint16(directoryView, offset + 4, versionMadeBy);
5332
5678
  if (!zip64UncompressedSize) {
@@ -5361,9 +5707,12 @@
5361
5707
  directoryOffset += getLength(rawExtraFieldExtendedTimestamp);
5362
5708
  arraySet(directoryArray, rawExtraFieldNTFS, directoryOffset);
5363
5709
  directoryOffset += getLength(rawExtraFieldNTFS);
5710
+ arraySet(directoryArray, rawExtraFieldUnix, directoryOffset);
5711
+ directoryOffset += getLength(rawExtraFieldUnix);
5364
5712
  arraySet(directoryArray, rawExtraField, directoryOffset);
5365
5713
  directoryOffset += getLength(rawExtraField);
5366
5714
  arraySet(directoryArray, rawComment, directoryOffset);
5715
+ directoryOffset += getLength(rawComment);
5367
5716
  if (offset - directoryDiskOffset > writer.availableSize) {
5368
5717
  writer.availableSize = 0;
5369
5718
  await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));