@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-fs.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.
@@ -2193,13 +2204,8 @@
2193
2204
  const { value, readable, writable } = message;
2194
2205
  const transferables = [];
2195
2206
  if (value) {
2196
- if (value.byteLength < value.buffer.byteLength) {
2197
- message.value = value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength);
2198
- }
2199
- else {
2200
- message.value = value.buffer;
2201
- }
2202
- transferables.push(message.value);
2207
+ message.value = value;
2208
+ transferables.push(message.value.buffer);
2203
2209
  }
2204
2210
  if (transferStreams && transferStreamsSupported) {
2205
2211
  if (readable) {
@@ -2425,6 +2431,7 @@
2425
2431
  const HTTP_METHOD_GET = "GET";
2426
2432
  const HTTP_RANGE_UNIT = "bytes";
2427
2433
  const DEFAULT_CHUNK_SIZE = 64 * 1024;
2434
+ const DEFAULT_BUFFER_SIZE = 256 * 1024;
2428
2435
 
2429
2436
  const PROPERTY_NAME_WRITABLE = "writable";
2430
2437
 
@@ -2917,19 +2924,29 @@
2917
2924
 
2918
2925
  class Uint8ArrayWriter extends Writer {
2919
2926
 
2927
+ constructor(defaultBufferSize) {
2928
+ super();
2929
+ this.defaultBufferSize = defaultBufferSize || DEFAULT_BUFFER_SIZE;
2930
+ }
2931
+
2920
2932
  init(initSize = 0) {
2921
2933
  Object.assign(this, {
2922
2934
  offset: 0,
2923
- array: new Uint8Array(initSize)
2935
+ array: new Uint8Array(initSize > 0 ? initSize : this.defaultBufferSize)
2924
2936
  });
2925
2937
  super.init();
2926
2938
  }
2927
2939
 
2928
2940
  writeUint8Array(array) {
2929
2941
  const writer = this;
2930
- if (writer.offset + array.length > writer.array.length) {
2942
+ const requiredLength = writer.offset + array.length;
2943
+ if (requiredLength > writer.array.length) {
2944
+ let newLength = writer.array.length ? writer.array.length * 2 : writer.defaultBufferSize;
2945
+ while (newLength < requiredLength) {
2946
+ newLength *= 2;
2947
+ }
2931
2948
  const previousArray = writer.array;
2932
- writer.array = new Uint8Array(previousArray.length + array.length);
2949
+ writer.array = new Uint8Array(newLength);
2933
2950
  writer.array.set(previousArray);
2934
2951
  }
2935
2952
  writer.array.set(array, writer.offset);
@@ -2937,7 +2954,11 @@
2937
2954
  }
2938
2955
 
2939
2956
  getData() {
2940
- return this.array;
2957
+ if (this.offset === this.array.length) {
2958
+ return this.array;
2959
+ } else {
2960
+ return this.array.slice(0, this.offset);
2961
+ }
2941
2962
  }
2942
2963
  }
2943
2964
 
@@ -3256,6 +3277,8 @@
3256
3277
  const PROPERTY_NAME_RAW_CREATION_DATE = "rawCreationDate";
3257
3278
  const PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES = "internalFileAttributes";
3258
3279
  const PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES = "externalFileAttributes";
3280
+ const PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW = "msdosAttributesRaw";
3281
+ const PROPERTY_NAME_MSDOS_ATTRIBUTES = "msdosAttributes";
3259
3282
  const PROPERTY_NAME_MS_DOS_COMPATIBLE = "msDosCompatible";
3260
3283
  const PROPERTY_NAME_ZIP64 = "zip64";
3261
3284
  const PROPERTY_NAME_ENCRYPTED = "encrypted";
@@ -3267,17 +3290,73 @@
3267
3290
  const PROPERTY_NAME_COMPRESSION_METHOD = "compressionMethod";
3268
3291
  const PROPERTY_NAME_SIGNATURE = "signature";
3269
3292
  const PROPERTY_NAME_EXTRA_FIELD = "extraField";
3293
+ const PROPERTY_NAME_EXTRA_FIELD_INFOZIP = "extraFieldInfoZip";
3294
+ const PROPERTY_NAME_EXTRA_FIELD_UNIX = "extraFieldUnix";
3295
+ const PROPERTY_NAME_UID = "uid";
3296
+ const PROPERTY_NAME_GID = "gid";
3297
+ const PROPERTY_NAME_UNIX_MODE = "unixMode";
3298
+ const PROPERTY_NAME_SETUID = "setuid";
3299
+ const PROPERTY_NAME_SETGID = "setgid";
3300
+ const PROPERTY_NAME_STICKY = "sticky";
3301
+ const PROPERTY_NAME_BITFLAG = "bitFlag";
3302
+ const PROPERTY_NAME_FILENAME_UTF8 = "filenameUTF8";
3303
+ const PROPERTY_NAME_COMMENT_UTF8 = "commentUTF8";
3304
+ const PROPERTY_NAME_RAW_EXTRA_FIELD = "rawExtraField";
3305
+ const PROPERTY_NAME_EXTRA_FIELD_ZIP64 = "extraFieldZip64";
3306
+ const PROPERTY_NAME_EXTRA_FIELD_UNICODE_PATH = "extraFieldUnicodePath";
3307
+ const PROPERTY_NAME_EXTRA_FIELD_UNICODE_COMMENT = "extraFieldUnicodeComment";
3308
+ const PROPERTY_NAME_EXTRA_FIELD_AES = "extraFieldAES";
3309
+ const PROPERTY_NAME_EXTRA_FIELD_NTFS = "extraFieldNTFS";
3310
+ const PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP = "extraFieldExtendedTimestamp";
3270
3311
 
3271
3312
  const PROPERTY_NAMES = [
3272
- PROPERTY_NAME_FILENAME, PROPERTY_NAME_RAW_FILENAME, PROPERTY_NAME_COMPRESSED_SIZE, PROPERTY_NAME_UNCOMPRESSED_SIZE,
3273
- PROPERTY_NAME_LAST_MODIFICATION_DATE, PROPERTY_NAME_RAW_LAST_MODIFICATION_DATE, PROPERTY_NAME_COMMENT, PROPERTY_NAME_RAW_COMMENT,
3274
- PROPERTY_NAME_LAST_ACCESS_DATE, PROPERTY_NAME_CREATION_DATE, PROPERTY_NAME_OFFSET, PROPERTY_NAME_DISK_NUMBER_START,
3275
- PROPERTY_NAME_DISK_NUMBER_START, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES,
3276
- PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES, PROPERTY_NAME_MS_DOS_COMPATIBLE, PROPERTY_NAME_ZIP64,
3277
- PROPERTY_NAME_ENCRYPTED, PROPERTY_NAME_VERSION, PROPERTY_NAME_VERSION_MADE_BY, PROPERTY_NAME_ZIPCRYPTO, PROPERTY_NAME_DIRECTORY,
3278
- PROPERTY_NAME_EXECUTABLE, PROPERTY_NAME_COMPRESSION_METHOD, PROPERTY_NAME_SIGNATURE, PROPERTY_NAME_EXTRA_FIELD,
3279
- "bitFlag", "filenameUTF8", "commentUTF8", "rawExtraField", "extraFieldZip64", "extraFieldUnicodePath", "extraFieldUnicodeComment",
3280
- "extraFieldAES", "extraFieldNTFS", "extraFieldExtendedTimestamp"];
3313
+ PROPERTY_NAME_FILENAME,
3314
+ PROPERTY_NAME_RAW_FILENAME,
3315
+ PROPERTY_NAME_UNCOMPRESSED_SIZE,
3316
+ PROPERTY_NAME_COMPRESSED_SIZE,
3317
+ PROPERTY_NAME_LAST_MODIFICATION_DATE,
3318
+ PROPERTY_NAME_RAW_LAST_MODIFICATION_DATE,
3319
+ PROPERTY_NAME_COMMENT,
3320
+ PROPERTY_NAME_RAW_COMMENT,
3321
+ PROPERTY_NAME_LAST_ACCESS_DATE,
3322
+ PROPERTY_NAME_CREATION_DATE,
3323
+ PROPERTY_NAME_RAW_CREATION_DATE,
3324
+ PROPERTY_NAME_OFFSET,
3325
+ PROPERTY_NAME_DISK_NUMBER_START,
3326
+ PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES,
3327
+ PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES,
3328
+ PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW,
3329
+ PROPERTY_NAME_MSDOS_ATTRIBUTES,
3330
+ PROPERTY_NAME_MS_DOS_COMPATIBLE,
3331
+ PROPERTY_NAME_ZIP64,
3332
+ PROPERTY_NAME_ENCRYPTED,
3333
+ PROPERTY_NAME_VERSION,
3334
+ PROPERTY_NAME_VERSION_MADE_BY,
3335
+ PROPERTY_NAME_ZIPCRYPTO,
3336
+ PROPERTY_NAME_DIRECTORY,
3337
+ PROPERTY_NAME_EXECUTABLE,
3338
+ PROPERTY_NAME_COMPRESSION_METHOD,
3339
+ PROPERTY_NAME_SIGNATURE,
3340
+ PROPERTY_NAME_EXTRA_FIELD,
3341
+ PROPERTY_NAME_EXTRA_FIELD_UNIX,
3342
+ PROPERTY_NAME_EXTRA_FIELD_INFOZIP,
3343
+ PROPERTY_NAME_UID,
3344
+ PROPERTY_NAME_GID,
3345
+ PROPERTY_NAME_UNIX_MODE,
3346
+ PROPERTY_NAME_SETUID,
3347
+ PROPERTY_NAME_SETGID,
3348
+ PROPERTY_NAME_STICKY,
3349
+ PROPERTY_NAME_BITFLAG,
3350
+ PROPERTY_NAME_FILENAME_UTF8,
3351
+ PROPERTY_NAME_COMMENT_UTF8,
3352
+ PROPERTY_NAME_RAW_EXTRA_FIELD,
3353
+ PROPERTY_NAME_EXTRA_FIELD_ZIP64,
3354
+ PROPERTY_NAME_EXTRA_FIELD_UNICODE_PATH,
3355
+ PROPERTY_NAME_EXTRA_FIELD_UNICODE_COMMENT,
3356
+ PROPERTY_NAME_EXTRA_FIELD_AES,
3357
+ PROPERTY_NAME_EXTRA_FIELD_NTFS,
3358
+ PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP
3359
+ ];
3281
3360
 
3282
3361
  class Entry {
3283
3362
 
@@ -3344,6 +3423,7 @@
3344
3423
  const OPTION_ENCODE_TEXT = "encodeText";
3345
3424
  const OPTION_OFFSET = "offset";
3346
3425
  const OPTION_USDZ = "usdz";
3426
+ const OPTION_UNIX_EXTRA_FIELD_TYPE = "unixExtraFieldType";
3347
3427
 
3348
3428
  /*
3349
3429
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
@@ -3386,6 +3466,7 @@
3386
3466
  const ERR_SPLIT_ZIP_FILE = "Split zip file";
3387
3467
  const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
3388
3468
  const CHARSET_UTF8 = "utf-8";
3469
+ const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
3389
3470
  const CHARSET_CP437 = "cp437";
3390
3471
  const ZIP64_PROPERTIES = [
3391
3472
  [PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
@@ -3541,51 +3622,71 @@
3541
3622
  const filenameUTF8 = languageEncodingFlag;
3542
3623
  const commentUTF8 = languageEncodingFlag;
3543
3624
  const externalFileAttributes = getUint32(directoryView, offset + 38);
3544
- const directory =
3545
- (msDosCompatible && ((getUint8(directoryView, offset + 38) & FILE_ATTR_MSDOS_DIR_MASK) == FILE_ATTR_MSDOS_DIR_MASK)) ||
3546
- (unixCompatible && (((externalFileAttributes >> 16) & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR)) ||
3547
- (rawFilename.length && rawFilename.at(-1) == DIRECTORY_SIGNATURE.charCodeAt(0));
3548
- const executable = (unixCompatible && (((externalFileAttributes >> 16) & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0));
3625
+ const msdosAttributesRaw = externalFileAttributes & MAX_8_BITS;
3626
+ const msdosAttributes = {
3627
+ readOnly: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_READONLY_MASK),
3628
+ hidden: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_HIDDEN_MASK),
3629
+ system: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_SYSTEM_MASK),
3630
+ directory: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_DIR_MASK),
3631
+ archive: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_ARCHIVE_MASK)
3632
+ };
3549
3633
  const offsetFileEntry = getUint32(directoryView, offset + 42) + prependedDataLength;
3634
+ const decode = getOptionValue$1(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
3635
+ const rawFilenameEncoding = filenameUTF8 ? CHARSET_UTF8 : filenameEncoding || CHARSET_CP437;
3636
+ const rawCommentEncoding = commentUTF8 ? CHARSET_UTF8 : commentEncoding || CHARSET_CP437;
3637
+ let filename = decode(rawFilename, rawFilenameEncoding);
3638
+ if (filename === UNDEFINED_VALUE) {
3639
+ filename = decodeText(rawFilename, rawFilenameEncoding);
3640
+ }
3641
+ let comment = decode(rawComment, rawCommentEncoding);
3642
+ if (comment === UNDEFINED_VALUE) {
3643
+ comment = decodeText(rawComment, rawCommentEncoding);
3644
+ }
3550
3645
  Object.assign(fileEntry, {
3551
3646
  versionMadeBy,
3552
3647
  msDosCompatible,
3553
3648
  compressedSize: 0,
3554
3649
  uncompressedSize: 0,
3555
3650
  commentLength,
3556
- directory,
3557
3651
  offset: offsetFileEntry,
3558
3652
  diskNumberStart: getUint16(directoryView, offset + 34),
3559
3653
  internalFileAttributes: getUint16(directoryView, offset + 36),
3560
3654
  externalFileAttributes,
3655
+ msdosAttributesRaw,
3656
+ msdosAttributes,
3561
3657
  rawFilename,
3562
3658
  filenameUTF8,
3563
3659
  commentUTF8,
3564
3660
  rawExtraField: directoryArray.subarray(extraFieldOffset, commentOffset),
3565
- executable
3566
- });
3567
- fileEntry.internalFileAttribute = fileEntry.internalFileAttributes;
3568
- fileEntry.externalFileAttribute = fileEntry.externalFileAttributes;
3569
- const decode = getOptionValue$1(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
3570
- const rawFilenameEncoding = filenameUTF8 ? CHARSET_UTF8 : filenameEncoding || CHARSET_CP437;
3571
- const rawCommentEncoding = commentUTF8 ? CHARSET_UTF8 : commentEncoding || CHARSET_CP437;
3572
- let filename = decode(rawFilename, rawFilenameEncoding);
3573
- if (filename === UNDEFINED_VALUE) {
3574
- filename = decodeText(rawFilename, rawFilenameEncoding);
3575
- }
3576
- let comment = decode(rawComment, rawCommentEncoding);
3577
- if (comment === UNDEFINED_VALUE) {
3578
- comment = decodeText(rawComment, rawCommentEncoding);
3579
- }
3580
- Object.assign(fileEntry, {
3581
3661
  rawComment,
3582
3662
  filename,
3583
- comment,
3584
- directory: directory || filename.endsWith(DIRECTORY_SIGNATURE)
3663
+ comment
3585
3664
  });
3586
3665
  startOffset = Math.max(offsetFileEntry, startOffset);
3587
3666
  readCommonFooter(fileEntry, fileEntry, directoryView, offset + 6);
3588
- fileEntry.zipCrypto = fileEntry.encrypted && !fileEntry.extraFieldAES;
3667
+ const unixExternalUpper = (fileEntry.externalFileAttributes >> 16) & MAX_16_BITS;
3668
+ if (fileEntry.unixMode === UNDEFINED_VALUE && (unixExternalUpper & (FILE_ATTR_UNIX_DEFAULT_MASK | FILE_ATTR_UNIX_EXECUTABLE_MASK | FILE_ATTR_UNIX_TYPE_DIR)) != 0) {
3669
+ fileEntry.unixMode = unixExternalUpper;
3670
+ }
3671
+ const setuid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETUID_MASK);
3672
+ const setgid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETGID_MASK);
3673
+ const sticky = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_STICKY_MASK);
3674
+ const executable = (fileEntry.unixMode !== UNDEFINED_VALUE)
3675
+ ? ((fileEntry.unixMode & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)
3676
+ : (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0));
3677
+ const modeIsDir = fileEntry.unixMode !== UNDEFINED_VALUE && ((fileEntry.unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
3678
+ const upperIsDir = ((unixExternalUpper & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
3679
+ Object.assign(fileEntry, {
3680
+ setuid,
3681
+ setgid,
3682
+ sticky,
3683
+ unixExternalUpper,
3684
+ internalFileAttribute: fileEntry.internalFileAttributes,
3685
+ externalFileAttribute: fileEntry.externalFileAttributes,
3686
+ executable,
3687
+ directory: modeIsDir || upperIsDir || (msDosCompatible && msdosAttributes.directory) || (filename.endsWith(DIRECTORY_SIGNATURE) && !fileEntry.uncompressedSize),
3688
+ zipCrypto: fileEntry.encrypted && !fileEntry.extraFieldAES
3689
+ });
3589
3690
  const entry = new Entry(fileEntry);
3590
3691
  entry.getData = (writer, options) => fileEntry.getData(writer, entry, zipReader.readRanges, options);
3591
3692
  entry.arrayBuffer = async options => {
@@ -3759,7 +3860,7 @@
3759
3860
  zipCrypto,
3760
3861
  encryptionStrength: extraFieldAES && extraFieldAES.strength,
3761
3862
  signed: getOptionValue$1(zipEntry, options, OPTION_CHECK_SIGNATURE) && !passThrough,
3762
- passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & 0xFF) : ((signature >>> 24) & 0xFF)),
3863
+ passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((signature >>> 24) & MAX_8_BITS)),
3763
3864
  outputSize: passThrough ? compressedSize : uncompressedSize,
3764
3865
  signature,
3765
3866
  compressed: compressionMethod != 0 && !passThrough,
@@ -3890,6 +3991,17 @@
3890
3991
  readExtraFieldNTFS(extraFieldNTFS, directory);
3891
3992
  directory.extraFieldNTFS = extraFieldNTFS;
3892
3993
  }
3994
+ const extraFieldUnix = extraField.get(EXTRAFIELD_TYPE_UNIX);
3995
+ if (extraFieldUnix) {
3996
+ readExtraFieldUnix(extraFieldUnix, directory, false);
3997
+ directory.extraFieldUnix = extraFieldUnix;
3998
+ } else {
3999
+ const extraFieldInfoZip = extraField.get(EXTRAFIELD_TYPE_INFOZIP);
4000
+ if (extraFieldInfoZip) {
4001
+ readExtraFieldUnix(extraFieldInfoZip, directory, true);
4002
+ directory.extraFieldInfoZip = extraFieldInfoZip;
4003
+ }
4004
+ }
3893
4005
  const extraFieldExtendedTimestamp = extraField.get(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
3894
4006
  if (extraFieldExtendedTimestamp) {
3895
4007
  readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory, localDirectory);
@@ -3931,7 +4043,7 @@
3931
4043
  });
3932
4044
  if (extraFieldUnicode.valid) {
3933
4045
  directory[propertyName] = extraFieldUnicode[propertyName];
3934
- directory[propertyName + "UTF8"] = true;
4046
+ directory[propertyName + PROPERTY_NAME_UTF8_SUFFIX] = true;
3935
4047
  }
3936
4048
  }
3937
4049
 
@@ -3987,6 +4099,47 @@
3987
4099
  }
3988
4100
  }
3989
4101
 
4102
+ function readExtraFieldUnix(extraField, directory, isInfoZip) {
4103
+ try {
4104
+ const view = getDataView$1(new Uint8Array(extraField.data));
4105
+ let offset = 0;
4106
+ const version = getUint8(view, offset++);
4107
+ const uidSize = getUint8(view, offset++);
4108
+ const uidBytes = extraField.data.subarray(offset, offset + uidSize);
4109
+ offset += uidSize;
4110
+ const uid = unpackUnixId(uidBytes);
4111
+ const gidSize = getUint8(view, offset++);
4112
+ const gidBytes = extraField.data.subarray(offset, offset + gidSize);
4113
+ offset += gidSize;
4114
+ const gid = unpackUnixId(gidBytes);
4115
+ let unixMode = UNDEFINED_VALUE;
4116
+ if (!isInfoZip && offset + 2 <= extraField.data.length) {
4117
+ const base = extraField.data;
4118
+ const modeView = new DataView(base.buffer, base.byteOffset + offset, 2);
4119
+ unixMode = modeView.getUint16(0, true);
4120
+ }
4121
+ Object.assign(extraField, { version, uid, gid, unixMode });
4122
+ if (uid !== UNDEFINED_VALUE) {
4123
+ directory.uid = uid;
4124
+ }
4125
+ if (gid !== UNDEFINED_VALUE) {
4126
+ directory.gid = gid;
4127
+ }
4128
+ if (unixMode !== UNDEFINED_VALUE) {
4129
+ directory.unixMode = unixMode;
4130
+ }
4131
+ } catch {
4132
+ // ignored
4133
+ }
4134
+ }
4135
+
4136
+ function unpackUnixId(bytes) {
4137
+ const buffer = new Uint8Array(4);
4138
+ buffer.set(bytes, 0);
4139
+ const view = new DataView(buffer.buffer, buffer.byteOffset, 4);
4140
+ return view.getUint32(0, true);
4141
+ }
4142
+
3990
4143
  function readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory, localDirectory) {
3991
4144
  const extraFieldView = getDataView$1(extraFieldExtendedTimestamp.data);
3992
4145
  const flags = getUint8(extraFieldView, 0);
@@ -4113,7 +4266,7 @@
4113
4266
  }
4114
4267
 
4115
4268
  function getDate(timeRaw) {
4116
- const date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & 0x0000ffff;
4269
+ const date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & MAX_16_BITS;
4117
4270
  try {
4118
4271
  return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
4119
4272
  } catch {
@@ -4189,8 +4342,16 @@
4189
4342
  const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (make sure 'keepOrder' is set to 'true')";
4190
4343
  const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
4191
4344
  const ERR_ZIP_NOT_EMPTY = "Zip file not empty";
4345
+ const ERR_INVALID_UID = "Invalid uid (must be integer 0..2^32-1)";
4346
+ const ERR_INVALID_GID = "Invalid gid (must be integer 0..2^32-1)";
4347
+ const ERR_INVALID_UNIX_MODE = "Invalid UNIX mode (must be integer 0..65535)";
4348
+ const ERR_INVALID_UNIX_EXTRA_FIELD_TYPE = "Invalid unixExtraFieldType (must be 'infozip' or 'unix')";
4349
+ const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be integer 0..255)";
4350
+ const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
4192
4351
 
4193
4352
  const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
4353
+ const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
4354
+ const UNIX_EXTRA_FIELD_TYPE = "unix";
4194
4355
 
4195
4356
  let workers = 0;
4196
4357
  const pendingEntries = [];
@@ -4248,15 +4409,17 @@
4248
4409
  rawExtraFieldAES,
4249
4410
  rawExtraFieldExtendedTimestamp,
4250
4411
  rawExtraFieldNTFS,
4251
- rawExtraField
4412
+ rawExtraFieldUnix,
4413
+ rawExtraField,
4252
4414
  } = entry;
4253
4415
  const { level, languageEncodingFlag, dataDescriptor } = bitFlag;
4254
4416
  rawExtraFieldZip64 = rawExtraFieldZip64 || new Uint8Array();
4255
4417
  rawExtraFieldAES = rawExtraFieldAES || new Uint8Array();
4256
4418
  rawExtraFieldExtendedTimestamp = rawExtraFieldExtendedTimestamp || new Uint8Array();
4257
4419
  rawExtraFieldNTFS = rawExtraFieldNTFS || new Uint8Array();
4420
+ rawExtraFieldUnix = entry.rawExtraFieldUnix || new Uint8Array();
4258
4421
  rawExtraField = rawExtraField || new Uint8Array();
4259
- const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
4422
+ const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
4260
4423
  const zip64UncompressedSize = zip64 && uncompressedSize > MAX_32_BITS;
4261
4424
  const zip64CompressedSize = zip64 && compressedSize > MAX_32_BITS;
4262
4425
  const {
@@ -4283,6 +4446,7 @@
4283
4446
  rawExtraFieldAES,
4284
4447
  rawExtraFieldExtendedTimestamp,
4285
4448
  rawExtraFieldNTFS,
4449
+ rawExtraFieldUnix,
4286
4450
  rawExtraField,
4287
4451
  extendedTimestamp: rawExtraFieldExtendedTimestamp.length > 0 || rawExtraFieldNTFS.length > 0,
4288
4452
  extraFieldExtendedTimestampFlag: 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0),
@@ -4351,7 +4515,7 @@
4351
4515
  while (pendingAddFileCalls.size) {
4352
4516
  await Promise.allSettled(Array.from(pendingAddFileCalls));
4353
4517
  }
4354
- await closeFile(this, comment, options);
4518
+ await closeFile(zipWriter, comment, options);
4355
4519
  const preventClose = getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
4356
4520
  if (!preventClose) {
4357
4521
  await writable.getWriter().close();
@@ -4382,16 +4546,52 @@
4382
4546
  return writable;
4383
4547
  }
4384
4548
 
4385
- close(comment = undefined, options = {}) {
4549
+ close(comment = UNDEFINED_VALUE, options = {}) {
4386
4550
  return this.zipWriter.close(comment, options);
4387
4551
  }
4388
4552
  }
4389
4553
 
4390
4554
  async function addFile(zipWriter, name, reader, options) {
4391
4555
  name = name.trim();
4392
- const msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
4393
- const versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
4556
+ let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
4557
+ let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
4394
4558
  const executable = getOptionValue(zipWriter, options, PROPERTY_NAME_EXECUTABLE);
4559
+ const uid = getOptionValue(zipWriter, options, PROPERTY_NAME_UID);
4560
+ const gid = getOptionValue(zipWriter, options, PROPERTY_NAME_GID);
4561
+ let unixMode = getOptionValue(zipWriter, options, PROPERTY_NAME_UNIX_MODE);
4562
+ const unixExtraFieldType = getOptionValue(zipWriter, options, OPTION_UNIX_EXTRA_FIELD_TYPE);
4563
+ let setuid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETUID);
4564
+ let setgid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETGID);
4565
+ let sticky = getOptionValue(zipWriter, options, PROPERTY_NAME_STICKY);
4566
+ if (uid !== UNDEFINED_VALUE && (uid < 0 || uid > MAX_32_BITS)) {
4567
+ throw new Error(ERR_INVALID_UID);
4568
+ }
4569
+ if (gid !== UNDEFINED_VALUE && (gid < 0 || gid > MAX_32_BITS)) {
4570
+ throw new Error(ERR_INVALID_GID);
4571
+ }
4572
+ if (unixMode !== UNDEFINED_VALUE && (unixMode < 0 || unixMode > MAX_16_BITS)) {
4573
+ throw new Error(ERR_INVALID_UNIX_MODE);
4574
+ }
4575
+ if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
4576
+ throw new Error(ERR_INVALID_UNIX_EXTRA_FIELD_TYPE);
4577
+ }
4578
+ let msdosAttributesRaw = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
4579
+ let msdosAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES);
4580
+ const hasUnixMetadata = uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE || unixExtraFieldType;
4581
+ const hasMsDosProvided = msdosAttributesRaw !== UNDEFINED_VALUE || msdosAttributes !== UNDEFINED_VALUE;
4582
+ if (hasUnixMetadata) {
4583
+ msDosCompatible = false;
4584
+ versionMadeBy = (versionMadeBy & MAX_16_BITS) | (3 << 8);
4585
+ } else if (hasMsDosProvided) {
4586
+ msDosCompatible = true;
4587
+ versionMadeBy = (versionMadeBy & MAX_8_BITS);
4588
+ }
4589
+ if (msdosAttributesRaw !== UNDEFINED_VALUE && (msdosAttributesRaw < 0 || msdosAttributesRaw > MAX_8_BITS)) {
4590
+ throw new Error(ERR_INVALID_MSDOS_ATTRIBUTES);
4591
+ }
4592
+ if (msdosAttributes && typeof msdosAttributes !== OBJECT_TYPE) {
4593
+ throw new Error(ERR_INVALID_MSDOS_DATA);
4594
+ }
4395
4595
  if (versionMadeBy > MAX_16_BITS) {
4396
4596
  throw new Error(ERR_INVALID_VERSION);
4397
4597
  }
@@ -4417,6 +4617,34 @@
4417
4617
  externalFileAttributes = FILE_ATTR_UNIX_DEFAULT_MASK << 16;
4418
4618
  }
4419
4619
  }
4620
+ let unixExternalUpper;
4621
+ if (!msDosCompatible) {
4622
+ unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
4623
+ unixMode = unixMode === UNDEFINED_VALUE ? unixExternalUpper : (unixMode & MAX_16_BITS);
4624
+ if (setuid) {
4625
+ unixMode |= FILE_ATTR_UNIX_SETUID_MASK;
4626
+ } else {
4627
+ setuid = Boolean(unixMode & FILE_ATTR_UNIX_SETUID_MASK);
4628
+ }
4629
+ if (setgid) {
4630
+ unixMode |= FILE_ATTR_UNIX_SETGID_MASK;
4631
+ } else {
4632
+ setgid = Boolean(unixMode & FILE_ATTR_UNIX_SETGID_MASK);
4633
+ }
4634
+ if (sticky) {
4635
+ unixMode |= FILE_ATTR_UNIX_STICKY_MASK;
4636
+ } else {
4637
+ sticky = Boolean(unixMode & FILE_ATTR_UNIX_STICKY_MASK);
4638
+ }
4639
+ if (directory) {
4640
+ unixMode |= FILE_ATTR_UNIX_TYPE_DIR;
4641
+ }
4642
+ externalFileAttributes = ((unixMode & MAX_16_BITS) << 16) | (externalFileAttributes & MAX_8_BITS);
4643
+ }
4644
+ ({ msdosAttributesRaw, msdosAttributes } = normalizeMsdosAttributes(msdosAttributesRaw, msdosAttributes));
4645
+ if (hasMsDosProvided) {
4646
+ externalFileAttributes = (externalFileAttributes & MAX_32_BITS) | (msdosAttributesRaw & MAX_8_BITS);
4647
+ }
4420
4648
  const encode = getOptionValue(zipWriter, options, OPTION_ENCODE_TEXT, encodeText);
4421
4649
  let rawFilename = encode(name);
4422
4650
  if (rawFilename === UNDEFINED_VALUE) {
@@ -4579,7 +4807,16 @@
4579
4807
  compressionMethod,
4580
4808
  uncompressedSize,
4581
4809
  offset: zipWriter.offset - diskOffset,
4582
- diskNumberStart: diskNumber
4810
+ diskNumberStart: diskNumber,
4811
+ uid,
4812
+ gid,
4813
+ setuid,
4814
+ setgid,
4815
+ sticky,
4816
+ unixMode,
4817
+ msdosAttributesRaw,
4818
+ msdosAttributes,
4819
+ unixExternalUpper
4583
4820
  });
4584
4821
  const headerInfo = getHeaderInfo(options);
4585
4822
  const dataDescriptorInfo = getDataDescriptorInfo(options);
@@ -4771,7 +5008,8 @@
4771
5008
  rawExtraFieldExtendedTimestamp,
4772
5009
  extraFieldExtendedTimestampFlag,
4773
5010
  rawExtraFieldNTFS,
4774
- rawExtraFieldAES
5011
+ rawExtraFieldUnix,
5012
+ rawExtraFieldAES,
4775
5013
  } = headerInfo;
4776
5014
  const { dataDescriptorArray } = dataDescriptorInfo;
4777
5015
  const {
@@ -4803,6 +5041,15 @@
4803
5041
  msDosCompatible,
4804
5042
  internalFileAttributes,
4805
5043
  externalFileAttributes,
5044
+ uid,
5045
+ gid,
5046
+ unixMode,
5047
+ setuid,
5048
+ setgid,
5049
+ sticky,
5050
+ unixExternalUpper,
5051
+ msdosAttributesRaw,
5052
+ msdosAttributes,
4806
5053
  useCompressionStream,
4807
5054
  passThrough
4808
5055
  } = options;
@@ -4820,13 +5067,23 @@
4820
5067
  localExtraFieldZip64Length,
4821
5068
  rawExtraFieldExtendedTimestamp,
4822
5069
  rawExtraFieldNTFS,
5070
+ rawExtraFieldUnix,
4823
5071
  rawExtraFieldAES,
4824
5072
  rawExtraField,
4825
5073
  extendedTimestamp,
4826
5074
  msDosCompatible,
4827
5075
  internalFileAttributes,
4828
5076
  externalFileAttributes,
4829
- diskNumberStart
5077
+ diskNumberStart,
5078
+ uid,
5079
+ gid,
5080
+ unixMode,
5081
+ setuid,
5082
+ setgid,
5083
+ sticky,
5084
+ unixExternalUpper,
5085
+ msdosAttributesRaw,
5086
+ msdosAttributes
4830
5087
  };
4831
5088
  let {
4832
5089
  signature,
@@ -4849,7 +5106,7 @@
4849
5106
  password,
4850
5107
  encryptionStrength,
4851
5108
  zipCrypto: encrypted && zipCrypto,
4852
- passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & 0xFF,
5109
+ passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & MAX_8_BITS,
4853
5110
  signed: !passThrough,
4854
5111
  compressed: compressed && !passThrough,
4855
5112
  encrypted: encrypted && !passThrough,
@@ -5028,6 +5285,49 @@
5028
5285
  } else {
5029
5286
  rawExtraFieldNTFS = rawExtraFieldExtendedTimestamp = new Uint8Array();
5030
5287
  }
5288
+ let rawExtraFieldUnix;
5289
+ try {
5290
+ const { uid, gid, unixMode, setuid, setgid, sticky, unixExtraFieldType } = options;
5291
+ if (unixExtraFieldType && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE)) {
5292
+ const uidBytes = packUnixId(uid);
5293
+ const gidBytes = packUnixId(gid);
5294
+ let modeArray = new Uint8Array();
5295
+ if (unixExtraFieldType == UNIX_EXTRA_FIELD_TYPE && unixMode !== UNDEFINED_VALUE) {
5296
+ let modeToWrite = unixMode & MAX_16_BITS;
5297
+ if (setuid) {
5298
+ modeToWrite |= FILE_ATTR_UNIX_SETUID_MASK;
5299
+ }
5300
+ if (setgid) {
5301
+ modeToWrite |= FILE_ATTR_UNIX_SETGID_MASK;
5302
+ }
5303
+ if (sticky) {
5304
+ modeToWrite |= FILE_ATTR_UNIX_STICKY_MASK;
5305
+ }
5306
+ modeArray = new Uint8Array(2);
5307
+ const modeDataView = new DataView(modeArray.buffer);
5308
+ modeDataView.setUint16(0, modeToWrite, true);
5309
+ }
5310
+ const payloadLength = 3 + uidBytes.length + gidBytes.length + modeArray.length;
5311
+ rawExtraFieldUnix = new Uint8Array(4 + payloadLength);
5312
+ const rawExtraFieldUnixView = getDataView(rawExtraFieldUnix);
5313
+ setUint16(rawExtraFieldUnixView, 0, unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE ? EXTRAFIELD_TYPE_INFOZIP : EXTRAFIELD_TYPE_UNIX);
5314
+ setUint16(rawExtraFieldUnixView, 2, payloadLength);
5315
+ setUint8(rawExtraFieldUnixView, 4, 1);
5316
+ setUint8(rawExtraFieldUnixView, 5, uidBytes.length);
5317
+ let offset = 6;
5318
+ arraySet(rawExtraFieldUnix, uidBytes, offset);
5319
+ offset += uidBytes.length;
5320
+ setUint8(rawExtraFieldUnixView, offset, gidBytes.length);
5321
+ offset++;
5322
+ arraySet(rawExtraFieldUnix, gidBytes, offset);
5323
+ offset += gidBytes.length;
5324
+ arraySet(rawExtraFieldUnix, modeArray, offset);
5325
+ } else {
5326
+ rawExtraFieldUnix = new Uint8Array();
5327
+ }
5328
+ } catch {
5329
+ rawExtraFieldUnix = new Uint8Array();
5330
+ }
5031
5331
  if (compressionMethod === UNDEFINED_VALUE) {
5032
5332
  compressionMethod = compressed ? COMPRESSION_METHOD_DEFLATE : COMPRESSION_METHOD_STORE;
5033
5333
  }
@@ -5040,7 +5340,7 @@
5040
5340
  compressionMethod = COMPRESSION_METHOD_AES;
5041
5341
  }
5042
5342
  const localExtraFieldZip64Length = zip64ExtraFieldComplete ? getLength(rawExtraFieldZip64) : 0;
5043
- const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
5343
+ const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
5044
5344
  const {
5045
5345
  headerArray,
5046
5346
  headerView,
@@ -5073,6 +5373,8 @@
5073
5373
  localHeaderOffset += getLength(rawExtraFieldExtendedTimestamp);
5074
5374
  arraySet(localHeaderArray, rawExtraFieldNTFS, localHeaderOffset);
5075
5375
  localHeaderOffset += getLength(rawExtraFieldNTFS);
5376
+ arraySet(localHeaderArray, rawExtraFieldUnix, localHeaderOffset);
5377
+ localHeaderOffset += getLength(rawExtraFieldUnix);
5076
5378
  arraySet(localHeaderArray, rawExtraField, localHeaderOffset);
5077
5379
  if (dataDescriptor) {
5078
5380
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + 4, 0);
@@ -5094,6 +5396,7 @@
5094
5396
  localExtraFieldZip64Length,
5095
5397
  rawExtraFieldExtendedTimestamp,
5096
5398
  rawExtraFieldNTFS,
5399
+ rawExtraFieldUnix,
5097
5400
  rawExtraFieldAES,
5098
5401
  extraFieldLength
5099
5402
  };
@@ -5120,6 +5423,46 @@
5120
5423
  entryInfo.metadataSize += extraBytesLength;
5121
5424
  }
5122
5425
 
5426
+ function packUnixId(id) {
5427
+ if (id === UNDEFINED_VALUE) {
5428
+ return new Uint8Array();
5429
+ } else {
5430
+ const dataArray = new Uint8Array(4);
5431
+ const dataView = getDataView(dataArray);
5432
+ dataView.setUint32(0, id, true);
5433
+ let length = 4;
5434
+ while (length > 1 && dataArray[length - 1] === 0) {
5435
+ length--;
5436
+ }
5437
+ return dataArray.subarray(0, length);
5438
+ }
5439
+ }
5440
+
5441
+ function normalizeMsdosAttributes(msdosAttributesRaw, msdosAttributes) {
5442
+ if (msdosAttributesRaw !== UNDEFINED_VALUE) {
5443
+ msdosAttributesRaw = msdosAttributesRaw & MAX_8_BITS;
5444
+ } else if (msdosAttributes !== UNDEFINED_VALUE) {
5445
+ const { readOnly, hidden, system, directory: msdDir, archive } = msdosAttributes;
5446
+ let raw = 0;
5447
+ if (readOnly) raw |= FILE_ATTR_MSDOS_READONLY_MASK;
5448
+ if (hidden) raw |= FILE_ATTR_MSDOS_HIDDEN_MASK;
5449
+ if (system) raw |= FILE_ATTR_MSDOS_SYSTEM_MASK;
5450
+ if (msdDir) raw |= FILE_ATTR_MSDOS_DIR_MASK;
5451
+ if (archive) raw |= FILE_ATTR_MSDOS_ARCHIVE_MASK;
5452
+ msdosAttributesRaw = raw & MAX_8_BITS;
5453
+ }
5454
+ if (msdosAttributes === UNDEFINED_VALUE) {
5455
+ msdosAttributes = {
5456
+ readOnly: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_READONLY_MASK),
5457
+ hidden: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_HIDDEN_MASK),
5458
+ system: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_SYSTEM_MASK),
5459
+ directory: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_DIR_MASK),
5460
+ archive: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_ARCHIVE_MASK)
5461
+ };
5462
+ }
5463
+ return { msdosAttributesRaw, msdosAttributes };
5464
+ }
5465
+
5123
5466
  function getDataDescriptorInfo({
5124
5467
  zip64,
5125
5468
  dataDescriptor,
@@ -5277,6 +5620,7 @@
5277
5620
  rawExtraFieldAES,
5278
5621
  rawComment,
5279
5622
  rawExtraFieldNTFS,
5623
+ rawExtraFieldUnix,
5280
5624
  rawExtraField,
5281
5625
  extendedTimestamp,
5282
5626
  extraFieldExtendedTimestampFlag,
@@ -5301,6 +5645,7 @@
5301
5645
  rawExtraFieldZip64,
5302
5646
  rawExtraFieldAES,
5303
5647
  rawExtraFieldNTFS,
5648
+ rawExtraFieldUnix,
5304
5649
  rawExtraFieldTimestamp,
5305
5650
  rawExtraField);
5306
5651
  }
@@ -5316,6 +5661,7 @@
5316
5661
  rawExtraFieldAES,
5317
5662
  rawExtraFieldExtendedTimestamp,
5318
5663
  rawExtraFieldNTFS,
5664
+ rawExtraFieldUnix,
5319
5665
  rawExtraField,
5320
5666
  rawComment,
5321
5667
  versionMadeBy,
@@ -5332,7 +5678,7 @@
5332
5678
  uncompressedSize,
5333
5679
  compressedSize
5334
5680
  } = fileEntry;
5335
- const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
5681
+ const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
5336
5682
  setUint32(directoryView, offset, CENTRAL_FILE_HEADER_SIGNATURE);
5337
5683
  setUint16(directoryView, offset + 4, versionMadeBy);
5338
5684
  if (!zip64UncompressedSize) {
@@ -5367,9 +5713,12 @@
5367
5713
  directoryOffset += getLength(rawExtraFieldExtendedTimestamp);
5368
5714
  arraySet(directoryArray, rawExtraFieldNTFS, directoryOffset);
5369
5715
  directoryOffset += getLength(rawExtraFieldNTFS);
5716
+ arraySet(directoryArray, rawExtraFieldUnix, directoryOffset);
5717
+ directoryOffset += getLength(rawExtraFieldUnix);
5370
5718
  arraySet(directoryArray, rawExtraField, directoryOffset);
5371
5719
  directoryOffset += getLength(rawExtraField);
5372
5720
  arraySet(directoryArray, rawComment, directoryOffset);
5721
+ directoryOffset += getLength(rawComment);
5373
5722
  if (offset - directoryDiskOffset > writer.availableSize) {
5374
5723
  writer.availableSize = 0;
5375
5724
  await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));