@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.
@@ -32,6 +32,7 @@
32
32
  import {
33
33
  MAX_32_BITS,
34
34
  MAX_16_BITS,
35
+ MAX_8_BITS,
35
36
  COMPRESSION_METHOD_DEFLATE,
36
37
  COMPRESSION_METHOD_DEFLATE_64,
37
38
  COMPRESSION_METHOD_STORE,
@@ -52,6 +53,8 @@ import {
52
53
  EXTRAFIELD_TYPE_NTFS,
53
54
  EXTRAFIELD_TYPE_NTFS_TAG1,
54
55
  EXTRAFIELD_TYPE_USDZ,
56
+ EXTRAFIELD_TYPE_INFOZIP,
57
+ EXTRAFIELD_TYPE_UNIX,
55
58
  END_OF_CENTRAL_DIR_LENGTH,
56
59
  ZIP64_END_OF_CENTRAL_DIR_LENGTH,
57
60
  ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH,
@@ -63,9 +66,16 @@ import {
63
66
  BITFLAG_LEVEL_SUPER_FAST_MASK,
64
67
  BITFLAG_LEVEL_MAX_MASK,
65
68
  FILE_ATTR_MSDOS_DIR_MASK,
69
+ FILE_ATTR_MSDOS_READONLY_MASK,
70
+ FILE_ATTR_MSDOS_HIDDEN_MASK,
71
+ FILE_ATTR_MSDOS_SYSTEM_MASK,
72
+ FILE_ATTR_MSDOS_ARCHIVE_MASK,
66
73
  FILE_ATTR_UNIX_TYPE_DIR,
67
74
  FILE_ATTR_UNIX_EXECUTABLE_MASK,
68
75
  FILE_ATTR_UNIX_DEFAULT_MASK,
76
+ FILE_ATTR_UNIX_SETUID_MASK,
77
+ FILE_ATTR_UNIX_SETGID_MASK,
78
+ FILE_ATTR_UNIX_STICKY_MASK,
69
79
  VERSION_DEFLATE,
70
80
  VERSION_ZIP64,
71
81
  VERSION_AES,
@@ -76,7 +86,8 @@ import {
76
86
  HEADER_OFFSET_UNCOMPRESSED_SIZE,
77
87
  MIN_DATE,
78
88
  MAX_DATE,
79
- UNDEFINED_VALUE
89
+ UNDEFINED_VALUE,
90
+ OBJECT_TYPE
80
91
  } from "./constants.js";
81
92
  import {
82
93
  getConfiguration,
@@ -111,6 +122,14 @@ import {
111
122
  PROPERTY_NAME_COMMENT,
112
123
  PROPERTY_NAME_UNCOMPRESSED_SIZE,
113
124
  PROPERTY_NAME_EXTRA_FIELD,
125
+ PROPERTY_NAME_UID,
126
+ PROPERTY_NAME_GID,
127
+ PROPERTY_NAME_UNIX_MODE,
128
+ PROPERTY_NAME_SETUID,
129
+ PROPERTY_NAME_SETGID,
130
+ PROPERTY_NAME_STICKY,
131
+ PROPERTY_NAME_MSDOS_ATTRIBUTES,
132
+ PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW,
114
133
  Entry
115
134
  } from "./zip-entry.js";
116
135
  import {
@@ -132,7 +151,8 @@ import {
132
151
  OPTION_SUPPORT_ZIP64_SPLIT_FILE,
133
152
  OPTION_ENCODE_TEXT,
134
153
  OPTION_OFFSET,
135
- OPTION_USDZ
154
+ OPTION_USDZ,
155
+ OPTION_UNIX_EXTRA_FIELD_TYPE
136
156
  } from "./options.js";
137
157
  import {
138
158
  ZipReader
@@ -149,8 +169,16 @@ const ERR_INVALID_EXTRAFIELD_DATA = "Extra field data exceeds 64KB";
149
169
  const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (make sure 'keepOrder' is set to 'true')";
150
170
  const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
151
171
  const ERR_ZIP_NOT_EMPTY = "Zip file not empty";
172
+ const ERR_INVALID_UID = "Invalid uid (must be integer 0..2^32-1)";
173
+ const ERR_INVALID_GID = "Invalid gid (must be integer 0..2^32-1)";
174
+ const ERR_INVALID_UNIX_MODE = "Invalid UNIX mode (must be integer 0..65535)";
175
+ const ERR_INVALID_UNIX_EXTRA_FIELD_TYPE = "Invalid unixExtraFieldType (must be 'infozip' or 'unix')";
176
+ const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be integer 0..255)";
177
+ const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
152
178
 
153
179
  const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
180
+ const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
181
+ const UNIX_EXTRA_FIELD_TYPE = "unix";
154
182
 
155
183
  let workers = 0;
156
184
  const pendingEntries = [];
@@ -208,15 +236,17 @@ class ZipWriter {
208
236
  rawExtraFieldAES,
209
237
  rawExtraFieldExtendedTimestamp,
210
238
  rawExtraFieldNTFS,
211
- rawExtraField
239
+ rawExtraFieldUnix,
240
+ rawExtraField,
212
241
  } = entry;
213
242
  const { level, languageEncodingFlag, dataDescriptor } = bitFlag;
214
243
  rawExtraFieldZip64 = rawExtraFieldZip64 || new Uint8Array();
215
244
  rawExtraFieldAES = rawExtraFieldAES || new Uint8Array();
216
245
  rawExtraFieldExtendedTimestamp = rawExtraFieldExtendedTimestamp || new Uint8Array();
217
246
  rawExtraFieldNTFS = rawExtraFieldNTFS || new Uint8Array();
247
+ rawExtraFieldUnix = entry.rawExtraFieldUnix || new Uint8Array();
218
248
  rawExtraField = rawExtraField || new Uint8Array();
219
- const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
249
+ const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
220
250
  const zip64UncompressedSize = zip64 && uncompressedSize > MAX_32_BITS;
221
251
  const zip64CompressedSize = zip64 && compressedSize > MAX_32_BITS;
222
252
  const {
@@ -243,6 +273,7 @@ class ZipWriter {
243
273
  rawExtraFieldAES,
244
274
  rawExtraFieldExtendedTimestamp,
245
275
  rawExtraFieldNTFS,
276
+ rawExtraFieldUnix,
246
277
  rawExtraField,
247
278
  extendedTimestamp: rawExtraFieldExtendedTimestamp.length > 0 || rawExtraFieldNTFS.length > 0,
248
279
  extraFieldExtendedTimestampFlag: 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0),
@@ -311,7 +342,7 @@ class ZipWriter {
311
342
  while (pendingAddFileCalls.size) {
312
343
  await Promise.allSettled(Array.from(pendingAddFileCalls));
313
344
  }
314
- await closeFile(this, comment, options);
345
+ await closeFile(zipWriter, comment, options);
315
346
  const preventClose = getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
316
347
  if (!preventClose) {
317
348
  await writable.getWriter().close();
@@ -342,7 +373,7 @@ class ZipWriterStream {
342
373
  return writable;
343
374
  }
344
375
 
345
- close(comment = undefined, options = {}) {
376
+ close(comment = UNDEFINED_VALUE, options = {}) {
346
377
  return this.zipWriter.close(comment, options);
347
378
  }
348
379
  }
@@ -365,9 +396,45 @@ export {
365
396
 
366
397
  async function addFile(zipWriter, name, reader, options) {
367
398
  name = name.trim();
368
- const msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
369
- const versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
399
+ let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
400
+ let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
370
401
  const executable = getOptionValue(zipWriter, options, PROPERTY_NAME_EXECUTABLE);
402
+ const uid = getOptionValue(zipWriter, options, PROPERTY_NAME_UID);
403
+ const gid = getOptionValue(zipWriter, options, PROPERTY_NAME_GID);
404
+ let unixMode = getOptionValue(zipWriter, options, PROPERTY_NAME_UNIX_MODE);
405
+ const unixExtraFieldType = getOptionValue(zipWriter, options, OPTION_UNIX_EXTRA_FIELD_TYPE);
406
+ let setuid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETUID);
407
+ let setgid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETGID);
408
+ let sticky = getOptionValue(zipWriter, options, PROPERTY_NAME_STICKY);
409
+ if (uid !== UNDEFINED_VALUE && (uid < 0 || uid > MAX_32_BITS)) {
410
+ throw new Error(ERR_INVALID_UID);
411
+ }
412
+ if (gid !== UNDEFINED_VALUE && (gid < 0 || gid > MAX_32_BITS)) {
413
+ throw new Error(ERR_INVALID_GID);
414
+ }
415
+ if (unixMode !== UNDEFINED_VALUE && (unixMode < 0 || unixMode > MAX_16_BITS)) {
416
+ throw new Error(ERR_INVALID_UNIX_MODE);
417
+ }
418
+ if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
419
+ throw new Error(ERR_INVALID_UNIX_EXTRA_FIELD_TYPE);
420
+ }
421
+ let msdosAttributesRaw = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
422
+ let msdosAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES);
423
+ const hasUnixMetadata = uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE || unixExtraFieldType;
424
+ const hasMsDosProvided = msdosAttributesRaw !== UNDEFINED_VALUE || msdosAttributes !== UNDEFINED_VALUE;
425
+ if (hasUnixMetadata) {
426
+ msDosCompatible = false;
427
+ versionMadeBy = (versionMadeBy & MAX_16_BITS) | (3 << 8);
428
+ } else if (hasMsDosProvided) {
429
+ msDosCompatible = true;
430
+ versionMadeBy = (versionMadeBy & MAX_8_BITS);
431
+ }
432
+ if (msdosAttributesRaw !== UNDEFINED_VALUE && (msdosAttributesRaw < 0 || msdosAttributesRaw > MAX_8_BITS)) {
433
+ throw new Error(ERR_INVALID_MSDOS_ATTRIBUTES);
434
+ }
435
+ if (msdosAttributes && typeof msdosAttributes !== OBJECT_TYPE) {
436
+ throw new Error(ERR_INVALID_MSDOS_DATA);
437
+ }
371
438
  if (versionMadeBy > MAX_16_BITS) {
372
439
  throw new Error(ERR_INVALID_VERSION);
373
440
  }
@@ -393,6 +460,34 @@ async function addFile(zipWriter, name, reader, options) {
393
460
  externalFileAttributes = FILE_ATTR_UNIX_DEFAULT_MASK << 16;
394
461
  }
395
462
  }
463
+ let unixExternalUpper;
464
+ if (!msDosCompatible) {
465
+ unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
466
+ unixMode = unixMode === UNDEFINED_VALUE ? unixExternalUpper : (unixMode & MAX_16_BITS);
467
+ if (setuid) {
468
+ unixMode |= FILE_ATTR_UNIX_SETUID_MASK;
469
+ } else {
470
+ setuid = Boolean(unixMode & FILE_ATTR_UNIX_SETUID_MASK);
471
+ }
472
+ if (setgid) {
473
+ unixMode |= FILE_ATTR_UNIX_SETGID_MASK;
474
+ } else {
475
+ setgid = Boolean(unixMode & FILE_ATTR_UNIX_SETGID_MASK);
476
+ }
477
+ if (sticky) {
478
+ unixMode |= FILE_ATTR_UNIX_STICKY_MASK;
479
+ } else {
480
+ sticky = Boolean(unixMode & FILE_ATTR_UNIX_STICKY_MASK);
481
+ }
482
+ if (directory) {
483
+ unixMode |= FILE_ATTR_UNIX_TYPE_DIR;
484
+ }
485
+ externalFileAttributes = ((unixMode & MAX_16_BITS) << 16) | (externalFileAttributes & MAX_8_BITS);
486
+ }
487
+ ({ msdosAttributesRaw, msdosAttributes } = normalizeMsdosAttributes(msdosAttributesRaw, msdosAttributes));
488
+ if (hasMsDosProvided) {
489
+ externalFileAttributes = (externalFileAttributes & MAX_32_BITS) | (msdosAttributesRaw & MAX_8_BITS);
490
+ }
396
491
  const encode = getOptionValue(zipWriter, options, OPTION_ENCODE_TEXT, encodeText);
397
492
  let rawFilename = encode(name);
398
493
  if (rawFilename === UNDEFINED_VALUE) {
@@ -555,7 +650,16 @@ async function addFile(zipWriter, name, reader, options) {
555
650
  compressionMethod,
556
651
  uncompressedSize,
557
652
  offset: zipWriter.offset - diskOffset,
558
- diskNumberStart: diskNumber
653
+ diskNumberStart: diskNumber,
654
+ uid,
655
+ gid,
656
+ setuid,
657
+ setgid,
658
+ sticky,
659
+ unixMode,
660
+ msdosAttributesRaw,
661
+ msdosAttributes,
662
+ unixExternalUpper
559
663
  });
560
664
  const headerInfo = getHeaderInfo(options);
561
665
  const dataDescriptorInfo = getDataDescriptorInfo(options);
@@ -747,7 +851,8 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
747
851
  rawExtraFieldExtendedTimestamp,
748
852
  extraFieldExtendedTimestampFlag,
749
853
  rawExtraFieldNTFS,
750
- rawExtraFieldAES
854
+ rawExtraFieldUnix,
855
+ rawExtraFieldAES,
751
856
  } = headerInfo;
752
857
  const { dataDescriptorArray } = dataDescriptorInfo;
753
858
  const {
@@ -779,6 +884,15 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
779
884
  msDosCompatible,
780
885
  internalFileAttributes,
781
886
  externalFileAttributes,
887
+ uid,
888
+ gid,
889
+ unixMode,
890
+ setuid,
891
+ setgid,
892
+ sticky,
893
+ unixExternalUpper,
894
+ msdosAttributesRaw,
895
+ msdosAttributes,
782
896
  useCompressionStream,
783
897
  passThrough
784
898
  } = options;
@@ -796,13 +910,23 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
796
910
  localExtraFieldZip64Length,
797
911
  rawExtraFieldExtendedTimestamp,
798
912
  rawExtraFieldNTFS,
913
+ rawExtraFieldUnix,
799
914
  rawExtraFieldAES,
800
915
  rawExtraField,
801
916
  extendedTimestamp,
802
917
  msDosCompatible,
803
918
  internalFileAttributes,
804
919
  externalFileAttributes,
805
- diskNumberStart
920
+ diskNumberStart,
921
+ uid,
922
+ gid,
923
+ unixMode,
924
+ setuid,
925
+ setgid,
926
+ sticky,
927
+ unixExternalUpper,
928
+ msdosAttributesRaw,
929
+ msdosAttributes
806
930
  };
807
931
  let {
808
932
  signature,
@@ -825,7 +949,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
825
949
  password,
826
950
  encryptionStrength,
827
951
  zipCrypto: encrypted && zipCrypto,
828
- passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & 0xFF,
952
+ passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & MAX_8_BITS,
829
953
  signed: !passThrough,
830
954
  compressed: compressed && !passThrough,
831
955
  encrypted: encrypted && !passThrough,
@@ -1004,6 +1128,49 @@ function getHeaderInfo(options) {
1004
1128
  } else {
1005
1129
  rawExtraFieldNTFS = rawExtraFieldExtendedTimestamp = new Uint8Array();
1006
1130
  }
1131
+ let rawExtraFieldUnix;
1132
+ try {
1133
+ const { uid, gid, unixMode, setuid, setgid, sticky, unixExtraFieldType } = options;
1134
+ if (unixExtraFieldType && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE)) {
1135
+ const uidBytes = packUnixId(uid);
1136
+ const gidBytes = packUnixId(gid);
1137
+ let modeArray = new Uint8Array();
1138
+ if (unixExtraFieldType == UNIX_EXTRA_FIELD_TYPE && unixMode !== UNDEFINED_VALUE) {
1139
+ let modeToWrite = unixMode & MAX_16_BITS;
1140
+ if (setuid) {
1141
+ modeToWrite |= FILE_ATTR_UNIX_SETUID_MASK;
1142
+ }
1143
+ if (setgid) {
1144
+ modeToWrite |= FILE_ATTR_UNIX_SETGID_MASK;
1145
+ }
1146
+ if (sticky) {
1147
+ modeToWrite |= FILE_ATTR_UNIX_STICKY_MASK;
1148
+ }
1149
+ modeArray = new Uint8Array(2);
1150
+ const modeDataView = new DataView(modeArray.buffer);
1151
+ modeDataView.setUint16(0, modeToWrite, true);
1152
+ }
1153
+ const payloadLength = 3 + uidBytes.length + gidBytes.length + modeArray.length;
1154
+ rawExtraFieldUnix = new Uint8Array(4 + payloadLength);
1155
+ const rawExtraFieldUnixView = getDataView(rawExtraFieldUnix);
1156
+ setUint16(rawExtraFieldUnixView, 0, unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE ? EXTRAFIELD_TYPE_INFOZIP : EXTRAFIELD_TYPE_UNIX);
1157
+ setUint16(rawExtraFieldUnixView, 2, payloadLength);
1158
+ setUint8(rawExtraFieldUnixView, 4, 1);
1159
+ setUint8(rawExtraFieldUnixView, 5, uidBytes.length);
1160
+ let offset = 6;
1161
+ arraySet(rawExtraFieldUnix, uidBytes, offset);
1162
+ offset += uidBytes.length;
1163
+ setUint8(rawExtraFieldUnixView, offset, gidBytes.length);
1164
+ offset++;
1165
+ arraySet(rawExtraFieldUnix, gidBytes, offset);
1166
+ offset += gidBytes.length;
1167
+ arraySet(rawExtraFieldUnix, modeArray, offset);
1168
+ } else {
1169
+ rawExtraFieldUnix = new Uint8Array();
1170
+ }
1171
+ } catch {
1172
+ rawExtraFieldUnix = new Uint8Array();
1173
+ }
1007
1174
  if (compressionMethod === UNDEFINED_VALUE) {
1008
1175
  compressionMethod = compressed ? COMPRESSION_METHOD_DEFLATE : COMPRESSION_METHOD_STORE;
1009
1176
  }
@@ -1016,7 +1183,7 @@ function getHeaderInfo(options) {
1016
1183
  compressionMethod = COMPRESSION_METHOD_AES;
1017
1184
  }
1018
1185
  const localExtraFieldZip64Length = zip64ExtraFieldComplete ? getLength(rawExtraFieldZip64) : 0;
1019
- const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
1186
+ const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
1020
1187
  const {
1021
1188
  headerArray,
1022
1189
  headerView,
@@ -1049,6 +1216,8 @@ function getHeaderInfo(options) {
1049
1216
  localHeaderOffset += getLength(rawExtraFieldExtendedTimestamp);
1050
1217
  arraySet(localHeaderArray, rawExtraFieldNTFS, localHeaderOffset);
1051
1218
  localHeaderOffset += getLength(rawExtraFieldNTFS);
1219
+ arraySet(localHeaderArray, rawExtraFieldUnix, localHeaderOffset);
1220
+ localHeaderOffset += getLength(rawExtraFieldUnix);
1052
1221
  arraySet(localHeaderArray, rawExtraField, localHeaderOffset);
1053
1222
  if (dataDescriptor) {
1054
1223
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + 4, 0);
@@ -1070,6 +1239,7 @@ function getHeaderInfo(options) {
1070
1239
  localExtraFieldZip64Length,
1071
1240
  rawExtraFieldExtendedTimestamp,
1072
1241
  rawExtraFieldNTFS,
1242
+ rawExtraFieldUnix,
1073
1243
  rawExtraFieldAES,
1074
1244
  extraFieldLength
1075
1245
  };
@@ -1096,6 +1266,46 @@ function appendExtraFieldUSDZ(entryInfo, zipWriterOffset) {
1096
1266
  entryInfo.metadataSize += extraBytesLength;
1097
1267
  }
1098
1268
 
1269
+ function packUnixId(id) {
1270
+ if (id === UNDEFINED_VALUE) {
1271
+ return new Uint8Array();
1272
+ } else {
1273
+ const dataArray = new Uint8Array(4);
1274
+ const dataView = getDataView(dataArray);
1275
+ dataView.setUint32(0, id, true);
1276
+ let length = 4;
1277
+ while (length > 1 && dataArray[length - 1] === 0) {
1278
+ length--;
1279
+ }
1280
+ return dataArray.subarray(0, length);
1281
+ }
1282
+ }
1283
+
1284
+ function normalizeMsdosAttributes(msdosAttributesRaw, msdosAttributes) {
1285
+ if (msdosAttributesRaw !== UNDEFINED_VALUE) {
1286
+ msdosAttributesRaw = msdosAttributesRaw & MAX_8_BITS;
1287
+ } else if (msdosAttributes !== UNDEFINED_VALUE) {
1288
+ const { readOnly, hidden, system, directory: msdDir, archive } = msdosAttributes;
1289
+ let raw = 0;
1290
+ if (readOnly) raw |= FILE_ATTR_MSDOS_READONLY_MASK;
1291
+ if (hidden) raw |= FILE_ATTR_MSDOS_HIDDEN_MASK;
1292
+ if (system) raw |= FILE_ATTR_MSDOS_SYSTEM_MASK;
1293
+ if (msdDir) raw |= FILE_ATTR_MSDOS_DIR_MASK;
1294
+ if (archive) raw |= FILE_ATTR_MSDOS_ARCHIVE_MASK;
1295
+ msdosAttributesRaw = raw & MAX_8_BITS;
1296
+ }
1297
+ if (msdosAttributes === UNDEFINED_VALUE) {
1298
+ msdosAttributes = {
1299
+ readOnly: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_READONLY_MASK),
1300
+ hidden: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_HIDDEN_MASK),
1301
+ system: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_SYSTEM_MASK),
1302
+ directory: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_DIR_MASK),
1303
+ archive: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_ARCHIVE_MASK)
1304
+ };
1305
+ }
1306
+ return { msdosAttributesRaw, msdosAttributes };
1307
+ }
1308
+
1099
1309
  function getDataDescriptorInfo({
1100
1310
  zip64,
1101
1311
  dataDescriptor,
@@ -1253,6 +1463,7 @@ async function closeFile(zipWriter, comment, options) {
1253
1463
  rawExtraFieldAES,
1254
1464
  rawComment,
1255
1465
  rawExtraFieldNTFS,
1466
+ rawExtraFieldUnix,
1256
1467
  rawExtraField,
1257
1468
  extendedTimestamp,
1258
1469
  extraFieldExtendedTimestampFlag,
@@ -1277,6 +1488,7 @@ async function closeFile(zipWriter, comment, options) {
1277
1488
  rawExtraFieldZip64,
1278
1489
  rawExtraFieldAES,
1279
1490
  rawExtraFieldNTFS,
1491
+ rawExtraFieldUnix,
1280
1492
  rawExtraFieldTimestamp,
1281
1493
  rawExtraField);
1282
1494
  }
@@ -1292,6 +1504,7 @@ async function closeFile(zipWriter, comment, options) {
1292
1504
  rawExtraFieldAES,
1293
1505
  rawExtraFieldExtendedTimestamp,
1294
1506
  rawExtraFieldNTFS,
1507
+ rawExtraFieldUnix,
1295
1508
  rawExtraField,
1296
1509
  rawComment,
1297
1510
  versionMadeBy,
@@ -1308,7 +1521,7 @@ async function closeFile(zipWriter, comment, options) {
1308
1521
  uncompressedSize,
1309
1522
  compressedSize
1310
1523
  } = fileEntry;
1311
- const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
1524
+ const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
1312
1525
  setUint32(directoryView, offset, CENTRAL_FILE_HEADER_SIGNATURE);
1313
1526
  setUint16(directoryView, offset + 4, versionMadeBy);
1314
1527
  if (!zip64UncompressedSize) {
@@ -1343,9 +1556,12 @@ async function closeFile(zipWriter, comment, options) {
1343
1556
  directoryOffset += getLength(rawExtraFieldExtendedTimestamp);
1344
1557
  arraySet(directoryArray, rawExtraFieldNTFS, directoryOffset);
1345
1558
  directoryOffset += getLength(rawExtraFieldNTFS);
1559
+ arraySet(directoryArray, rawExtraFieldUnix, directoryOffset);
1560
+ directoryOffset += getLength(rawExtraFieldUnix);
1346
1561
  arraySet(directoryArray, rawExtraField, directoryOffset);
1347
1562
  directoryOffset += getLength(rawExtraField);
1348
1563
  arraySet(directoryArray, rawComment, directoryOffset);
1564
+ directoryOffset += getLength(rawComment);
1349
1565
  if (offset - directoryDiskOffset > writer.availableSize) {
1350
1566
  writer.availableSize = 0;
1351
1567
  await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "A JavaScript library to zip and unzip files in the browser, Deno and Node.js",
4
4
  "author": "Gildas Lormeau",
5
5
  "license": "BSD-3-Clause",
6
- "version": "2.8.6",
6
+ "version": "2.8.8",
7
7
  "type": "module",
8
8
  "keywords": [
9
9
  "zip",
@@ -156,10 +156,10 @@
156
156
  "devDependencies": {
157
157
  "@rollup/plugin-replace": "^6.0.2",
158
158
  "@rollup/plugin-terser": "^0.4.4",
159
- "eslint": "^9.36.0",
159
+ "eslint": "^9.37.0",
160
160
  "http-server": "^14.1.1",
161
- "rollup": "^4.52.3",
162
- "typedoc": "^0.28.13",
161
+ "rollup": "^4.52.4",
162
+ "typedoc": "^0.28.14",
163
163
  "typedoc-plugin-markdown": "^4.9.0"
164
164
  }
165
165
  }