@zip.js/zip.js 2.11.4 → 2.13.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 +549 -139
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +559 -136
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +615 -260
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +628 -257
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +615 -260
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +630 -259
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +631 -260
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +561 -138
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +561 -138
- 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 +562 -139
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +630 -259
- package/index-native.min.js +1 -1
- package/index.cjs +631 -260
- package/index.d.cts +474 -59
- package/index.d.ts +474 -59
- package/index.min.js +1 -1
- package/lib/core/codec-worker-web.js +72 -22
- package/lib/core/codec-worker.js +18 -5
- package/lib/core/configuration.js +20 -5
- package/lib/core/constants.js +2 -0
- package/lib/core/io.js +13 -5
- package/lib/core/options.js +16 -0
- package/lib/core/streams/codec-stream.js +6 -0
- package/lib/core/util/error.js +35 -0
- package/lib/core/util/warnings.js +42 -0
- package/lib/core/version.js +1 -1
- package/lib/core/web-worker-base.js +46 -9
- 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 +45 -133
- package/lib/core/zip-reader.js +115 -52
- package/lib/core/zip-writer.js +244 -57
- 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/worker-message-property-names.js +1 -1
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,7 +176,9 @@ 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";
|
|
181
|
+
import { isErrorObject } from "./util/error.js";
|
|
179
182
|
import {
|
|
180
183
|
PROPERTY_NAME_LAST_MODIFICATION_DATE,
|
|
181
184
|
PROPERTY_NAME_RAW_LAST_MODIFICATION_DATE,
|
|
@@ -204,7 +207,9 @@ import {
|
|
|
204
207
|
PROPERTY_NAME_STICKY,
|
|
205
208
|
PROPERTY_NAME_MSDOS_ATTRIBUTES,
|
|
206
209
|
PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW,
|
|
207
|
-
Entry
|
|
210
|
+
Entry,
|
|
211
|
+
getEncryptionOverhead,
|
|
212
|
+
getUserExtraField
|
|
208
213
|
} from "./zip-entry.js";
|
|
209
214
|
import {
|
|
210
215
|
OPTION_PASSWORD,
|
|
@@ -240,9 +245,12 @@ import {
|
|
|
240
245
|
checkSignalOption,
|
|
241
246
|
throwIfAborted,
|
|
242
247
|
checkPasswordOption,
|
|
248
|
+
checkPassThroughOption,
|
|
243
249
|
checkInteger,
|
|
244
250
|
checkIntegerOption,
|
|
245
|
-
toNumber
|
|
251
|
+
toNumber,
|
|
252
|
+
OPTION_ENTRY,
|
|
253
|
+
PASS_THROUGH_COMPRESSED
|
|
246
254
|
} from "./options.js";
|
|
247
255
|
|
|
248
256
|
const ERR_DUPLICATED_NAME = "File already exists";
|
|
@@ -256,7 +264,7 @@ const ERR_INVALID_VERSION = "Version exceeds 65535";
|
|
|
256
264
|
const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
|
|
257
265
|
const ERR_UNSUPPORTED_ENCRYPTION_USDZ = "Encryption is not supported in USDZ files";
|
|
258
266
|
const ERR_UNSUPPORTED_SPLIT_USDZ = "Split zip files are not supported in USDZ files";
|
|
259
|
-
const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set";
|
|
267
|
+
const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set to true (use 'compressed' instead)";
|
|
260
268
|
const ERR_INVALID_EXTRAFIELD = "Invalid extra field (must be a Map)";
|
|
261
269
|
const ERR_INVALID_EXTRAFIELD_TYPE = "Invalid extra field type (must be integer 0..65535)";
|
|
262
270
|
const ERR_INVALID_EXTRAFIELD_DATA_TYPE = "Invalid extra field data (must be a Uint8Array)";
|
|
@@ -268,6 +276,7 @@ const MAX_NTFS_TIME = BigInt("0x7fffffffffffffff");
|
|
|
268
276
|
const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
|
|
269
277
|
const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
|
|
270
278
|
const ERR_UNDEFINED_COMPRESSION_METHOD = "Undefined compression method";
|
|
279
|
+
const ERR_UNDEFINED_CRC32 = "Undefined CRC32";
|
|
271
280
|
const ERR_UNDETERMINED_SIZE = "Undetermined size";
|
|
272
281
|
const ERR_UNDEFINED_READER = "Undefined reader";
|
|
273
282
|
const ERR_INVALID_READER = "Invalid reader (must be a Reader instance, a ReadableStream instance, or an object with a 'readable' property)";
|
|
@@ -281,14 +290,21 @@ const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be intege
|
|
|
281
290
|
const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
|
|
282
291
|
const ERR_INVALID_LEVEL = "Invalid level (must be integer 0..9)";
|
|
283
292
|
const ERR_INVALID_SIGNATURE_DATA = "Signature data exceeds 64KB";
|
|
293
|
+
const ERR_INVALID_ENTRY = "Invalid entry option (must be an entry returned by ZipReader#getEntries())";
|
|
294
|
+
const ERR_ZIP_CRYPTO_LAST_MOD_DATE = "The last modification date of an entry encrypted with ZipCrypto cannot be changed when passThrough is set";
|
|
295
|
+
const WARNING_COMPRESSION_UNAVAILABLE = "compression unavailable";
|
|
296
|
+
const WARNING_CLAMPED_LAST_MODIFICATION_DATE = "clamped last modification date";
|
|
284
297
|
|
|
285
298
|
const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
|
|
286
299
|
const EXTRAFIELD_OFFSET_AES_VENDOR_VERSION = 4;
|
|
287
300
|
const EXTRAFIELD_OFFSET_AES_COMPRESSION_METHOD = 9;
|
|
288
301
|
const EXTRAFIELD_USDZ_MAX_LENGTH = 67;
|
|
302
|
+
const MIN_PRINTABLE_ASCII_CHARACTER_CODE = 0x20;
|
|
303
|
+
const MAX_PRINTABLE_ASCII_CHARACTER_CODE = 0x7e;
|
|
289
304
|
const VENDOR_VERSION_AE_1 = 1;
|
|
290
305
|
const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
|
|
291
306
|
const UNIX_EXTRA_FIELD_TYPE = "unix";
|
|
307
|
+
const LEVEL_BY_BITFLAG_LEVEL = [8, 9, 5, 3];
|
|
292
308
|
const MAX_LEVEL = 9;
|
|
293
309
|
|
|
294
310
|
let workers = 0;
|
|
@@ -315,9 +331,11 @@ class ZipWriter {
|
|
|
315
331
|
initialOffset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : options[OPTION_OFFSET] - (writer.size || writer.writable.size || 0),
|
|
316
332
|
pendingAddFileCalls: new Set(),
|
|
317
333
|
pendingErrors: [],
|
|
334
|
+
warnings: [],
|
|
318
335
|
bufferedWrites: 0,
|
|
319
336
|
directWrites: 0,
|
|
320
|
-
lastFileEntry: UNDEFINED_VALUE
|
|
337
|
+
lastFileEntry: UNDEFINED_VALUE,
|
|
338
|
+
archiveClosed: false
|
|
321
339
|
});
|
|
322
340
|
}
|
|
323
341
|
|
|
@@ -482,6 +500,9 @@ class ZipWriter {
|
|
|
482
500
|
const zipWriter = this;
|
|
483
501
|
const { pendingAddFileCalls, writer } = this;
|
|
484
502
|
const { writable } = writer;
|
|
503
|
+
if (zipWriter.archiveClosed) {
|
|
504
|
+
return getWriterData(writer);
|
|
505
|
+
}
|
|
485
506
|
if (!(comment instanceof Uint8Array)) {
|
|
486
507
|
throw new Error(ERR_INVALID_COMMENT_TYPE);
|
|
487
508
|
}
|
|
@@ -492,7 +513,7 @@ class ZipWriter {
|
|
|
492
513
|
await Promise.allSettled(Array.from(pendingAddFileCalls));
|
|
493
514
|
}
|
|
494
515
|
await Promise.allSettled(zipWriter.pendingErrors.map(watcher => watcher.recorded));
|
|
495
|
-
const unobservedWatchers = zipWriter.pendingErrors.filter(watcher => watcher.
|
|
516
|
+
const unobservedWatchers = zipWriter.pendingErrors.filter(watcher => watcher.failed && !watcher.observed);
|
|
496
517
|
if (unobservedWatchers.length) {
|
|
497
518
|
const unobservedErrors = unobservedWatchers.map(watcher => watcher.error);
|
|
498
519
|
unobservedWatchers.forEach(watcher => watcher.observed = true);
|
|
@@ -505,11 +526,16 @@ class ZipWriter {
|
|
|
505
526
|
throw error;
|
|
506
527
|
}
|
|
507
528
|
await closeFile(zipWriter, comment, options);
|
|
529
|
+
zipWriter.archiveClosed = true;
|
|
508
530
|
const preventClose = !ownsWritable(writer) && getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
|
|
509
531
|
if (!preventClose) {
|
|
510
532
|
await writable.getWriter().close();
|
|
511
533
|
}
|
|
512
|
-
return writer
|
|
534
|
+
return getWriterData(writer);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
[SYMBOL_ASYNC_DISPOSE]() {
|
|
538
|
+
return this.close();
|
|
513
539
|
}
|
|
514
540
|
}
|
|
515
541
|
|
|
@@ -588,11 +614,16 @@ class WatchedPromise extends Promise {
|
|
|
588
614
|
}
|
|
589
615
|
}
|
|
590
616
|
|
|
617
|
+
function getWriterData(writer) {
|
|
618
|
+
return writer.getData ? writer.getData() : writer.writable;
|
|
619
|
+
}
|
|
620
|
+
|
|
591
621
|
function watchPromiseError(zipWriter, promise) {
|
|
592
622
|
const watchedPromise = new WatchedPromise((resolve, reject) => Promise.prototype.then.call(promise, resolve, reject));
|
|
593
623
|
const watcher = {};
|
|
594
624
|
watchedPromise.watcher = watcher;
|
|
595
|
-
watcher.recorded = Promise.prototype.then.call(watchedPromise, UNDEFINED_VALUE,
|
|
625
|
+
watcher.recorded = Promise.prototype.then.call(watchedPromise, UNDEFINED_VALUE,
|
|
626
|
+
error => Object.assign(watcher, { failed: true, error }));
|
|
596
627
|
zipWriter.pendingErrors.push(watcher);
|
|
597
628
|
return watchedPromise;
|
|
598
629
|
}
|
|
@@ -606,6 +637,14 @@ async function prependZipEntries(zipWriter, reader) {
|
|
|
606
637
|
|
|
607
638
|
async function addFileEntry(zipWriter, name, reader, options) {
|
|
608
639
|
options = Object.assign({}, options);
|
|
640
|
+
const entry = options[OPTION_ENTRY];
|
|
641
|
+
if (entry !== UNDEFINED_VALUE) {
|
|
642
|
+
const { entryOptions, passThroughOptions } = getSourceEntryOptions(entry,
|
|
643
|
+
checkPassThroughOption(getOptionValue(zipWriter, options, OPTION_PASS_THROUGH)),
|
|
644
|
+
getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE));
|
|
645
|
+
delete options[OPTION_ENTRY];
|
|
646
|
+
options = Object.assign(entryOptions, passThroughOptions, options);
|
|
647
|
+
}
|
|
609
648
|
if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
|
|
610
649
|
name += DIRECTORY_SIGNATURE;
|
|
611
650
|
}
|
|
@@ -656,6 +695,7 @@ export {
|
|
|
656
695
|
ZipWriter,
|
|
657
696
|
ZipWriterStream,
|
|
658
697
|
getEntriesSize,
|
|
698
|
+
getSourceEntryOptions,
|
|
659
699
|
ERR_DUPLICATED_NAME,
|
|
660
700
|
ERR_INVALID_COMMENT,
|
|
661
701
|
ERR_INVALID_COMMENT_TYPE,
|
|
@@ -675,11 +715,14 @@ export {
|
|
|
675
715
|
ERR_UNSUPPORTED_FORMAT,
|
|
676
716
|
ERR_UNDEFINED_UNCOMPRESSED_SIZE,
|
|
677
717
|
ERR_UNDEFINED_COMPRESSION_METHOD,
|
|
718
|
+
ERR_UNDEFINED_CRC32,
|
|
678
719
|
ERR_UNDETERMINED_SIZE,
|
|
679
720
|
ERR_UNDEFINED_READER,
|
|
680
721
|
ERR_INVALID_READER,
|
|
681
722
|
ERR_ZIP_NOT_EMPTY,
|
|
682
723
|
ERR_INVALID_SIGNATURE_DATA,
|
|
724
|
+
ERR_INVALID_ENTRY,
|
|
725
|
+
ERR_ZIP_CRYPTO_LAST_MOD_DATE,
|
|
683
726
|
ERR_INVALID_UID,
|
|
684
727
|
ERR_INVALID_GID,
|
|
685
728
|
ERR_INVALID_UNIX_MODE,
|
|
@@ -689,7 +732,9 @@ export {
|
|
|
689
732
|
ERR_INVALID_MSDOS_DATA,
|
|
690
733
|
ERR_INVALID_LEVEL,
|
|
691
734
|
ERR_INVALID_PASSWORD_TYPE,
|
|
692
|
-
ERR_UNSUPPORTED_CRYPTO_API
|
|
735
|
+
ERR_UNSUPPORTED_CRYPTO_API,
|
|
736
|
+
WARNING_COMPRESSION_UNAVAILABLE,
|
|
737
|
+
WARNING_CLAMPED_LAST_MODIFICATION_DATE
|
|
693
738
|
};
|
|
694
739
|
|
|
695
740
|
async function addFile(zipWriter, name, reader, options) {
|
|
@@ -710,21 +755,33 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
710
755
|
try {
|
|
711
756
|
const { resolvedOptions } = metadataInfo;
|
|
712
757
|
if (resolvedOptions.level != 0 && resolvedOptions.compressionMethod === UNDEFINED_VALUE &&
|
|
713
|
-
!resolvedOptions.
|
|
758
|
+
!resolvedOptions.passThroughCompression && !(await supportsDeflate(getConfiguration()))) {
|
|
714
759
|
resolvedOptions.level = 0;
|
|
760
|
+
addWarning(zipWriter.warnings, WARNING_COMPRESSION_UNAVAILABLE, name);
|
|
715
761
|
}
|
|
716
762
|
const sizesInfo = await resolveSizes(zipWriter, reader, metadataInfo, options);
|
|
717
763
|
({ reader } = sizesInfo);
|
|
718
764
|
const diskOffset = getDiskOffset(zipWriter.writer);
|
|
719
765
|
const diskNumber = getDiskNumber(zipWriter.writer);
|
|
766
|
+
let crc32 = options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32;
|
|
767
|
+
const storesAE2 = sizesInfo.resolvedOptions.encrypted && !resolvedOptions.zipCrypto;
|
|
768
|
+
if (resolvedOptions.passThroughCompression && !resolvedOptions.passThroughEncryption && storesAE2) {
|
|
769
|
+
crc32 = UNDEFINED_VALUE;
|
|
770
|
+
}
|
|
771
|
+
if (resolvedOptions.passThroughCompression && reader && !storesAE2 && crc32 === UNDEFINED_VALUE) {
|
|
772
|
+
throw new Error(ERR_UNDEFINED_CRC32);
|
|
773
|
+
}
|
|
720
774
|
options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
|
|
721
775
|
signature: options[PROPERTY_NAME_SIGNATURE],
|
|
722
|
-
crc32
|
|
776
|
+
crc32,
|
|
723
777
|
offset: zipWriter.offset - diskOffset,
|
|
724
778
|
diskNumberStart: diskNumber,
|
|
725
779
|
[OPTION_USDZ]: zipWriter.options[OPTION_USDZ]
|
|
726
780
|
});
|
|
727
781
|
const headerInfo = getHeaderInfo(options);
|
|
782
|
+
if (headerInfo.lastModDateClamped) {
|
|
783
|
+
addWarning(zipWriter.warnings, WARNING_CLAMPED_LAST_MODIFICATION_DATE, name);
|
|
784
|
+
}
|
|
728
785
|
const dataDescriptorInfo = getDataDescriptorInfo(options);
|
|
729
786
|
const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
|
|
730
787
|
fileEntry = await getFileEntry(zipWriter, name, reader, {
|
|
@@ -751,6 +808,95 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
751
808
|
return new Entry(fileEntry);
|
|
752
809
|
}
|
|
753
810
|
|
|
811
|
+
function getSourceEntryOptions(entry, passThrough, lastModDateOverride) {
|
|
812
|
+
if (entry === null || typeof entry != OBJECT_TYPE || Array.isArray(entry)) {
|
|
813
|
+
throw new Error(ERR_INVALID_ENTRY);
|
|
814
|
+
}
|
|
815
|
+
const {
|
|
816
|
+
externalFileAttributes,
|
|
817
|
+
versionMadeBy,
|
|
818
|
+
comment,
|
|
819
|
+
lastModDate,
|
|
820
|
+
rawLastModDate,
|
|
821
|
+
creationDate,
|
|
822
|
+
lastAccessDate,
|
|
823
|
+
uncompressedSize,
|
|
824
|
+
encrypted,
|
|
825
|
+
zipCrypto,
|
|
826
|
+
crc32,
|
|
827
|
+
compressionMethod,
|
|
828
|
+
extraFieldAES,
|
|
829
|
+
extraFieldUnix,
|
|
830
|
+
internalFileAttributes,
|
|
831
|
+
extraField,
|
|
832
|
+
bitFlag,
|
|
833
|
+
directory,
|
|
834
|
+
uid,
|
|
835
|
+
gid
|
|
836
|
+
} = entry;
|
|
837
|
+
const entryOptions = {
|
|
838
|
+
externalFileAttributes,
|
|
839
|
+
versionMadeBy,
|
|
840
|
+
comment,
|
|
841
|
+
lastModDate,
|
|
842
|
+
creationDate,
|
|
843
|
+
lastAccessDate,
|
|
844
|
+
internalFileAttributes,
|
|
845
|
+
directory
|
|
846
|
+
};
|
|
847
|
+
if (bitFlag && bitFlag.languageEncodingFlag) {
|
|
848
|
+
entryOptions[OPTION_USE_UNICODE_FILE_NAMES] = true;
|
|
849
|
+
}
|
|
850
|
+
const userExtraField = getUserExtraField(extraField);
|
|
851
|
+
if (userExtraField) {
|
|
852
|
+
entryOptions[PROPERTY_NAME_EXTRA_FIELD] = userExtraField;
|
|
853
|
+
}
|
|
854
|
+
if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
|
|
855
|
+
Object.assign(entryOptions, {
|
|
856
|
+
uid,
|
|
857
|
+
gid,
|
|
858
|
+
unixExtraFieldType: extraFieldUnix ? UNIX_EXTRA_FIELD_TYPE : INFOZIP_EXTRA_FIELD_TYPE
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
const passThroughOptions = {};
|
|
862
|
+
if (passThrough && !directory) {
|
|
863
|
+
Object.assign(passThroughOptions, {
|
|
864
|
+
uncompressedSize,
|
|
865
|
+
crc32,
|
|
866
|
+
compressionMethod
|
|
867
|
+
});
|
|
868
|
+
if (passThrough !== PASS_THROUGH_COMPRESSED) {
|
|
869
|
+
Object.assign(passThroughOptions, {
|
|
870
|
+
encrypted,
|
|
871
|
+
zipCrypto,
|
|
872
|
+
encryptionStrength: extraFieldAES ? extraFieldAES.strength : UNDEFINED_VALUE
|
|
873
|
+
});
|
|
874
|
+
}
|
|
875
|
+
if (bitFlag) {
|
|
876
|
+
passThroughOptions.dataDescriptor = bitFlag.dataDescriptor;
|
|
877
|
+
passThroughOptions[OPTION_LEVEL] = LEVEL_BY_BITFLAG_LEVEL[bitFlag.level];
|
|
878
|
+
}
|
|
879
|
+
if (lastModDateOverride === UNDEFINED_VALUE) {
|
|
880
|
+
passThroughOptions.rawLastModDate = rawLastModDate;
|
|
881
|
+
} else if (passThrough !== PASS_THROUGH_COMPRESSED && zipCrypto && (!bitFlag || bitFlag.dataDescriptor) &&
|
|
882
|
+
lastModDateOverride instanceof Date &&
|
|
883
|
+
getDosTimeHighByte(lastModDateOverride) != ((rawLastModDate >>> 8) & MAX_8_BITS)) {
|
|
884
|
+
throw new Error(ERR_ZIP_CRYPTO_LAST_MOD_DATE);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
return { entryOptions, passThroughOptions };
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
function getDosTimeHighByte(lastModDate) {
|
|
891
|
+
let dosLastModDate = new Date(Math.ceil(Math.floor(lastModDate.getTime() / 1000) / 2) * 2000);
|
|
892
|
+
if (dosLastModDate < MIN_DATE) {
|
|
893
|
+
dosLastModDate = MIN_DATE;
|
|
894
|
+
} else if (dosLastModDate > MAX_DATE) {
|
|
895
|
+
dosLastModDate = MAX_DATE;
|
|
896
|
+
}
|
|
897
|
+
return ((dosLastModDate.getHours() << 3) | (dosLastModDate.getMinutes() >> 3)) & MAX_8_BITS;
|
|
898
|
+
}
|
|
899
|
+
|
|
754
900
|
function resolveAttributes(zipWriter, name, options) {
|
|
755
901
|
let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
|
|
756
902
|
let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? VERSION_MADE_BY_MSDOS : VERSION_MADE_BY_UNIX);
|
|
@@ -904,7 +1050,9 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
904
1050
|
const lastAccessDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
|
|
905
1051
|
const creationDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
|
|
906
1052
|
const internalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, 0);
|
|
907
|
-
const passThrough = getOptionValue(zipWriter, options, OPTION_PASS_THROUGH);
|
|
1053
|
+
const passThrough = checkPassThroughOption(getOptionValue(zipWriter, options, OPTION_PASS_THROUGH));
|
|
1054
|
+
const passThroughCompression = Boolean(passThrough);
|
|
1055
|
+
const passThroughEncryption = passThrough === true;
|
|
908
1056
|
const password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
|
|
909
1057
|
const rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
|
|
910
1058
|
checkPasswordOption(password, rawPassword);
|
|
@@ -920,10 +1068,11 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
920
1068
|
const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, true);
|
|
921
1069
|
const signal = checkSignalOption(getOptionValue(zipWriter, options, OPTION_SIGNAL));
|
|
922
1070
|
throwIfAborted(signal);
|
|
923
|
-
const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES,
|
|
1071
|
+
const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES,
|
|
1072
|
+
!isPrintableASCIIText(rawFilename) || !isPrintableASCIIText(rawComment));
|
|
924
1073
|
const compressionMethod = getOptionValue(zipWriter, options, PROPERTY_NAME_COMPRESSION_METHOD);
|
|
925
|
-
const registeredCodec =
|
|
926
|
-
if (!
|
|
1074
|
+
const registeredCodec = passThroughCompression || compressionMethod === UNDEFINED_VALUE ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
|
|
1075
|
+
if (!passThroughCompression && compressionMethod !== UNDEFINED_VALUE &&
|
|
927
1076
|
compressionMethod !== COMPRESSION_METHOD_STORE && compressionMethod !== COMPRESSION_METHOD_DEFLATE && !registeredCodec) {
|
|
928
1077
|
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
929
1078
|
}
|
|
@@ -937,15 +1086,15 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
937
1086
|
level = 0;
|
|
938
1087
|
}
|
|
939
1088
|
}
|
|
940
|
-
if (
|
|
941
|
-
level =
|
|
1089
|
+
if (passThroughCompression) {
|
|
1090
|
+
level = toNumber(options[OPTION_LEVEL]);
|
|
942
1091
|
}
|
|
943
1092
|
let useCompressionStream = getOptionValue(zipWriter, options, OPTION_USE_COMPRESSION_STREAM);
|
|
944
1093
|
let dataDescriptor = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR);
|
|
945
1094
|
if (bufferedWrite && dataDescriptor === UNDEFINED_VALUE) {
|
|
946
1095
|
dataDescriptor = false;
|
|
947
1096
|
}
|
|
948
|
-
if (dataDescriptor === UNDEFINED_VALUE || (zipCrypto && !
|
|
1097
|
+
if (dataDescriptor === UNDEFINED_VALUE || (zipCrypto && !passThroughEncryption)) {
|
|
949
1098
|
dataDescriptor = true;
|
|
950
1099
|
}
|
|
951
1100
|
if (level !== UNDEFINED_VALUE && level != 6) {
|
|
@@ -969,7 +1118,8 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
969
1118
|
lastAccessDate,
|
|
970
1119
|
creationDate,
|
|
971
1120
|
internalFileAttributes,
|
|
972
|
-
|
|
1121
|
+
passThroughCompression,
|
|
1122
|
+
passThroughEncryption,
|
|
973
1123
|
password,
|
|
974
1124
|
rawPassword,
|
|
975
1125
|
encryptionStrength,
|
|
@@ -1030,7 +1180,7 @@ function serializeExtraField(extraField) {
|
|
|
1030
1180
|
}
|
|
1031
1181
|
|
|
1032
1182
|
async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
|
|
1033
|
-
if (metadata.
|
|
1183
|
+
if (metadata.passThroughCompression && !reader && !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY)) {
|
|
1034
1184
|
throw new Error(ERR_UNDEFINED_READER);
|
|
1035
1185
|
}
|
|
1036
1186
|
let contentSize;
|
|
@@ -1046,12 +1196,12 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
|
|
|
1046
1196
|
}
|
|
1047
1197
|
|
|
1048
1198
|
function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options) {
|
|
1049
|
-
const {
|
|
1199
|
+
const { passThroughCompression, passThroughEncryption, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
|
|
1050
1200
|
let { dataDescriptor, zip64, level, compressionMethod } = metadata;
|
|
1051
1201
|
let maximumCompressedSize = 0;
|
|
1052
1202
|
let uncompressedSize = 0;
|
|
1053
1203
|
let unknownSize = false;
|
|
1054
|
-
if (
|
|
1204
|
+
if (passThroughCompression && hasContent) {
|
|
1055
1205
|
uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
|
|
1056
1206
|
if (uncompressedSize === UNDEFINED_VALUE) {
|
|
1057
1207
|
throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
|
|
@@ -1062,17 +1212,17 @@ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options
|
|
|
1062
1212
|
}
|
|
1063
1213
|
const zip64Enabled = zip64 === true;
|
|
1064
1214
|
const encrypted = getOptionValue(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
|
|
1065
|
-
if (hasContent &&
|
|
1215
|
+
if (hasContent && passThroughEncryption && !encrypted && getLength(password, rawPassword)) {
|
|
1066
1216
|
throw new Error(ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH);
|
|
1067
1217
|
}
|
|
1068
|
-
const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (
|
|
1218
|
+
const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThroughEncryption && encrypted));
|
|
1069
1219
|
if (!hasContent) {
|
|
1070
1220
|
level = 0;
|
|
1071
1221
|
compressionMethod = COMPRESSION_METHOD_STORE;
|
|
1072
1222
|
}
|
|
1073
|
-
const encryptionOverhead = encryptedEntry
|
|
1223
|
+
const encryptionOverhead = getEncryptionOverhead(encryptedEntry, zipCrypto, encryptionStrength);
|
|
1074
1224
|
if (hasContent) {
|
|
1075
|
-
if (!
|
|
1225
|
+
if (!passThroughCompression) {
|
|
1076
1226
|
if (contentSize === UNDEFINED_VALUE) {
|
|
1077
1227
|
dataDescriptor = true;
|
|
1078
1228
|
if (zip64 || zip64 === UNDEFINED_VALUE) {
|
|
@@ -1085,10 +1235,12 @@ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options
|
|
|
1085
1235
|
}
|
|
1086
1236
|
} else {
|
|
1087
1237
|
options.uncompressedSize = uncompressedSize;
|
|
1088
|
-
maximumCompressedSize = contentSize === UNDEFINED_VALUE ?
|
|
1238
|
+
maximumCompressedSize = contentSize === UNDEFINED_VALUE ?
|
|
1239
|
+
getMaximumCompressedSize(uncompressedSize) + encryptionOverhead :
|
|
1240
|
+
contentSize + (passThroughEncryption ? 0 : encryptionOverhead);
|
|
1089
1241
|
}
|
|
1090
1242
|
}
|
|
1091
|
-
const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !
|
|
1243
|
+
const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !passThroughCompression)) && !isCompressed(compressionMethod, level);
|
|
1092
1244
|
if (emptyEntry && !zipCrypto && getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR) === UNDEFINED_VALUE) {
|
|
1093
1245
|
dataDescriptor = false;
|
|
1094
1246
|
}
|
|
@@ -1137,6 +1289,8 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1137
1289
|
const initialOffset = writerOptions[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : writerOptions[OPTION_OFFSET];
|
|
1138
1290
|
let offset = initialOffset;
|
|
1139
1291
|
let minimumEntrySize = INFINITY_VALUE;
|
|
1292
|
+
const entrySizes = [];
|
|
1293
|
+
const entriesAlreadyZip64 = new Set();
|
|
1140
1294
|
for (const entry of entries) {
|
|
1141
1295
|
let { name } = entry;
|
|
1142
1296
|
const { size } = entry;
|
|
@@ -1148,7 +1302,7 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1148
1302
|
({ name } = attributesInfo);
|
|
1149
1303
|
const { resolvedOptions: metadata } = resolveMetadata(zipWriter, name, options);
|
|
1150
1304
|
if (metadata.level != 0 && metadata.compressionMethod === UNDEFINED_VALUE &&
|
|
1151
|
-
!metadata.
|
|
1305
|
+
!metadata.passThroughCompression && !(await supportsDeflate(getConfiguration()))) {
|
|
1152
1306
|
metadata.level = 0;
|
|
1153
1307
|
}
|
|
1154
1308
|
const hasContent = !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY);
|
|
@@ -1156,7 +1310,7 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1156
1310
|
throw new Error(ERR_UNDETERMINED_SIZE);
|
|
1157
1311
|
}
|
|
1158
1312
|
const { maximumCompressedSize, resolvedOptions: sizes } = resolveEntrySizes(zipWriter, hasContent, size, metadata, options);
|
|
1159
|
-
if (hasContent && !metadata.
|
|
1313
|
+
if (hasContent && !metadata.passThroughCompression && isCompressed(sizes.compressionMethod, sizes.level)) {
|
|
1160
1314
|
throw new Error(ERR_UNDETERMINED_SIZE);
|
|
1161
1315
|
}
|
|
1162
1316
|
const entryOptions = Object.assign({}, options, attributesInfo.resolvedOptions, metadata, sizes, { [OPTION_USDZ]: usdz });
|
|
@@ -1176,10 +1330,15 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1176
1330
|
compressedSize
|
|
1177
1331
|
}));
|
|
1178
1332
|
const entrySize = entryInfo.metadataSize + compressedSize;
|
|
1333
|
+
entrySizes.push(entrySize);
|
|
1334
|
+
entriesAlreadyZip64.add(Boolean(entryOptions.zip64Enabled ||
|
|
1335
|
+
entryOptions.uncompressedSize >= MAX_32_BITS || compressedSize >= MAX_32_BITS));
|
|
1179
1336
|
minimumEntrySize = Math.min(minimumEntrySize, entrySize);
|
|
1180
1337
|
offset += entrySize;
|
|
1181
1338
|
}
|
|
1182
|
-
const layoutDependsOnWriteOrder = files.size > 1 && (usdz ||
|
|
1339
|
+
const layoutDependsOnWriteOrder = files.size > 1 && (usdz ||
|
|
1340
|
+
(offset - minimumEntrySize >= MAX_32_BITS &&
|
|
1341
|
+
(entriesAlreadyZip64.size > 1 || countEntriesBefore4GB(entrySizes, initialOffset, true) != countEntriesBefore4GB(entrySizes, initialOffset, false))));
|
|
1183
1342
|
if (layoutDependsOnWriteOrder && !writeOrderGuaranteed) {
|
|
1184
1343
|
throw new Error(ERR_UNDETERMINED_SIZE);
|
|
1185
1344
|
}
|
|
@@ -1197,6 +1356,20 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1197
1356
|
return offset - initialOffset + directoryDataLength + commentLength + (zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
|
|
1198
1357
|
}
|
|
1199
1358
|
|
|
1359
|
+
function countEntriesBefore4GB(entrySizes, initialOffset, largestFirst) {
|
|
1360
|
+
const ordered = entrySizes.slice().sort((first, second) => largestFirst ? second - first : first - second);
|
|
1361
|
+
let position = initialOffset;
|
|
1362
|
+
let count = 0;
|
|
1363
|
+
for (const entrySize of ordered) {
|
|
1364
|
+
if (position >= MAX_32_BITS) {
|
|
1365
|
+
break;
|
|
1366
|
+
}
|
|
1367
|
+
position += entrySize;
|
|
1368
|
+
count++;
|
|
1369
|
+
}
|
|
1370
|
+
return count;
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1200
1373
|
async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
1201
1374
|
const {
|
|
1202
1375
|
fileEntries,
|
|
@@ -1372,6 +1545,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1372
1545
|
localExtraFieldZip64Length,
|
|
1373
1546
|
rawExtraFieldExtendedTimestamp,
|
|
1374
1547
|
extraFieldExtendedTimestampFlag,
|
|
1548
|
+
extraFieldExtendedTimestampTime,
|
|
1375
1549
|
rawExtraFieldNTFS,
|
|
1376
1550
|
rawExtraFieldUnix,
|
|
1377
1551
|
rawExtraFieldAES,
|
|
@@ -1384,6 +1558,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1384
1558
|
password,
|
|
1385
1559
|
rawPassword,
|
|
1386
1560
|
level,
|
|
1561
|
+
useUnicodeFileNames,
|
|
1387
1562
|
zip64,
|
|
1388
1563
|
zip64Enabled,
|
|
1389
1564
|
zip64UncompressedSize,
|
|
@@ -1418,7 +1593,8 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1418
1593
|
msdosAttributesRaw,
|
|
1419
1594
|
msdosAttributes,
|
|
1420
1595
|
useCompressionStream,
|
|
1421
|
-
|
|
1596
|
+
passThroughCompression,
|
|
1597
|
+
passThroughEncryption,
|
|
1422
1598
|
format,
|
|
1423
1599
|
codecURI
|
|
1424
1600
|
} = options;
|
|
@@ -1429,9 +1605,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1429
1605
|
zip64Enabled,
|
|
1430
1606
|
directory: Boolean(directory),
|
|
1431
1607
|
executable: Boolean(executable),
|
|
1432
|
-
filenameUTF8:
|
|
1608
|
+
filenameUTF8: Boolean(useUnicodeFileNames),
|
|
1433
1609
|
rawFilename,
|
|
1434
|
-
commentUTF8:
|
|
1610
|
+
commentUTF8: Boolean(useUnicodeFileNames),
|
|
1435
1611
|
rawComment,
|
|
1436
1612
|
rawExtraFieldZip64,
|
|
1437
1613
|
localExtraFieldZip64Length,
|
|
@@ -1462,7 +1638,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1462
1638
|
uncompressedSize
|
|
1463
1639
|
} = options;
|
|
1464
1640
|
let compressedSize = 0;
|
|
1465
|
-
if (!
|
|
1641
|
+
if (!passThroughCompression) {
|
|
1466
1642
|
uncompressedSize = 0;
|
|
1467
1643
|
}
|
|
1468
1644
|
const { writable } = writer;
|
|
@@ -1479,9 +1655,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1479
1655
|
encryptionStrength,
|
|
1480
1656
|
zipCrypto: encrypted && zipCrypto,
|
|
1481
1657
|
passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & MAX_8_BITS,
|
|
1482
|
-
computeCrc32: !
|
|
1483
|
-
compressed: compressed && !
|
|
1484
|
-
encrypted: encrypted && !
|
|
1658
|
+
computeCrc32: !passThroughCompression,
|
|
1659
|
+
compressed: compressed && !passThroughCompression,
|
|
1660
|
+
encrypted: encrypted && !passThroughEncryption,
|
|
1485
1661
|
useWebWorkers,
|
|
1486
1662
|
useCompressionStream,
|
|
1487
1663
|
transferStreams,
|
|
@@ -1496,7 +1672,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1496
1672
|
const result = await runWorker({ readable, writable }, workerOptions);
|
|
1497
1673
|
compressedSize = result.outputSize;
|
|
1498
1674
|
writer.size += compressedSize;
|
|
1499
|
-
if (!
|
|
1675
|
+
if (!passThroughCompression) {
|
|
1500
1676
|
uncompressedSize = result.inputSize;
|
|
1501
1677
|
if (!encrypted || zipCrypto) {
|
|
1502
1678
|
crc32 = result.crc32;
|
|
@@ -1507,7 +1683,10 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1507
1683
|
throw new Error(ERR_UNSUPPORTED_FORMAT);
|
|
1508
1684
|
}
|
|
1509
1685
|
} catch (error) {
|
|
1510
|
-
|
|
1686
|
+
const { outputSize: failedOutputSize } = workerOptions;
|
|
1687
|
+
if (failedOutputSize !== UNDEFINED_VALUE) {
|
|
1688
|
+
writer.size += failedOutputSize;
|
|
1689
|
+
} else if (isErrorObject(error) && error.outputSize !== UNDEFINED_VALUE) {
|
|
1511
1690
|
writer.size += error.outputSize;
|
|
1512
1691
|
}
|
|
1513
1692
|
throw error;
|
|
@@ -1539,8 +1718,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1539
1718
|
headerArray,
|
|
1540
1719
|
headerView,
|
|
1541
1720
|
signature: crc32,
|
|
1542
|
-
crc32: encrypted && !zipCrypto && !
|
|
1721
|
+
crc32: encrypted && !zipCrypto && !passThroughCompression ? UNDEFINED_VALUE : crc32,
|
|
1543
1722
|
extraFieldExtendedTimestampFlag,
|
|
1723
|
+
extraFieldExtendedTimestampTime,
|
|
1544
1724
|
zip64UncompressedSize,
|
|
1545
1725
|
zip64CompressedSize
|
|
1546
1726
|
});
|
|
@@ -1565,7 +1745,7 @@ function getHeaderInfo(options) {
|
|
|
1565
1745
|
encryptionStrength,
|
|
1566
1746
|
extendedTimestamp,
|
|
1567
1747
|
ntfsTimestamp,
|
|
1568
|
-
|
|
1748
|
+
passThroughCompression,
|
|
1569
1749
|
encrypted,
|
|
1570
1750
|
zip64UncompressedSize,
|
|
1571
1751
|
zip64CompressedSize,
|
|
@@ -1576,7 +1756,7 @@ function getHeaderInfo(options) {
|
|
|
1576
1756
|
let { version, compressionMethod } = options;
|
|
1577
1757
|
const compressed = !directory && isCompressed(compressionMethod, level);
|
|
1578
1758
|
let rawLocalExtraFieldZip64;
|
|
1579
|
-
const uncompressedFile =
|
|
1759
|
+
const uncompressedFile = passThroughCompression || !compressed;
|
|
1580
1760
|
const zip64ExtraFieldComplete = zip64 && (options.bufferedWrite || !dataDescriptor || ((!zip64UncompressedSize && !zip64CompressedSize) || (uncompressedFile && !unknownSize)));
|
|
1581
1761
|
const writeLocalExtraFieldZip64 = zip64ExtraFieldComplete || (zip64 && dataDescriptor && (zip64UncompressedSize || zip64CompressedSize));
|
|
1582
1762
|
if (zip64 && (zip64UncompressedSize || zip64CompressedSize)) {
|
|
@@ -1588,8 +1768,8 @@ function getHeaderInfo(options) {
|
|
|
1588
1768
|
if (zip64ExtraFieldComplete) {
|
|
1589
1769
|
extraFieldZip64.writeUint64(uncompressedSize);
|
|
1590
1770
|
if (uncompressedFile) {
|
|
1591
|
-
const encryptionOverhead = encrypted
|
|
1592
|
-
extraFieldZip64.writeUint64(
|
|
1771
|
+
const encryptionOverhead = getEncryptionOverhead(encrypted, zipCrypto, encryptionStrength);
|
|
1772
|
+
extraFieldZip64.writeUint64(passThroughCompression ? 0 : uncompressedSize + encryptionOverhead);
|
|
1593
1773
|
}
|
|
1594
1774
|
}
|
|
1595
1775
|
} else {
|
|
@@ -1608,6 +1788,7 @@ function getHeaderInfo(options) {
|
|
|
1608
1788
|
let rawExtraFieldNTFS;
|
|
1609
1789
|
let rawExtraFieldExtendedTimestamp;
|
|
1610
1790
|
let extraFieldExtendedTimestampFlag;
|
|
1791
|
+
let extraFieldExtendedTimestampTime;
|
|
1611
1792
|
if (extendedTimestamp) {
|
|
1612
1793
|
const lastModTimeUnix = getTimeUnix(lastModDate);
|
|
1613
1794
|
const lastModTimeUnixInRange = inUnixTimeRange(lastModTimeUnix);
|
|
@@ -1615,6 +1796,7 @@ function getHeaderInfo(options) {
|
|
|
1615
1796
|
const extraFieldTimestampLength = 9 + (lastAccessDate ? 4 : 0) + (creationDate ? 4 : 0);
|
|
1616
1797
|
const extraFieldTimestamp = createRecordWriter(extraFieldTimestampLength);
|
|
1617
1798
|
extraFieldExtendedTimestampFlag = 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0);
|
|
1799
|
+
extraFieldExtendedTimestampTime = lastModTimeUnix;
|
|
1618
1800
|
extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
1619
1801
|
extraFieldTimestamp.writeUint16(extraFieldTimestampLength - 4);
|
|
1620
1802
|
extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
|
|
@@ -1698,7 +1880,7 @@ function getHeaderInfo(options) {
|
|
|
1698
1880
|
}
|
|
1699
1881
|
if (encrypted && !zipCrypto) {
|
|
1700
1882
|
version = version > VERSION_AES ? version : VERSION_AES;
|
|
1701
|
-
if (
|
|
1883
|
+
if (passThroughCompression && crc32 !== UNDEFINED_VALUE) {
|
|
1702
1884
|
rawExtraFieldAES[EXTRAFIELD_OFFSET_AES_VENDOR_VERSION] = VENDOR_VERSION_AE_1;
|
|
1703
1885
|
}
|
|
1704
1886
|
setUint16(getDataView(rawExtraFieldAES), EXTRAFIELD_OFFSET_AES_COMPRESSION_METHOD, compressionMethod);
|
|
@@ -1760,12 +1942,14 @@ function getHeaderInfo(options) {
|
|
|
1760
1942
|
headerArray,
|
|
1761
1943
|
headerView,
|
|
1762
1944
|
lastModDate: storedLastModDate,
|
|
1945
|
+
lastModDateClamped: storedLastModDate === clampedLastModDate && dosLastModDate.getTime() != clampedLastModDate.getTime(),
|
|
1763
1946
|
rawLastModDate,
|
|
1764
1947
|
encrypted,
|
|
1765
1948
|
compressed,
|
|
1766
1949
|
version,
|
|
1767
1950
|
compressionMethod,
|
|
1768
1951
|
extraFieldExtendedTimestampFlag,
|
|
1952
|
+
extraFieldExtendedTimestampTime,
|
|
1769
1953
|
rawExtraFieldZip64: EMPTY_UINT8_ARRAY,
|
|
1770
1954
|
localExtraFieldZip64Length,
|
|
1771
1955
|
rawExtraFieldExtendedTimestamp,
|
|
@@ -1868,7 +2052,7 @@ function setEntryInfo({
|
|
|
1868
2052
|
}, {
|
|
1869
2053
|
zip64,
|
|
1870
2054
|
zipCrypto,
|
|
1871
|
-
|
|
2055
|
+
passThroughCompression,
|
|
1872
2056
|
dataDescriptor
|
|
1873
2057
|
}) {
|
|
1874
2058
|
const {
|
|
@@ -1879,7 +2063,7 @@ function setEntryInfo({
|
|
|
1879
2063
|
dataDescriptorView,
|
|
1880
2064
|
dataDescriptorOffset
|
|
1881
2065
|
} = dataDescriptorInfo;
|
|
1882
|
-
if ((!encrypted || zipCrypto ||
|
|
2066
|
+
if ((!encrypted || zipCrypto || passThroughCompression) && crc32 !== UNDEFINED_VALUE) {
|
|
1883
2067
|
setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
|
|
1884
2068
|
if (dataDescriptor) {
|
|
1885
2069
|
setUint32(dataDescriptorView, dataDescriptorOffset, crc32);
|
|
@@ -1910,9 +2094,9 @@ function updateLocalHeader({
|
|
|
1910
2094
|
uncompressedSize,
|
|
1911
2095
|
zip64UncompressedSize,
|
|
1912
2096
|
zip64CompressedSize
|
|
1913
|
-
}, localHeaderView, { dataDescriptor,
|
|
2097
|
+
}, localHeaderView, { dataDescriptor, passThroughCompression }) {
|
|
1914
2098
|
if (!dataDescriptor) {
|
|
1915
|
-
if (!encrypted || (
|
|
2099
|
+
if (!encrypted || (passThroughCompression && crc32 !== UNDEFINED_VALUE)) {
|
|
1916
2100
|
setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, crc32);
|
|
1917
2101
|
}
|
|
1918
2102
|
if (!zip64CompressedSize) {
|
|
@@ -1949,9 +2133,8 @@ function createDirectoryRecords(files) {
|
|
|
1949
2133
|
rawExtraFieldUnix,
|
|
1950
2134
|
rawExtraField,
|
|
1951
2135
|
rawCentralExtraField,
|
|
1952
|
-
extendedTimestamp,
|
|
1953
2136
|
extraFieldExtendedTimestampFlag,
|
|
1954
|
-
|
|
2137
|
+
extraFieldExtendedTimestampTime,
|
|
1955
2138
|
zip64Enabled,
|
|
1956
2139
|
uncompressedSize,
|
|
1957
2140
|
compressedSize
|
|
@@ -1994,16 +2177,15 @@ function createDirectoryRecords(files) {
|
|
|
1994
2177
|
fileEntry.zip64Offset = zip64Offset;
|
|
1995
2178
|
fileEntry.zip64DiskNumberStart = zip64DiskNumberStart;
|
|
1996
2179
|
let rawExtraFieldTimestamp;
|
|
1997
|
-
|
|
1998
|
-
|
|
2180
|
+
if (extraFieldExtendedTimestampTime === UNDEFINED_VALUE) {
|
|
2181
|
+
rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
|
|
2182
|
+
} else {
|
|
1999
2183
|
const extraFieldTimestamp = createRecordWriter(9);
|
|
2000
2184
|
extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
2001
2185
|
extraFieldTimestamp.writeUint16(5);
|
|
2002
2186
|
extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
|
|
2003
|
-
extraFieldTimestamp.writeUint32(
|
|
2187
|
+
extraFieldTimestamp.writeUint32(extraFieldExtendedTimestampTime);
|
|
2004
2188
|
rawExtraFieldTimestamp = extraFieldTimestamp.array;
|
|
2005
|
-
} else {
|
|
2006
|
-
rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
|
|
2007
2189
|
}
|
|
2008
2190
|
fileEntry.rawExtraFieldExtendedTimestamp = rawExtraFieldTimestamp;
|
|
2009
2191
|
const extraFieldLength = getLength(
|
|
@@ -2503,6 +2685,11 @@ function getHeaderArrayData({
|
|
|
2503
2685
|
};
|
|
2504
2686
|
}
|
|
2505
2687
|
|
|
2688
|
+
function isPrintableASCIIText(rawText) {
|
|
2689
|
+
return rawText.every(characterCode =>
|
|
2690
|
+
characterCode >= MIN_PRINTABLE_ASCII_CHARACTER_CODE && characterCode <= MAX_PRINTABLE_ASCII_CHARACTER_CODE);
|
|
2691
|
+
}
|
|
2692
|
+
|
|
2506
2693
|
function getBitFlag(level, useUnicodeFileNames, dataDescriptor, encrypted, compressionMethod) {
|
|
2507
2694
|
let bitFlag = 0;
|
|
2508
2695
|
if (useUnicodeFileNames) {
|