@zip.js/zip.js 2.11.3 → 2.12.0
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/deno.json +1 -1
- package/dist/zip-core-external.js +444 -114
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +454 -111
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +509 -236
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +522 -233
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +509 -236
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +524 -235
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +525 -236
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +456 -113
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +456 -113
- package/dist/zip-native.min.js +1 -1
- package/dist/zip-web-worker-native.js +1 -1
- package/dist/zip-web-worker.js +1 -1
- package/dist/zip.js +457 -114
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +524 -235
- package/index-native.min.js +1 -1
- package/index.cjs +525 -236
- package/index.d.cts +480 -59
- package/index.d.ts +480 -59
- package/index.min.js +1 -1
- package/lib/core/codec-worker-web.js +10 -2
- package/lib/core/codec-worker.js +4 -3
- package/lib/core/configuration.js +20 -5
- package/lib/core/constants.js +2 -0
- package/lib/core/io.js +20 -10
- package/lib/core/options.js +29 -0
- package/lib/core/streams/codec-stream.js +6 -0
- package/lib/core/util/warnings.js +42 -0
- package/lib/core/version.js +1 -1
- package/lib/core/web-worker-base.js +4 -3
- package/lib/core/web-worker-inline-native.js +1 -1
- package/lib/core/web-worker-inline-wasm.js +1 -1
- package/lib/core/zip-entry.js +49 -1
- package/lib/core/zip-fs.js +43 -134
- package/lib/core/zip-reader.js +108 -47
- package/lib/core/zip-writer.js +238 -54
- package/lib/zip-core-base.js +9 -3
- package/lib/zip-core-reader.js +2 -0
- package/lib/zip-core-writer.js +6 -1
- package/lib/zip-module-wasm-base.js +2 -2
- package/package.json +5 -3
package/lib/core/zip-writer.js
CHANGED
|
@@ -154,7 +154,8 @@ import {
|
|
|
154
154
|
OBJECT_TYPE,
|
|
155
155
|
STRING_TYPE,
|
|
156
156
|
FUNCTION_TYPE,
|
|
157
|
-
EMPTY_UINT8_ARRAY
|
|
157
|
+
EMPTY_UINT8_ARRAY,
|
|
158
|
+
SYMBOL_ASYNC_DISPOSE
|
|
158
159
|
} from "./constants.js";
|
|
159
160
|
import { getConfiguration } from "./configuration.js";
|
|
160
161
|
import { getRegisteredCodec, ERR_UNSUPPORTED_COMPRESSION } from "./codec-registry.js";
|
|
@@ -175,6 +176,7 @@ import {
|
|
|
175
176
|
} from "./io.js";
|
|
176
177
|
import { encodeText } from "./util/encode-text.js";
|
|
177
178
|
import { concat, getDataView } from "./util/array.js";
|
|
179
|
+
import { addWarning } from "./util/warnings.js";
|
|
178
180
|
import { toCompatibleReadable, streamToBlob } from "./util/compatible-streams.js";
|
|
179
181
|
import {
|
|
180
182
|
PROPERTY_NAME_LAST_MODIFICATION_DATE,
|
|
@@ -204,7 +206,9 @@ import {
|
|
|
204
206
|
PROPERTY_NAME_STICKY,
|
|
205
207
|
PROPERTY_NAME_MSDOS_ATTRIBUTES,
|
|
206
208
|
PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW,
|
|
207
|
-
Entry
|
|
209
|
+
Entry,
|
|
210
|
+
getEncryptionOverhead,
|
|
211
|
+
getUserExtraField
|
|
208
212
|
} from "./zip-entry.js";
|
|
209
213
|
import {
|
|
210
214
|
OPTION_PASSWORD,
|
|
@@ -238,10 +242,14 @@ import {
|
|
|
238
242
|
ERR_INVALID_PASSWORD_TYPE,
|
|
239
243
|
checkFunctionOption,
|
|
240
244
|
checkSignalOption,
|
|
245
|
+
throwIfAborted,
|
|
241
246
|
checkPasswordOption,
|
|
247
|
+
checkPassThroughOption,
|
|
242
248
|
checkInteger,
|
|
243
249
|
checkIntegerOption,
|
|
244
|
-
toNumber
|
|
250
|
+
toNumber,
|
|
251
|
+
OPTION_ENTRY,
|
|
252
|
+
PASS_THROUGH_COMPRESSED
|
|
245
253
|
} from "./options.js";
|
|
246
254
|
|
|
247
255
|
const ERR_DUPLICATED_NAME = "File already exists";
|
|
@@ -255,7 +263,7 @@ const ERR_INVALID_VERSION = "Version exceeds 65535";
|
|
|
255
263
|
const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
|
|
256
264
|
const ERR_UNSUPPORTED_ENCRYPTION_USDZ = "Encryption is not supported in USDZ files";
|
|
257
265
|
const ERR_UNSUPPORTED_SPLIT_USDZ = "Split zip files are not supported in USDZ files";
|
|
258
|
-
const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set";
|
|
266
|
+
const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set to true (use 'compressed' instead)";
|
|
259
267
|
const ERR_INVALID_EXTRAFIELD = "Invalid extra field (must be a Map)";
|
|
260
268
|
const ERR_INVALID_EXTRAFIELD_TYPE = "Invalid extra field type (must be integer 0..65535)";
|
|
261
269
|
const ERR_INVALID_EXTRAFIELD_DATA_TYPE = "Invalid extra field data (must be a Uint8Array)";
|
|
@@ -267,6 +275,7 @@ const MAX_NTFS_TIME = BigInt("0x7fffffffffffffff");
|
|
|
267
275
|
const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
|
|
268
276
|
const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
|
|
269
277
|
const ERR_UNDEFINED_COMPRESSION_METHOD = "Undefined compression method";
|
|
278
|
+
const ERR_UNDEFINED_CRC32 = "Undefined CRC32";
|
|
270
279
|
const ERR_UNDETERMINED_SIZE = "Undetermined size";
|
|
271
280
|
const ERR_UNDEFINED_READER = "Undefined reader";
|
|
272
281
|
const ERR_INVALID_READER = "Invalid reader (must be a Reader instance, a ReadableStream instance, or an object with a 'readable' property)";
|
|
@@ -280,14 +289,21 @@ const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be intege
|
|
|
280
289
|
const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
|
|
281
290
|
const ERR_INVALID_LEVEL = "Invalid level (must be integer 0..9)";
|
|
282
291
|
const ERR_INVALID_SIGNATURE_DATA = "Signature data exceeds 64KB";
|
|
292
|
+
const ERR_INVALID_ENTRY = "Invalid entry option (must be an entry returned by ZipReader#getEntries())";
|
|
293
|
+
const ERR_ZIP_CRYPTO_LAST_MOD_DATE = "The last modification date of an entry encrypted with ZipCrypto cannot be changed when passThrough is set";
|
|
294
|
+
const WARNING_COMPRESSION_UNAVAILABLE = "compression unavailable";
|
|
295
|
+
const WARNING_CLAMPED_LAST_MODIFICATION_DATE = "clamped last modification date";
|
|
283
296
|
|
|
284
297
|
const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
|
|
285
298
|
const EXTRAFIELD_OFFSET_AES_VENDOR_VERSION = 4;
|
|
286
299
|
const EXTRAFIELD_OFFSET_AES_COMPRESSION_METHOD = 9;
|
|
287
300
|
const EXTRAFIELD_USDZ_MAX_LENGTH = 67;
|
|
301
|
+
const MIN_PRINTABLE_ASCII_CHARACTER_CODE = 0x20;
|
|
302
|
+
const MAX_PRINTABLE_ASCII_CHARACTER_CODE = 0x7e;
|
|
288
303
|
const VENDOR_VERSION_AE_1 = 1;
|
|
289
304
|
const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
|
|
290
305
|
const UNIX_EXTRA_FIELD_TYPE = "unix";
|
|
306
|
+
const LEVEL_BY_BITFLAG_LEVEL = [8, 9, 5, 3];
|
|
291
307
|
const MAX_LEVEL = 9;
|
|
292
308
|
|
|
293
309
|
let workers = 0;
|
|
@@ -314,9 +330,11 @@ class ZipWriter {
|
|
|
314
330
|
initialOffset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : options[OPTION_OFFSET] - (writer.size || writer.writable.size || 0),
|
|
315
331
|
pendingAddFileCalls: new Set(),
|
|
316
332
|
pendingErrors: [],
|
|
333
|
+
warnings: [],
|
|
317
334
|
bufferedWrites: 0,
|
|
318
335
|
directWrites: 0,
|
|
319
|
-
lastFileEntry: UNDEFINED_VALUE
|
|
336
|
+
lastFileEntry: UNDEFINED_VALUE,
|
|
337
|
+
archiveClosed: false
|
|
320
338
|
});
|
|
321
339
|
}
|
|
322
340
|
|
|
@@ -481,6 +499,9 @@ class ZipWriter {
|
|
|
481
499
|
const zipWriter = this;
|
|
482
500
|
const { pendingAddFileCalls, writer } = this;
|
|
483
501
|
const { writable } = writer;
|
|
502
|
+
if (zipWriter.archiveClosed) {
|
|
503
|
+
return getWriterData(writer);
|
|
504
|
+
}
|
|
484
505
|
if (!(comment instanceof Uint8Array)) {
|
|
485
506
|
throw new Error(ERR_INVALID_COMMENT_TYPE);
|
|
486
507
|
}
|
|
@@ -504,11 +525,16 @@ class ZipWriter {
|
|
|
504
525
|
throw error;
|
|
505
526
|
}
|
|
506
527
|
await closeFile(zipWriter, comment, options);
|
|
528
|
+
zipWriter.archiveClosed = true;
|
|
507
529
|
const preventClose = !ownsWritable(writer) && getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
|
|
508
530
|
if (!preventClose) {
|
|
509
531
|
await writable.getWriter().close();
|
|
510
532
|
}
|
|
511
|
-
return writer
|
|
533
|
+
return getWriterData(writer);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
[SYMBOL_ASYNC_DISPOSE]() {
|
|
537
|
+
return this.close();
|
|
512
538
|
}
|
|
513
539
|
}
|
|
514
540
|
|
|
@@ -587,6 +613,10 @@ class WatchedPromise extends Promise {
|
|
|
587
613
|
}
|
|
588
614
|
}
|
|
589
615
|
|
|
616
|
+
function getWriterData(writer) {
|
|
617
|
+
return writer.getData ? writer.getData() : writer.writable;
|
|
618
|
+
}
|
|
619
|
+
|
|
590
620
|
function watchPromiseError(zipWriter, promise) {
|
|
591
621
|
const watchedPromise = new WatchedPromise((resolve, reject) => Promise.prototype.then.call(promise, resolve, reject));
|
|
592
622
|
const watcher = {};
|
|
@@ -605,6 +635,14 @@ async function prependZipEntries(zipWriter, reader) {
|
|
|
605
635
|
|
|
606
636
|
async function addFileEntry(zipWriter, name, reader, options) {
|
|
607
637
|
options = Object.assign({}, options);
|
|
638
|
+
const entry = options[OPTION_ENTRY];
|
|
639
|
+
if (entry !== UNDEFINED_VALUE) {
|
|
640
|
+
const { entryOptions, passThroughOptions } = getSourceEntryOptions(entry,
|
|
641
|
+
checkPassThroughOption(getOptionValue(zipWriter, options, OPTION_PASS_THROUGH)),
|
|
642
|
+
getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE));
|
|
643
|
+
delete options[OPTION_ENTRY];
|
|
644
|
+
options = Object.assign(entryOptions, passThroughOptions, options);
|
|
645
|
+
}
|
|
608
646
|
if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
|
|
609
647
|
name += DIRECTORY_SIGNATURE;
|
|
610
648
|
}
|
|
@@ -655,6 +693,7 @@ export {
|
|
|
655
693
|
ZipWriter,
|
|
656
694
|
ZipWriterStream,
|
|
657
695
|
getEntriesSize,
|
|
696
|
+
getSourceEntryOptions,
|
|
658
697
|
ERR_DUPLICATED_NAME,
|
|
659
698
|
ERR_INVALID_COMMENT,
|
|
660
699
|
ERR_INVALID_COMMENT_TYPE,
|
|
@@ -674,11 +713,14 @@ export {
|
|
|
674
713
|
ERR_UNSUPPORTED_FORMAT,
|
|
675
714
|
ERR_UNDEFINED_UNCOMPRESSED_SIZE,
|
|
676
715
|
ERR_UNDEFINED_COMPRESSION_METHOD,
|
|
716
|
+
ERR_UNDEFINED_CRC32,
|
|
677
717
|
ERR_UNDETERMINED_SIZE,
|
|
678
718
|
ERR_UNDEFINED_READER,
|
|
679
719
|
ERR_INVALID_READER,
|
|
680
720
|
ERR_ZIP_NOT_EMPTY,
|
|
681
721
|
ERR_INVALID_SIGNATURE_DATA,
|
|
722
|
+
ERR_INVALID_ENTRY,
|
|
723
|
+
ERR_ZIP_CRYPTO_LAST_MOD_DATE,
|
|
682
724
|
ERR_INVALID_UID,
|
|
683
725
|
ERR_INVALID_GID,
|
|
684
726
|
ERR_INVALID_UNIX_MODE,
|
|
@@ -688,7 +730,9 @@ export {
|
|
|
688
730
|
ERR_INVALID_MSDOS_DATA,
|
|
689
731
|
ERR_INVALID_LEVEL,
|
|
690
732
|
ERR_INVALID_PASSWORD_TYPE,
|
|
691
|
-
ERR_UNSUPPORTED_CRYPTO_API
|
|
733
|
+
ERR_UNSUPPORTED_CRYPTO_API,
|
|
734
|
+
WARNING_COMPRESSION_UNAVAILABLE,
|
|
735
|
+
WARNING_CLAMPED_LAST_MODIFICATION_DATE
|
|
692
736
|
};
|
|
693
737
|
|
|
694
738
|
async function addFile(zipWriter, name, reader, options) {
|
|
@@ -709,21 +753,33 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
709
753
|
try {
|
|
710
754
|
const { resolvedOptions } = metadataInfo;
|
|
711
755
|
if (resolvedOptions.level != 0 && resolvedOptions.compressionMethod === UNDEFINED_VALUE &&
|
|
712
|
-
!resolvedOptions.
|
|
756
|
+
!resolvedOptions.passThroughCompression && !(await supportsDeflate(getConfiguration()))) {
|
|
713
757
|
resolvedOptions.level = 0;
|
|
758
|
+
addWarning(zipWriter.warnings, WARNING_COMPRESSION_UNAVAILABLE, name);
|
|
714
759
|
}
|
|
715
760
|
const sizesInfo = await resolveSizes(zipWriter, reader, metadataInfo, options);
|
|
716
761
|
({ reader } = sizesInfo);
|
|
717
762
|
const diskOffset = getDiskOffset(zipWriter.writer);
|
|
718
763
|
const diskNumber = getDiskNumber(zipWriter.writer);
|
|
764
|
+
let crc32 = options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32;
|
|
765
|
+
const storesAE2 = sizesInfo.resolvedOptions.encrypted && !resolvedOptions.zipCrypto;
|
|
766
|
+
if (resolvedOptions.passThroughCompression && !resolvedOptions.passThroughEncryption && storesAE2) {
|
|
767
|
+
crc32 = UNDEFINED_VALUE;
|
|
768
|
+
}
|
|
769
|
+
if (resolvedOptions.passThroughCompression && reader && !storesAE2 && crc32 === UNDEFINED_VALUE) {
|
|
770
|
+
throw new Error(ERR_UNDEFINED_CRC32);
|
|
771
|
+
}
|
|
719
772
|
options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
|
|
720
773
|
signature: options[PROPERTY_NAME_SIGNATURE],
|
|
721
|
-
crc32
|
|
774
|
+
crc32,
|
|
722
775
|
offset: zipWriter.offset - diskOffset,
|
|
723
776
|
diskNumberStart: diskNumber,
|
|
724
777
|
[OPTION_USDZ]: zipWriter.options[OPTION_USDZ]
|
|
725
778
|
});
|
|
726
779
|
const headerInfo = getHeaderInfo(options);
|
|
780
|
+
if (headerInfo.lastModDateClamped) {
|
|
781
|
+
addWarning(zipWriter.warnings, WARNING_CLAMPED_LAST_MODIFICATION_DATE, name);
|
|
782
|
+
}
|
|
727
783
|
const dataDescriptorInfo = getDataDescriptorInfo(options);
|
|
728
784
|
const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
|
|
729
785
|
fileEntry = await getFileEntry(zipWriter, name, reader, {
|
|
@@ -750,6 +806,95 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
750
806
|
return new Entry(fileEntry);
|
|
751
807
|
}
|
|
752
808
|
|
|
809
|
+
function getSourceEntryOptions(entry, passThrough, lastModDateOverride) {
|
|
810
|
+
if (entry === null || typeof entry != OBJECT_TYPE || Array.isArray(entry)) {
|
|
811
|
+
throw new Error(ERR_INVALID_ENTRY);
|
|
812
|
+
}
|
|
813
|
+
const {
|
|
814
|
+
externalFileAttributes,
|
|
815
|
+
versionMadeBy,
|
|
816
|
+
comment,
|
|
817
|
+
lastModDate,
|
|
818
|
+
rawLastModDate,
|
|
819
|
+
creationDate,
|
|
820
|
+
lastAccessDate,
|
|
821
|
+
uncompressedSize,
|
|
822
|
+
encrypted,
|
|
823
|
+
zipCrypto,
|
|
824
|
+
crc32,
|
|
825
|
+
compressionMethod,
|
|
826
|
+
extraFieldAES,
|
|
827
|
+
extraFieldUnix,
|
|
828
|
+
internalFileAttributes,
|
|
829
|
+
extraField,
|
|
830
|
+
bitFlag,
|
|
831
|
+
directory,
|
|
832
|
+
uid,
|
|
833
|
+
gid
|
|
834
|
+
} = entry;
|
|
835
|
+
const entryOptions = {
|
|
836
|
+
externalFileAttributes,
|
|
837
|
+
versionMadeBy,
|
|
838
|
+
comment,
|
|
839
|
+
lastModDate,
|
|
840
|
+
creationDate,
|
|
841
|
+
lastAccessDate,
|
|
842
|
+
internalFileAttributes,
|
|
843
|
+
directory
|
|
844
|
+
};
|
|
845
|
+
if (bitFlag && bitFlag.languageEncodingFlag) {
|
|
846
|
+
entryOptions[OPTION_USE_UNICODE_FILE_NAMES] = true;
|
|
847
|
+
}
|
|
848
|
+
const userExtraField = getUserExtraField(extraField);
|
|
849
|
+
if (userExtraField) {
|
|
850
|
+
entryOptions[PROPERTY_NAME_EXTRA_FIELD] = userExtraField;
|
|
851
|
+
}
|
|
852
|
+
if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
|
|
853
|
+
Object.assign(entryOptions, {
|
|
854
|
+
uid,
|
|
855
|
+
gid,
|
|
856
|
+
unixExtraFieldType: extraFieldUnix ? UNIX_EXTRA_FIELD_TYPE : INFOZIP_EXTRA_FIELD_TYPE
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
const passThroughOptions = {};
|
|
860
|
+
if (passThrough && !directory) {
|
|
861
|
+
Object.assign(passThroughOptions, {
|
|
862
|
+
uncompressedSize,
|
|
863
|
+
crc32,
|
|
864
|
+
compressionMethod
|
|
865
|
+
});
|
|
866
|
+
if (passThrough !== PASS_THROUGH_COMPRESSED) {
|
|
867
|
+
Object.assign(passThroughOptions, {
|
|
868
|
+
encrypted,
|
|
869
|
+
zipCrypto,
|
|
870
|
+
encryptionStrength: extraFieldAES ? extraFieldAES.strength : UNDEFINED_VALUE
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
if (bitFlag) {
|
|
874
|
+
passThroughOptions.dataDescriptor = bitFlag.dataDescriptor;
|
|
875
|
+
passThroughOptions[OPTION_LEVEL] = LEVEL_BY_BITFLAG_LEVEL[bitFlag.level];
|
|
876
|
+
}
|
|
877
|
+
if (lastModDateOverride === UNDEFINED_VALUE) {
|
|
878
|
+
passThroughOptions.rawLastModDate = rawLastModDate;
|
|
879
|
+
} else if (passThrough !== PASS_THROUGH_COMPRESSED && zipCrypto && (!bitFlag || bitFlag.dataDescriptor) &&
|
|
880
|
+
lastModDateOverride instanceof Date &&
|
|
881
|
+
getDosTimeHighByte(lastModDateOverride) != ((rawLastModDate >>> 8) & MAX_8_BITS)) {
|
|
882
|
+
throw new Error(ERR_ZIP_CRYPTO_LAST_MOD_DATE);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
return { entryOptions, passThroughOptions };
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
function getDosTimeHighByte(lastModDate) {
|
|
889
|
+
let dosLastModDate = new Date(Math.ceil(Math.floor(lastModDate.getTime() / 1000) / 2) * 2000);
|
|
890
|
+
if (dosLastModDate < MIN_DATE) {
|
|
891
|
+
dosLastModDate = MIN_DATE;
|
|
892
|
+
} else if (dosLastModDate > MAX_DATE) {
|
|
893
|
+
dosLastModDate = MAX_DATE;
|
|
894
|
+
}
|
|
895
|
+
return ((dosLastModDate.getHours() << 3) | (dosLastModDate.getMinutes() >> 3)) & MAX_8_BITS;
|
|
896
|
+
}
|
|
897
|
+
|
|
753
898
|
function resolveAttributes(zipWriter, name, options) {
|
|
754
899
|
let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
|
|
755
900
|
let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? VERSION_MADE_BY_MSDOS : VERSION_MADE_BY_UNIX);
|
|
@@ -903,7 +1048,9 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
903
1048
|
const lastAccessDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
|
|
904
1049
|
const creationDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
|
|
905
1050
|
const internalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, 0);
|
|
906
|
-
const passThrough = getOptionValue(zipWriter, options, OPTION_PASS_THROUGH);
|
|
1051
|
+
const passThrough = checkPassThroughOption(getOptionValue(zipWriter, options, OPTION_PASS_THROUGH));
|
|
1052
|
+
const passThroughCompression = Boolean(passThrough);
|
|
1053
|
+
const passThroughEncryption = passThrough === true;
|
|
907
1054
|
const password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
|
|
908
1055
|
const rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
|
|
909
1056
|
checkPasswordOption(password, rawPassword);
|
|
@@ -918,10 +1065,12 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
918
1065
|
const createTempStream = getFunctionOptionValue(zipWriter, options, OPTION_CREATE_TEMP_STREAM);
|
|
919
1066
|
const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, true);
|
|
920
1067
|
const signal = checkSignalOption(getOptionValue(zipWriter, options, OPTION_SIGNAL));
|
|
921
|
-
|
|
1068
|
+
throwIfAborted(signal);
|
|
1069
|
+
const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES,
|
|
1070
|
+
!isPrintableASCIIText(rawFilename) || !isPrintableASCIIText(rawComment));
|
|
922
1071
|
const compressionMethod = getOptionValue(zipWriter, options, PROPERTY_NAME_COMPRESSION_METHOD);
|
|
923
|
-
const registeredCodec =
|
|
924
|
-
if (!
|
|
1072
|
+
const registeredCodec = passThroughCompression || compressionMethod === UNDEFINED_VALUE ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
|
|
1073
|
+
if (!passThroughCompression && compressionMethod !== UNDEFINED_VALUE &&
|
|
925
1074
|
compressionMethod !== COMPRESSION_METHOD_STORE && compressionMethod !== COMPRESSION_METHOD_DEFLATE && !registeredCodec) {
|
|
926
1075
|
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
927
1076
|
}
|
|
@@ -935,15 +1084,15 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
935
1084
|
level = 0;
|
|
936
1085
|
}
|
|
937
1086
|
}
|
|
938
|
-
if (
|
|
939
|
-
level =
|
|
1087
|
+
if (passThroughCompression) {
|
|
1088
|
+
level = toNumber(options[OPTION_LEVEL]);
|
|
940
1089
|
}
|
|
941
1090
|
let useCompressionStream = getOptionValue(zipWriter, options, OPTION_USE_COMPRESSION_STREAM);
|
|
942
1091
|
let dataDescriptor = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR);
|
|
943
1092
|
if (bufferedWrite && dataDescriptor === UNDEFINED_VALUE) {
|
|
944
1093
|
dataDescriptor = false;
|
|
945
1094
|
}
|
|
946
|
-
if (dataDescriptor === UNDEFINED_VALUE || (zipCrypto && !
|
|
1095
|
+
if (dataDescriptor === UNDEFINED_VALUE || (zipCrypto && !passThroughEncryption)) {
|
|
947
1096
|
dataDescriptor = true;
|
|
948
1097
|
}
|
|
949
1098
|
if (level !== UNDEFINED_VALUE && level != 6) {
|
|
@@ -967,7 +1116,8 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
967
1116
|
lastAccessDate,
|
|
968
1117
|
creationDate,
|
|
969
1118
|
internalFileAttributes,
|
|
970
|
-
|
|
1119
|
+
passThroughCompression,
|
|
1120
|
+
passThroughEncryption,
|
|
971
1121
|
password,
|
|
972
1122
|
rawPassword,
|
|
973
1123
|
encryptionStrength,
|
|
@@ -1028,7 +1178,7 @@ function serializeExtraField(extraField) {
|
|
|
1028
1178
|
}
|
|
1029
1179
|
|
|
1030
1180
|
async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
|
|
1031
|
-
if (metadata.
|
|
1181
|
+
if (metadata.passThroughCompression && !reader && !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY)) {
|
|
1032
1182
|
throw new Error(ERR_UNDEFINED_READER);
|
|
1033
1183
|
}
|
|
1034
1184
|
let contentSize;
|
|
@@ -1044,12 +1194,12 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
|
|
|
1044
1194
|
}
|
|
1045
1195
|
|
|
1046
1196
|
function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options) {
|
|
1047
|
-
const {
|
|
1197
|
+
const { passThroughCompression, passThroughEncryption, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
|
|
1048
1198
|
let { dataDescriptor, zip64, level, compressionMethod } = metadata;
|
|
1049
1199
|
let maximumCompressedSize = 0;
|
|
1050
1200
|
let uncompressedSize = 0;
|
|
1051
1201
|
let unknownSize = false;
|
|
1052
|
-
if (
|
|
1202
|
+
if (passThroughCompression && hasContent) {
|
|
1053
1203
|
uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
|
|
1054
1204
|
if (uncompressedSize === UNDEFINED_VALUE) {
|
|
1055
1205
|
throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
|
|
@@ -1060,17 +1210,17 @@ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options
|
|
|
1060
1210
|
}
|
|
1061
1211
|
const zip64Enabled = zip64 === true;
|
|
1062
1212
|
const encrypted = getOptionValue(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
|
|
1063
|
-
if (hasContent &&
|
|
1213
|
+
if (hasContent && passThroughEncryption && !encrypted && getLength(password, rawPassword)) {
|
|
1064
1214
|
throw new Error(ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH);
|
|
1065
1215
|
}
|
|
1066
|
-
const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (
|
|
1216
|
+
const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThroughEncryption && encrypted));
|
|
1067
1217
|
if (!hasContent) {
|
|
1068
1218
|
level = 0;
|
|
1069
1219
|
compressionMethod = COMPRESSION_METHOD_STORE;
|
|
1070
1220
|
}
|
|
1071
|
-
const encryptionOverhead = encryptedEntry
|
|
1221
|
+
const encryptionOverhead = getEncryptionOverhead(encryptedEntry, zipCrypto, encryptionStrength);
|
|
1072
1222
|
if (hasContent) {
|
|
1073
|
-
if (!
|
|
1223
|
+
if (!passThroughCompression) {
|
|
1074
1224
|
if (contentSize === UNDEFINED_VALUE) {
|
|
1075
1225
|
dataDescriptor = true;
|
|
1076
1226
|
if (zip64 || zip64 === UNDEFINED_VALUE) {
|
|
@@ -1083,10 +1233,12 @@ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options
|
|
|
1083
1233
|
}
|
|
1084
1234
|
} else {
|
|
1085
1235
|
options.uncompressedSize = uncompressedSize;
|
|
1086
|
-
maximumCompressedSize = contentSize === UNDEFINED_VALUE ?
|
|
1236
|
+
maximumCompressedSize = contentSize === UNDEFINED_VALUE ?
|
|
1237
|
+
getMaximumCompressedSize(uncompressedSize) + encryptionOverhead :
|
|
1238
|
+
contentSize + (passThroughEncryption ? 0 : encryptionOverhead);
|
|
1087
1239
|
}
|
|
1088
1240
|
}
|
|
1089
|
-
const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !
|
|
1241
|
+
const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !passThroughCompression)) && !isCompressed(compressionMethod, level);
|
|
1090
1242
|
if (emptyEntry && !zipCrypto && getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR) === UNDEFINED_VALUE) {
|
|
1091
1243
|
dataDescriptor = false;
|
|
1092
1244
|
}
|
|
@@ -1135,6 +1287,8 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1135
1287
|
const initialOffset = writerOptions[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : writerOptions[OPTION_OFFSET];
|
|
1136
1288
|
let offset = initialOffset;
|
|
1137
1289
|
let minimumEntrySize = INFINITY_VALUE;
|
|
1290
|
+
const entrySizes = [];
|
|
1291
|
+
const entriesAlreadyZip64 = new Set();
|
|
1138
1292
|
for (const entry of entries) {
|
|
1139
1293
|
let { name } = entry;
|
|
1140
1294
|
const { size } = entry;
|
|
@@ -1146,7 +1300,7 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1146
1300
|
({ name } = attributesInfo);
|
|
1147
1301
|
const { resolvedOptions: metadata } = resolveMetadata(zipWriter, name, options);
|
|
1148
1302
|
if (metadata.level != 0 && metadata.compressionMethod === UNDEFINED_VALUE &&
|
|
1149
|
-
!metadata.
|
|
1303
|
+
!metadata.passThroughCompression && !(await supportsDeflate(getConfiguration()))) {
|
|
1150
1304
|
metadata.level = 0;
|
|
1151
1305
|
}
|
|
1152
1306
|
const hasContent = !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY);
|
|
@@ -1154,7 +1308,7 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1154
1308
|
throw new Error(ERR_UNDETERMINED_SIZE);
|
|
1155
1309
|
}
|
|
1156
1310
|
const { maximumCompressedSize, resolvedOptions: sizes } = resolveEntrySizes(zipWriter, hasContent, size, metadata, options);
|
|
1157
|
-
if (hasContent && !metadata.
|
|
1311
|
+
if (hasContent && !metadata.passThroughCompression && isCompressed(sizes.compressionMethod, sizes.level)) {
|
|
1158
1312
|
throw new Error(ERR_UNDETERMINED_SIZE);
|
|
1159
1313
|
}
|
|
1160
1314
|
const entryOptions = Object.assign({}, options, attributesInfo.resolvedOptions, metadata, sizes, { [OPTION_USDZ]: usdz });
|
|
@@ -1174,10 +1328,15 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1174
1328
|
compressedSize
|
|
1175
1329
|
}));
|
|
1176
1330
|
const entrySize = entryInfo.metadataSize + compressedSize;
|
|
1331
|
+
entrySizes.push(entrySize);
|
|
1332
|
+
entriesAlreadyZip64.add(Boolean(entryOptions.zip64Enabled ||
|
|
1333
|
+
entryOptions.uncompressedSize >= MAX_32_BITS || compressedSize >= MAX_32_BITS));
|
|
1177
1334
|
minimumEntrySize = Math.min(minimumEntrySize, entrySize);
|
|
1178
1335
|
offset += entrySize;
|
|
1179
1336
|
}
|
|
1180
|
-
const layoutDependsOnWriteOrder = files.size > 1 && (usdz ||
|
|
1337
|
+
const layoutDependsOnWriteOrder = files.size > 1 && (usdz ||
|
|
1338
|
+
(offset - minimumEntrySize >= MAX_32_BITS &&
|
|
1339
|
+
(entriesAlreadyZip64.size > 1 || countEntriesBefore4GB(entrySizes, initialOffset, true) != countEntriesBefore4GB(entrySizes, initialOffset, false))));
|
|
1181
1340
|
if (layoutDependsOnWriteOrder && !writeOrderGuaranteed) {
|
|
1182
1341
|
throw new Error(ERR_UNDETERMINED_SIZE);
|
|
1183
1342
|
}
|
|
@@ -1195,6 +1354,20 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1195
1354
|
return offset - initialOffset + directoryDataLength + commentLength + (zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
|
|
1196
1355
|
}
|
|
1197
1356
|
|
|
1357
|
+
function countEntriesBefore4GB(entrySizes, initialOffset, largestFirst) {
|
|
1358
|
+
const ordered = entrySizes.slice().sort((first, second) => largestFirst ? second - first : first - second);
|
|
1359
|
+
let position = initialOffset;
|
|
1360
|
+
let count = 0;
|
|
1361
|
+
for (const entrySize of ordered) {
|
|
1362
|
+
if (position >= MAX_32_BITS) {
|
|
1363
|
+
break;
|
|
1364
|
+
}
|
|
1365
|
+
position += entrySize;
|
|
1366
|
+
count++;
|
|
1367
|
+
}
|
|
1368
|
+
return count;
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1198
1371
|
async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
1199
1372
|
const {
|
|
1200
1373
|
fileEntries,
|
|
@@ -1370,6 +1543,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1370
1543
|
localExtraFieldZip64Length,
|
|
1371
1544
|
rawExtraFieldExtendedTimestamp,
|
|
1372
1545
|
extraFieldExtendedTimestampFlag,
|
|
1546
|
+
extraFieldExtendedTimestampTime,
|
|
1373
1547
|
rawExtraFieldNTFS,
|
|
1374
1548
|
rawExtraFieldUnix,
|
|
1375
1549
|
rawExtraFieldAES,
|
|
@@ -1382,6 +1556,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1382
1556
|
password,
|
|
1383
1557
|
rawPassword,
|
|
1384
1558
|
level,
|
|
1559
|
+
useUnicodeFileNames,
|
|
1385
1560
|
zip64,
|
|
1386
1561
|
zip64Enabled,
|
|
1387
1562
|
zip64UncompressedSize,
|
|
@@ -1416,7 +1591,8 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1416
1591
|
msdosAttributesRaw,
|
|
1417
1592
|
msdosAttributes,
|
|
1418
1593
|
useCompressionStream,
|
|
1419
|
-
|
|
1594
|
+
passThroughCompression,
|
|
1595
|
+
passThroughEncryption,
|
|
1420
1596
|
format,
|
|
1421
1597
|
codecURI
|
|
1422
1598
|
} = options;
|
|
@@ -1427,9 +1603,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1427
1603
|
zip64Enabled,
|
|
1428
1604
|
directory: Boolean(directory),
|
|
1429
1605
|
executable: Boolean(executable),
|
|
1430
|
-
filenameUTF8:
|
|
1606
|
+
filenameUTF8: Boolean(useUnicodeFileNames),
|
|
1431
1607
|
rawFilename,
|
|
1432
|
-
commentUTF8:
|
|
1608
|
+
commentUTF8: Boolean(useUnicodeFileNames),
|
|
1433
1609
|
rawComment,
|
|
1434
1610
|
rawExtraFieldZip64,
|
|
1435
1611
|
localExtraFieldZip64Length,
|
|
@@ -1460,7 +1636,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1460
1636
|
uncompressedSize
|
|
1461
1637
|
} = options;
|
|
1462
1638
|
let compressedSize = 0;
|
|
1463
|
-
if (!
|
|
1639
|
+
if (!passThroughCompression) {
|
|
1464
1640
|
uncompressedSize = 0;
|
|
1465
1641
|
}
|
|
1466
1642
|
const { writable } = writer;
|
|
@@ -1477,9 +1653,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1477
1653
|
encryptionStrength,
|
|
1478
1654
|
zipCrypto: encrypted && zipCrypto,
|
|
1479
1655
|
passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & MAX_8_BITS,
|
|
1480
|
-
computeCrc32: !
|
|
1481
|
-
compressed: compressed && !
|
|
1482
|
-
encrypted: encrypted && !
|
|
1656
|
+
computeCrc32: !passThroughCompression,
|
|
1657
|
+
compressed: compressed && !passThroughCompression,
|
|
1658
|
+
encrypted: encrypted && !passThroughEncryption,
|
|
1483
1659
|
useWebWorkers,
|
|
1484
1660
|
useCompressionStream,
|
|
1485
1661
|
transferStreams,
|
|
@@ -1494,7 +1670,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1494
1670
|
const result = await runWorker({ readable, writable }, workerOptions);
|
|
1495
1671
|
compressedSize = result.outputSize;
|
|
1496
1672
|
writer.size += compressedSize;
|
|
1497
|
-
if (!
|
|
1673
|
+
if (!passThroughCompression) {
|
|
1498
1674
|
uncompressedSize = result.inputSize;
|
|
1499
1675
|
if (!encrypted || zipCrypto) {
|
|
1500
1676
|
crc32 = result.crc32;
|
|
@@ -1537,8 +1713,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1537
1713
|
headerArray,
|
|
1538
1714
|
headerView,
|
|
1539
1715
|
signature: crc32,
|
|
1540
|
-
crc32: encrypted && !zipCrypto && !
|
|
1716
|
+
crc32: encrypted && !zipCrypto && !passThroughCompression ? UNDEFINED_VALUE : crc32,
|
|
1541
1717
|
extraFieldExtendedTimestampFlag,
|
|
1718
|
+
extraFieldExtendedTimestampTime,
|
|
1542
1719
|
zip64UncompressedSize,
|
|
1543
1720
|
zip64CompressedSize
|
|
1544
1721
|
});
|
|
@@ -1563,7 +1740,7 @@ function getHeaderInfo(options) {
|
|
|
1563
1740
|
encryptionStrength,
|
|
1564
1741
|
extendedTimestamp,
|
|
1565
1742
|
ntfsTimestamp,
|
|
1566
|
-
|
|
1743
|
+
passThroughCompression,
|
|
1567
1744
|
encrypted,
|
|
1568
1745
|
zip64UncompressedSize,
|
|
1569
1746
|
zip64CompressedSize,
|
|
@@ -1574,7 +1751,7 @@ function getHeaderInfo(options) {
|
|
|
1574
1751
|
let { version, compressionMethod } = options;
|
|
1575
1752
|
const compressed = !directory && isCompressed(compressionMethod, level);
|
|
1576
1753
|
let rawLocalExtraFieldZip64;
|
|
1577
|
-
const uncompressedFile =
|
|
1754
|
+
const uncompressedFile = passThroughCompression || !compressed;
|
|
1578
1755
|
const zip64ExtraFieldComplete = zip64 && (options.bufferedWrite || !dataDescriptor || ((!zip64UncompressedSize && !zip64CompressedSize) || (uncompressedFile && !unknownSize)));
|
|
1579
1756
|
const writeLocalExtraFieldZip64 = zip64ExtraFieldComplete || (zip64 && dataDescriptor && (zip64UncompressedSize || zip64CompressedSize));
|
|
1580
1757
|
if (zip64 && (zip64UncompressedSize || zip64CompressedSize)) {
|
|
@@ -1586,8 +1763,8 @@ function getHeaderInfo(options) {
|
|
|
1586
1763
|
if (zip64ExtraFieldComplete) {
|
|
1587
1764
|
extraFieldZip64.writeUint64(uncompressedSize);
|
|
1588
1765
|
if (uncompressedFile) {
|
|
1589
|
-
const encryptionOverhead = encrypted
|
|
1590
|
-
extraFieldZip64.writeUint64(
|
|
1766
|
+
const encryptionOverhead = getEncryptionOverhead(encrypted, zipCrypto, encryptionStrength);
|
|
1767
|
+
extraFieldZip64.writeUint64(passThroughCompression ? 0 : uncompressedSize + encryptionOverhead);
|
|
1591
1768
|
}
|
|
1592
1769
|
}
|
|
1593
1770
|
} else {
|
|
@@ -1606,6 +1783,7 @@ function getHeaderInfo(options) {
|
|
|
1606
1783
|
let rawExtraFieldNTFS;
|
|
1607
1784
|
let rawExtraFieldExtendedTimestamp;
|
|
1608
1785
|
let extraFieldExtendedTimestampFlag;
|
|
1786
|
+
let extraFieldExtendedTimestampTime;
|
|
1609
1787
|
if (extendedTimestamp) {
|
|
1610
1788
|
const lastModTimeUnix = getTimeUnix(lastModDate);
|
|
1611
1789
|
const lastModTimeUnixInRange = inUnixTimeRange(lastModTimeUnix);
|
|
@@ -1613,6 +1791,7 @@ function getHeaderInfo(options) {
|
|
|
1613
1791
|
const extraFieldTimestampLength = 9 + (lastAccessDate ? 4 : 0) + (creationDate ? 4 : 0);
|
|
1614
1792
|
const extraFieldTimestamp = createRecordWriter(extraFieldTimestampLength);
|
|
1615
1793
|
extraFieldExtendedTimestampFlag = 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0);
|
|
1794
|
+
extraFieldExtendedTimestampTime = lastModTimeUnix;
|
|
1616
1795
|
extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
1617
1796
|
extraFieldTimestamp.writeUint16(extraFieldTimestampLength - 4);
|
|
1618
1797
|
extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
|
|
@@ -1696,7 +1875,7 @@ function getHeaderInfo(options) {
|
|
|
1696
1875
|
}
|
|
1697
1876
|
if (encrypted && !zipCrypto) {
|
|
1698
1877
|
version = version > VERSION_AES ? version : VERSION_AES;
|
|
1699
|
-
if (
|
|
1878
|
+
if (passThroughCompression && crc32 !== UNDEFINED_VALUE) {
|
|
1700
1879
|
rawExtraFieldAES[EXTRAFIELD_OFFSET_AES_VENDOR_VERSION] = VENDOR_VERSION_AE_1;
|
|
1701
1880
|
}
|
|
1702
1881
|
setUint16(getDataView(rawExtraFieldAES), EXTRAFIELD_OFFSET_AES_COMPRESSION_METHOD, compressionMethod);
|
|
@@ -1758,12 +1937,14 @@ function getHeaderInfo(options) {
|
|
|
1758
1937
|
headerArray,
|
|
1759
1938
|
headerView,
|
|
1760
1939
|
lastModDate: storedLastModDate,
|
|
1940
|
+
lastModDateClamped: storedLastModDate === clampedLastModDate && dosLastModDate.getTime() != clampedLastModDate.getTime(),
|
|
1761
1941
|
rawLastModDate,
|
|
1762
1942
|
encrypted,
|
|
1763
1943
|
compressed,
|
|
1764
1944
|
version,
|
|
1765
1945
|
compressionMethod,
|
|
1766
1946
|
extraFieldExtendedTimestampFlag,
|
|
1947
|
+
extraFieldExtendedTimestampTime,
|
|
1767
1948
|
rawExtraFieldZip64: EMPTY_UINT8_ARRAY,
|
|
1768
1949
|
localExtraFieldZip64Length,
|
|
1769
1950
|
rawExtraFieldExtendedTimestamp,
|
|
@@ -1866,7 +2047,7 @@ function setEntryInfo({
|
|
|
1866
2047
|
}, {
|
|
1867
2048
|
zip64,
|
|
1868
2049
|
zipCrypto,
|
|
1869
|
-
|
|
2050
|
+
passThroughCompression,
|
|
1870
2051
|
dataDescriptor
|
|
1871
2052
|
}) {
|
|
1872
2053
|
const {
|
|
@@ -1877,7 +2058,7 @@ function setEntryInfo({
|
|
|
1877
2058
|
dataDescriptorView,
|
|
1878
2059
|
dataDescriptorOffset
|
|
1879
2060
|
} = dataDescriptorInfo;
|
|
1880
|
-
if ((!encrypted || zipCrypto ||
|
|
2061
|
+
if ((!encrypted || zipCrypto || passThroughCompression) && crc32 !== UNDEFINED_VALUE) {
|
|
1881
2062
|
setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
|
|
1882
2063
|
if (dataDescriptor) {
|
|
1883
2064
|
setUint32(dataDescriptorView, dataDescriptorOffset, crc32);
|
|
@@ -1908,9 +2089,9 @@ function updateLocalHeader({
|
|
|
1908
2089
|
uncompressedSize,
|
|
1909
2090
|
zip64UncompressedSize,
|
|
1910
2091
|
zip64CompressedSize
|
|
1911
|
-
}, localHeaderView, { dataDescriptor,
|
|
2092
|
+
}, localHeaderView, { dataDescriptor, passThroughCompression }) {
|
|
1912
2093
|
if (!dataDescriptor) {
|
|
1913
|
-
if (!encrypted || (
|
|
2094
|
+
if (!encrypted || (passThroughCompression && crc32 !== UNDEFINED_VALUE)) {
|
|
1914
2095
|
setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, crc32);
|
|
1915
2096
|
}
|
|
1916
2097
|
if (!zip64CompressedSize) {
|
|
@@ -1947,9 +2128,8 @@ function createDirectoryRecords(files) {
|
|
|
1947
2128
|
rawExtraFieldUnix,
|
|
1948
2129
|
rawExtraField,
|
|
1949
2130
|
rawCentralExtraField,
|
|
1950
|
-
extendedTimestamp,
|
|
1951
2131
|
extraFieldExtendedTimestampFlag,
|
|
1952
|
-
|
|
2132
|
+
extraFieldExtendedTimestampTime,
|
|
1953
2133
|
zip64Enabled,
|
|
1954
2134
|
uncompressedSize,
|
|
1955
2135
|
compressedSize
|
|
@@ -1992,16 +2172,15 @@ function createDirectoryRecords(files) {
|
|
|
1992
2172
|
fileEntry.zip64Offset = zip64Offset;
|
|
1993
2173
|
fileEntry.zip64DiskNumberStart = zip64DiskNumberStart;
|
|
1994
2174
|
let rawExtraFieldTimestamp;
|
|
1995
|
-
|
|
1996
|
-
|
|
2175
|
+
if (extraFieldExtendedTimestampTime === UNDEFINED_VALUE) {
|
|
2176
|
+
rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
|
|
2177
|
+
} else {
|
|
1997
2178
|
const extraFieldTimestamp = createRecordWriter(9);
|
|
1998
2179
|
extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
1999
2180
|
extraFieldTimestamp.writeUint16(5);
|
|
2000
2181
|
extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
|
|
2001
|
-
extraFieldTimestamp.writeUint32(
|
|
2182
|
+
extraFieldTimestamp.writeUint32(extraFieldExtendedTimestampTime);
|
|
2002
2183
|
rawExtraFieldTimestamp = extraFieldTimestamp.array;
|
|
2003
|
-
} else {
|
|
2004
|
-
rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
|
|
2005
2184
|
}
|
|
2006
2185
|
fileEntry.rawExtraFieldExtendedTimestamp = rawExtraFieldTimestamp;
|
|
2007
2186
|
const extraFieldLength = getLength(
|
|
@@ -2501,6 +2680,11 @@ function getHeaderArrayData({
|
|
|
2501
2680
|
};
|
|
2502
2681
|
}
|
|
2503
2682
|
|
|
2683
|
+
function isPrintableASCIIText(rawText) {
|
|
2684
|
+
return rawText.every(characterCode =>
|
|
2685
|
+
characterCode >= MIN_PRINTABLE_ASCII_CHARACTER_CODE && characterCode <= MAX_PRINTABLE_ASCII_CHARACTER_CODE);
|
|
2686
|
+
}
|
|
2687
|
+
|
|
2504
2688
|
function getBitFlag(level, useUnicodeFileNames, dataDescriptor, encrypted, compressionMethod) {
|
|
2505
2689
|
let bitFlag = 0;
|
|
2506
2690
|
if (useUnicodeFileNames) {
|