@zip.js/zip.js 2.11.4 → 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 +427 -110
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +437 -107
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +492 -230
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +505 -227
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +492 -230
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +507 -229
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +508 -230
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +439 -109
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +439 -109
- 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 +440 -110
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +507 -229
- package/index-native.min.js +1 -1
- package/index.cjs +508 -230
- package/index.d.cts +468 -59
- package/index.d.ts +468 -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 +13 -5
- package/lib/core/options.js +16 -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 -132
- package/lib/core/zip-reader.js +106 -48
- package/lib/core/zip-writer.js +236 -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,
|
|
@@ -240,9 +244,12 @@ import {
|
|
|
240
244
|
checkSignalOption,
|
|
241
245
|
throwIfAborted,
|
|
242
246
|
checkPasswordOption,
|
|
247
|
+
checkPassThroughOption,
|
|
243
248
|
checkInteger,
|
|
244
249
|
checkIntegerOption,
|
|
245
|
-
toNumber
|
|
250
|
+
toNumber,
|
|
251
|
+
OPTION_ENTRY,
|
|
252
|
+
PASS_THROUGH_COMPRESSED
|
|
246
253
|
} from "./options.js";
|
|
247
254
|
|
|
248
255
|
const ERR_DUPLICATED_NAME = "File already exists";
|
|
@@ -256,7 +263,7 @@ const ERR_INVALID_VERSION = "Version exceeds 65535";
|
|
|
256
263
|
const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
|
|
257
264
|
const ERR_UNSUPPORTED_ENCRYPTION_USDZ = "Encryption is not supported in USDZ files";
|
|
258
265
|
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";
|
|
266
|
+
const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set to true (use 'compressed' instead)";
|
|
260
267
|
const ERR_INVALID_EXTRAFIELD = "Invalid extra field (must be a Map)";
|
|
261
268
|
const ERR_INVALID_EXTRAFIELD_TYPE = "Invalid extra field type (must be integer 0..65535)";
|
|
262
269
|
const ERR_INVALID_EXTRAFIELD_DATA_TYPE = "Invalid extra field data (must be a Uint8Array)";
|
|
@@ -268,6 +275,7 @@ const MAX_NTFS_TIME = BigInt("0x7fffffffffffffff");
|
|
|
268
275
|
const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
|
|
269
276
|
const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
|
|
270
277
|
const ERR_UNDEFINED_COMPRESSION_METHOD = "Undefined compression method";
|
|
278
|
+
const ERR_UNDEFINED_CRC32 = "Undefined CRC32";
|
|
271
279
|
const ERR_UNDETERMINED_SIZE = "Undetermined size";
|
|
272
280
|
const ERR_UNDEFINED_READER = "Undefined reader";
|
|
273
281
|
const ERR_INVALID_READER = "Invalid reader (must be a Reader instance, a ReadableStream instance, or an object with a 'readable' property)";
|
|
@@ -281,14 +289,21 @@ const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be intege
|
|
|
281
289
|
const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
|
|
282
290
|
const ERR_INVALID_LEVEL = "Invalid level (must be integer 0..9)";
|
|
283
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";
|
|
284
296
|
|
|
285
297
|
const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
|
|
286
298
|
const EXTRAFIELD_OFFSET_AES_VENDOR_VERSION = 4;
|
|
287
299
|
const EXTRAFIELD_OFFSET_AES_COMPRESSION_METHOD = 9;
|
|
288
300
|
const EXTRAFIELD_USDZ_MAX_LENGTH = 67;
|
|
301
|
+
const MIN_PRINTABLE_ASCII_CHARACTER_CODE = 0x20;
|
|
302
|
+
const MAX_PRINTABLE_ASCII_CHARACTER_CODE = 0x7e;
|
|
289
303
|
const VENDOR_VERSION_AE_1 = 1;
|
|
290
304
|
const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
|
|
291
305
|
const UNIX_EXTRA_FIELD_TYPE = "unix";
|
|
306
|
+
const LEVEL_BY_BITFLAG_LEVEL = [8, 9, 5, 3];
|
|
292
307
|
const MAX_LEVEL = 9;
|
|
293
308
|
|
|
294
309
|
let workers = 0;
|
|
@@ -315,9 +330,11 @@ class ZipWriter {
|
|
|
315
330
|
initialOffset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : options[OPTION_OFFSET] - (writer.size || writer.writable.size || 0),
|
|
316
331
|
pendingAddFileCalls: new Set(),
|
|
317
332
|
pendingErrors: [],
|
|
333
|
+
warnings: [],
|
|
318
334
|
bufferedWrites: 0,
|
|
319
335
|
directWrites: 0,
|
|
320
|
-
lastFileEntry: UNDEFINED_VALUE
|
|
336
|
+
lastFileEntry: UNDEFINED_VALUE,
|
|
337
|
+
archiveClosed: false
|
|
321
338
|
});
|
|
322
339
|
}
|
|
323
340
|
|
|
@@ -482,6 +499,9 @@ class ZipWriter {
|
|
|
482
499
|
const zipWriter = this;
|
|
483
500
|
const { pendingAddFileCalls, writer } = this;
|
|
484
501
|
const { writable } = writer;
|
|
502
|
+
if (zipWriter.archiveClosed) {
|
|
503
|
+
return getWriterData(writer);
|
|
504
|
+
}
|
|
485
505
|
if (!(comment instanceof Uint8Array)) {
|
|
486
506
|
throw new Error(ERR_INVALID_COMMENT_TYPE);
|
|
487
507
|
}
|
|
@@ -505,11 +525,16 @@ class ZipWriter {
|
|
|
505
525
|
throw error;
|
|
506
526
|
}
|
|
507
527
|
await closeFile(zipWriter, comment, options);
|
|
528
|
+
zipWriter.archiveClosed = true;
|
|
508
529
|
const preventClose = !ownsWritable(writer) && getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
|
|
509
530
|
if (!preventClose) {
|
|
510
531
|
await writable.getWriter().close();
|
|
511
532
|
}
|
|
512
|
-
return writer
|
|
533
|
+
return getWriterData(writer);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
[SYMBOL_ASYNC_DISPOSE]() {
|
|
537
|
+
return this.close();
|
|
513
538
|
}
|
|
514
539
|
}
|
|
515
540
|
|
|
@@ -588,6 +613,10 @@ class WatchedPromise extends Promise {
|
|
|
588
613
|
}
|
|
589
614
|
}
|
|
590
615
|
|
|
616
|
+
function getWriterData(writer) {
|
|
617
|
+
return writer.getData ? writer.getData() : writer.writable;
|
|
618
|
+
}
|
|
619
|
+
|
|
591
620
|
function watchPromiseError(zipWriter, promise) {
|
|
592
621
|
const watchedPromise = new WatchedPromise((resolve, reject) => Promise.prototype.then.call(promise, resolve, reject));
|
|
593
622
|
const watcher = {};
|
|
@@ -606,6 +635,14 @@ async function prependZipEntries(zipWriter, reader) {
|
|
|
606
635
|
|
|
607
636
|
async function addFileEntry(zipWriter, name, reader, options) {
|
|
608
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
|
+
}
|
|
609
646
|
if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
|
|
610
647
|
name += DIRECTORY_SIGNATURE;
|
|
611
648
|
}
|
|
@@ -656,6 +693,7 @@ export {
|
|
|
656
693
|
ZipWriter,
|
|
657
694
|
ZipWriterStream,
|
|
658
695
|
getEntriesSize,
|
|
696
|
+
getSourceEntryOptions,
|
|
659
697
|
ERR_DUPLICATED_NAME,
|
|
660
698
|
ERR_INVALID_COMMENT,
|
|
661
699
|
ERR_INVALID_COMMENT_TYPE,
|
|
@@ -675,11 +713,14 @@ export {
|
|
|
675
713
|
ERR_UNSUPPORTED_FORMAT,
|
|
676
714
|
ERR_UNDEFINED_UNCOMPRESSED_SIZE,
|
|
677
715
|
ERR_UNDEFINED_COMPRESSION_METHOD,
|
|
716
|
+
ERR_UNDEFINED_CRC32,
|
|
678
717
|
ERR_UNDETERMINED_SIZE,
|
|
679
718
|
ERR_UNDEFINED_READER,
|
|
680
719
|
ERR_INVALID_READER,
|
|
681
720
|
ERR_ZIP_NOT_EMPTY,
|
|
682
721
|
ERR_INVALID_SIGNATURE_DATA,
|
|
722
|
+
ERR_INVALID_ENTRY,
|
|
723
|
+
ERR_ZIP_CRYPTO_LAST_MOD_DATE,
|
|
683
724
|
ERR_INVALID_UID,
|
|
684
725
|
ERR_INVALID_GID,
|
|
685
726
|
ERR_INVALID_UNIX_MODE,
|
|
@@ -689,7 +730,9 @@ export {
|
|
|
689
730
|
ERR_INVALID_MSDOS_DATA,
|
|
690
731
|
ERR_INVALID_LEVEL,
|
|
691
732
|
ERR_INVALID_PASSWORD_TYPE,
|
|
692
|
-
ERR_UNSUPPORTED_CRYPTO_API
|
|
733
|
+
ERR_UNSUPPORTED_CRYPTO_API,
|
|
734
|
+
WARNING_COMPRESSION_UNAVAILABLE,
|
|
735
|
+
WARNING_CLAMPED_LAST_MODIFICATION_DATE
|
|
693
736
|
};
|
|
694
737
|
|
|
695
738
|
async function addFile(zipWriter, name, reader, options) {
|
|
@@ -710,21 +753,33 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
710
753
|
try {
|
|
711
754
|
const { resolvedOptions } = metadataInfo;
|
|
712
755
|
if (resolvedOptions.level != 0 && resolvedOptions.compressionMethod === UNDEFINED_VALUE &&
|
|
713
|
-
!resolvedOptions.
|
|
756
|
+
!resolvedOptions.passThroughCompression && !(await supportsDeflate(getConfiguration()))) {
|
|
714
757
|
resolvedOptions.level = 0;
|
|
758
|
+
addWarning(zipWriter.warnings, WARNING_COMPRESSION_UNAVAILABLE, name);
|
|
715
759
|
}
|
|
716
760
|
const sizesInfo = await resolveSizes(zipWriter, reader, metadataInfo, options);
|
|
717
761
|
({ reader } = sizesInfo);
|
|
718
762
|
const diskOffset = getDiskOffset(zipWriter.writer);
|
|
719
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
|
+
}
|
|
720
772
|
options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
|
|
721
773
|
signature: options[PROPERTY_NAME_SIGNATURE],
|
|
722
|
-
crc32
|
|
774
|
+
crc32,
|
|
723
775
|
offset: zipWriter.offset - diskOffset,
|
|
724
776
|
diskNumberStart: diskNumber,
|
|
725
777
|
[OPTION_USDZ]: zipWriter.options[OPTION_USDZ]
|
|
726
778
|
});
|
|
727
779
|
const headerInfo = getHeaderInfo(options);
|
|
780
|
+
if (headerInfo.lastModDateClamped) {
|
|
781
|
+
addWarning(zipWriter.warnings, WARNING_CLAMPED_LAST_MODIFICATION_DATE, name);
|
|
782
|
+
}
|
|
728
783
|
const dataDescriptorInfo = getDataDescriptorInfo(options);
|
|
729
784
|
const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
|
|
730
785
|
fileEntry = await getFileEntry(zipWriter, name, reader, {
|
|
@@ -751,6 +806,95 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
751
806
|
return new Entry(fileEntry);
|
|
752
807
|
}
|
|
753
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
|
+
|
|
754
898
|
function resolveAttributes(zipWriter, name, options) {
|
|
755
899
|
let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
|
|
756
900
|
let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? VERSION_MADE_BY_MSDOS : VERSION_MADE_BY_UNIX);
|
|
@@ -904,7 +1048,9 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
904
1048
|
const lastAccessDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
|
|
905
1049
|
const creationDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
|
|
906
1050
|
const internalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, 0);
|
|
907
|
-
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;
|
|
908
1054
|
const password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
|
|
909
1055
|
const rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
|
|
910
1056
|
checkPasswordOption(password, rawPassword);
|
|
@@ -920,10 +1066,11 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
920
1066
|
const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, true);
|
|
921
1067
|
const signal = checkSignalOption(getOptionValue(zipWriter, options, OPTION_SIGNAL));
|
|
922
1068
|
throwIfAborted(signal);
|
|
923
|
-
const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES,
|
|
1069
|
+
const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES,
|
|
1070
|
+
!isPrintableASCIIText(rawFilename) || !isPrintableASCIIText(rawComment));
|
|
924
1071
|
const compressionMethod = getOptionValue(zipWriter, options, PROPERTY_NAME_COMPRESSION_METHOD);
|
|
925
|
-
const registeredCodec =
|
|
926
|
-
if (!
|
|
1072
|
+
const registeredCodec = passThroughCompression || compressionMethod === UNDEFINED_VALUE ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
|
|
1073
|
+
if (!passThroughCompression && compressionMethod !== UNDEFINED_VALUE &&
|
|
927
1074
|
compressionMethod !== COMPRESSION_METHOD_STORE && compressionMethod !== COMPRESSION_METHOD_DEFLATE && !registeredCodec) {
|
|
928
1075
|
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
929
1076
|
}
|
|
@@ -937,15 +1084,15 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
937
1084
|
level = 0;
|
|
938
1085
|
}
|
|
939
1086
|
}
|
|
940
|
-
if (
|
|
941
|
-
level =
|
|
1087
|
+
if (passThroughCompression) {
|
|
1088
|
+
level = toNumber(options[OPTION_LEVEL]);
|
|
942
1089
|
}
|
|
943
1090
|
let useCompressionStream = getOptionValue(zipWriter, options, OPTION_USE_COMPRESSION_STREAM);
|
|
944
1091
|
let dataDescriptor = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR);
|
|
945
1092
|
if (bufferedWrite && dataDescriptor === UNDEFINED_VALUE) {
|
|
946
1093
|
dataDescriptor = false;
|
|
947
1094
|
}
|
|
948
|
-
if (dataDescriptor === UNDEFINED_VALUE || (zipCrypto && !
|
|
1095
|
+
if (dataDescriptor === UNDEFINED_VALUE || (zipCrypto && !passThroughEncryption)) {
|
|
949
1096
|
dataDescriptor = true;
|
|
950
1097
|
}
|
|
951
1098
|
if (level !== UNDEFINED_VALUE && level != 6) {
|
|
@@ -969,7 +1116,8 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
969
1116
|
lastAccessDate,
|
|
970
1117
|
creationDate,
|
|
971
1118
|
internalFileAttributes,
|
|
972
|
-
|
|
1119
|
+
passThroughCompression,
|
|
1120
|
+
passThroughEncryption,
|
|
973
1121
|
password,
|
|
974
1122
|
rawPassword,
|
|
975
1123
|
encryptionStrength,
|
|
@@ -1030,7 +1178,7 @@ function serializeExtraField(extraField) {
|
|
|
1030
1178
|
}
|
|
1031
1179
|
|
|
1032
1180
|
async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
|
|
1033
|
-
if (metadata.
|
|
1181
|
+
if (metadata.passThroughCompression && !reader && !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY)) {
|
|
1034
1182
|
throw new Error(ERR_UNDEFINED_READER);
|
|
1035
1183
|
}
|
|
1036
1184
|
let contentSize;
|
|
@@ -1046,12 +1194,12 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
|
|
|
1046
1194
|
}
|
|
1047
1195
|
|
|
1048
1196
|
function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options) {
|
|
1049
|
-
const {
|
|
1197
|
+
const { passThroughCompression, passThroughEncryption, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
|
|
1050
1198
|
let { dataDescriptor, zip64, level, compressionMethod } = metadata;
|
|
1051
1199
|
let maximumCompressedSize = 0;
|
|
1052
1200
|
let uncompressedSize = 0;
|
|
1053
1201
|
let unknownSize = false;
|
|
1054
|
-
if (
|
|
1202
|
+
if (passThroughCompression && hasContent) {
|
|
1055
1203
|
uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
|
|
1056
1204
|
if (uncompressedSize === UNDEFINED_VALUE) {
|
|
1057
1205
|
throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
|
|
@@ -1062,17 +1210,17 @@ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options
|
|
|
1062
1210
|
}
|
|
1063
1211
|
const zip64Enabled = zip64 === true;
|
|
1064
1212
|
const encrypted = getOptionValue(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
|
|
1065
|
-
if (hasContent &&
|
|
1213
|
+
if (hasContent && passThroughEncryption && !encrypted && getLength(password, rawPassword)) {
|
|
1066
1214
|
throw new Error(ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH);
|
|
1067
1215
|
}
|
|
1068
|
-
const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (
|
|
1216
|
+
const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThroughEncryption && encrypted));
|
|
1069
1217
|
if (!hasContent) {
|
|
1070
1218
|
level = 0;
|
|
1071
1219
|
compressionMethod = COMPRESSION_METHOD_STORE;
|
|
1072
1220
|
}
|
|
1073
|
-
const encryptionOverhead = encryptedEntry
|
|
1221
|
+
const encryptionOverhead = getEncryptionOverhead(encryptedEntry, zipCrypto, encryptionStrength);
|
|
1074
1222
|
if (hasContent) {
|
|
1075
|
-
if (!
|
|
1223
|
+
if (!passThroughCompression) {
|
|
1076
1224
|
if (contentSize === UNDEFINED_VALUE) {
|
|
1077
1225
|
dataDescriptor = true;
|
|
1078
1226
|
if (zip64 || zip64 === UNDEFINED_VALUE) {
|
|
@@ -1085,10 +1233,12 @@ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options
|
|
|
1085
1233
|
}
|
|
1086
1234
|
} else {
|
|
1087
1235
|
options.uncompressedSize = uncompressedSize;
|
|
1088
|
-
maximumCompressedSize = contentSize === UNDEFINED_VALUE ?
|
|
1236
|
+
maximumCompressedSize = contentSize === UNDEFINED_VALUE ?
|
|
1237
|
+
getMaximumCompressedSize(uncompressedSize) + encryptionOverhead :
|
|
1238
|
+
contentSize + (passThroughEncryption ? 0 : encryptionOverhead);
|
|
1089
1239
|
}
|
|
1090
1240
|
}
|
|
1091
|
-
const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !
|
|
1241
|
+
const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !passThroughCompression)) && !isCompressed(compressionMethod, level);
|
|
1092
1242
|
if (emptyEntry && !zipCrypto && getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR) === UNDEFINED_VALUE) {
|
|
1093
1243
|
dataDescriptor = false;
|
|
1094
1244
|
}
|
|
@@ -1137,6 +1287,8 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1137
1287
|
const initialOffset = writerOptions[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : writerOptions[OPTION_OFFSET];
|
|
1138
1288
|
let offset = initialOffset;
|
|
1139
1289
|
let minimumEntrySize = INFINITY_VALUE;
|
|
1290
|
+
const entrySizes = [];
|
|
1291
|
+
const entriesAlreadyZip64 = new Set();
|
|
1140
1292
|
for (const entry of entries) {
|
|
1141
1293
|
let { name } = entry;
|
|
1142
1294
|
const { size } = entry;
|
|
@@ -1148,7 +1300,7 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1148
1300
|
({ name } = attributesInfo);
|
|
1149
1301
|
const { resolvedOptions: metadata } = resolveMetadata(zipWriter, name, options);
|
|
1150
1302
|
if (metadata.level != 0 && metadata.compressionMethod === UNDEFINED_VALUE &&
|
|
1151
|
-
!metadata.
|
|
1303
|
+
!metadata.passThroughCompression && !(await supportsDeflate(getConfiguration()))) {
|
|
1152
1304
|
metadata.level = 0;
|
|
1153
1305
|
}
|
|
1154
1306
|
const hasContent = !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY);
|
|
@@ -1156,7 +1308,7 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1156
1308
|
throw new Error(ERR_UNDETERMINED_SIZE);
|
|
1157
1309
|
}
|
|
1158
1310
|
const { maximumCompressedSize, resolvedOptions: sizes } = resolveEntrySizes(zipWriter, hasContent, size, metadata, options);
|
|
1159
|
-
if (hasContent && !metadata.
|
|
1311
|
+
if (hasContent && !metadata.passThroughCompression && isCompressed(sizes.compressionMethod, sizes.level)) {
|
|
1160
1312
|
throw new Error(ERR_UNDETERMINED_SIZE);
|
|
1161
1313
|
}
|
|
1162
1314
|
const entryOptions = Object.assign({}, options, attributesInfo.resolvedOptions, metadata, sizes, { [OPTION_USDZ]: usdz });
|
|
@@ -1176,10 +1328,15 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1176
1328
|
compressedSize
|
|
1177
1329
|
}));
|
|
1178
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));
|
|
1179
1334
|
minimumEntrySize = Math.min(minimumEntrySize, entrySize);
|
|
1180
1335
|
offset += entrySize;
|
|
1181
1336
|
}
|
|
1182
|
-
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))));
|
|
1183
1340
|
if (layoutDependsOnWriteOrder && !writeOrderGuaranteed) {
|
|
1184
1341
|
throw new Error(ERR_UNDETERMINED_SIZE);
|
|
1185
1342
|
}
|
|
@@ -1197,6 +1354,20 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1197
1354
|
return offset - initialOffset + directoryDataLength + commentLength + (zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
|
|
1198
1355
|
}
|
|
1199
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
|
+
|
|
1200
1371
|
async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
1201
1372
|
const {
|
|
1202
1373
|
fileEntries,
|
|
@@ -1372,6 +1543,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1372
1543
|
localExtraFieldZip64Length,
|
|
1373
1544
|
rawExtraFieldExtendedTimestamp,
|
|
1374
1545
|
extraFieldExtendedTimestampFlag,
|
|
1546
|
+
extraFieldExtendedTimestampTime,
|
|
1375
1547
|
rawExtraFieldNTFS,
|
|
1376
1548
|
rawExtraFieldUnix,
|
|
1377
1549
|
rawExtraFieldAES,
|
|
@@ -1384,6 +1556,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1384
1556
|
password,
|
|
1385
1557
|
rawPassword,
|
|
1386
1558
|
level,
|
|
1559
|
+
useUnicodeFileNames,
|
|
1387
1560
|
zip64,
|
|
1388
1561
|
zip64Enabled,
|
|
1389
1562
|
zip64UncompressedSize,
|
|
@@ -1418,7 +1591,8 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1418
1591
|
msdosAttributesRaw,
|
|
1419
1592
|
msdosAttributes,
|
|
1420
1593
|
useCompressionStream,
|
|
1421
|
-
|
|
1594
|
+
passThroughCompression,
|
|
1595
|
+
passThroughEncryption,
|
|
1422
1596
|
format,
|
|
1423
1597
|
codecURI
|
|
1424
1598
|
} = options;
|
|
@@ -1429,9 +1603,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1429
1603
|
zip64Enabled,
|
|
1430
1604
|
directory: Boolean(directory),
|
|
1431
1605
|
executable: Boolean(executable),
|
|
1432
|
-
filenameUTF8:
|
|
1606
|
+
filenameUTF8: Boolean(useUnicodeFileNames),
|
|
1433
1607
|
rawFilename,
|
|
1434
|
-
commentUTF8:
|
|
1608
|
+
commentUTF8: Boolean(useUnicodeFileNames),
|
|
1435
1609
|
rawComment,
|
|
1436
1610
|
rawExtraFieldZip64,
|
|
1437
1611
|
localExtraFieldZip64Length,
|
|
@@ -1462,7 +1636,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1462
1636
|
uncompressedSize
|
|
1463
1637
|
} = options;
|
|
1464
1638
|
let compressedSize = 0;
|
|
1465
|
-
if (!
|
|
1639
|
+
if (!passThroughCompression) {
|
|
1466
1640
|
uncompressedSize = 0;
|
|
1467
1641
|
}
|
|
1468
1642
|
const { writable } = writer;
|
|
@@ -1479,9 +1653,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1479
1653
|
encryptionStrength,
|
|
1480
1654
|
zipCrypto: encrypted && zipCrypto,
|
|
1481
1655
|
passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & MAX_8_BITS,
|
|
1482
|
-
computeCrc32: !
|
|
1483
|
-
compressed: compressed && !
|
|
1484
|
-
encrypted: encrypted && !
|
|
1656
|
+
computeCrc32: !passThroughCompression,
|
|
1657
|
+
compressed: compressed && !passThroughCompression,
|
|
1658
|
+
encrypted: encrypted && !passThroughEncryption,
|
|
1485
1659
|
useWebWorkers,
|
|
1486
1660
|
useCompressionStream,
|
|
1487
1661
|
transferStreams,
|
|
@@ -1496,7 +1670,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1496
1670
|
const result = await runWorker({ readable, writable }, workerOptions);
|
|
1497
1671
|
compressedSize = result.outputSize;
|
|
1498
1672
|
writer.size += compressedSize;
|
|
1499
|
-
if (!
|
|
1673
|
+
if (!passThroughCompression) {
|
|
1500
1674
|
uncompressedSize = result.inputSize;
|
|
1501
1675
|
if (!encrypted || zipCrypto) {
|
|
1502
1676
|
crc32 = result.crc32;
|
|
@@ -1539,8 +1713,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1539
1713
|
headerArray,
|
|
1540
1714
|
headerView,
|
|
1541
1715
|
signature: crc32,
|
|
1542
|
-
crc32: encrypted && !zipCrypto && !
|
|
1716
|
+
crc32: encrypted && !zipCrypto && !passThroughCompression ? UNDEFINED_VALUE : crc32,
|
|
1543
1717
|
extraFieldExtendedTimestampFlag,
|
|
1718
|
+
extraFieldExtendedTimestampTime,
|
|
1544
1719
|
zip64UncompressedSize,
|
|
1545
1720
|
zip64CompressedSize
|
|
1546
1721
|
});
|
|
@@ -1565,7 +1740,7 @@ function getHeaderInfo(options) {
|
|
|
1565
1740
|
encryptionStrength,
|
|
1566
1741
|
extendedTimestamp,
|
|
1567
1742
|
ntfsTimestamp,
|
|
1568
|
-
|
|
1743
|
+
passThroughCompression,
|
|
1569
1744
|
encrypted,
|
|
1570
1745
|
zip64UncompressedSize,
|
|
1571
1746
|
zip64CompressedSize,
|
|
@@ -1576,7 +1751,7 @@ function getHeaderInfo(options) {
|
|
|
1576
1751
|
let { version, compressionMethod } = options;
|
|
1577
1752
|
const compressed = !directory && isCompressed(compressionMethod, level);
|
|
1578
1753
|
let rawLocalExtraFieldZip64;
|
|
1579
|
-
const uncompressedFile =
|
|
1754
|
+
const uncompressedFile = passThroughCompression || !compressed;
|
|
1580
1755
|
const zip64ExtraFieldComplete = zip64 && (options.bufferedWrite || !dataDescriptor || ((!zip64UncompressedSize && !zip64CompressedSize) || (uncompressedFile && !unknownSize)));
|
|
1581
1756
|
const writeLocalExtraFieldZip64 = zip64ExtraFieldComplete || (zip64 && dataDescriptor && (zip64UncompressedSize || zip64CompressedSize));
|
|
1582
1757
|
if (zip64 && (zip64UncompressedSize || zip64CompressedSize)) {
|
|
@@ -1588,8 +1763,8 @@ function getHeaderInfo(options) {
|
|
|
1588
1763
|
if (zip64ExtraFieldComplete) {
|
|
1589
1764
|
extraFieldZip64.writeUint64(uncompressedSize);
|
|
1590
1765
|
if (uncompressedFile) {
|
|
1591
|
-
const encryptionOverhead = encrypted
|
|
1592
|
-
extraFieldZip64.writeUint64(
|
|
1766
|
+
const encryptionOverhead = getEncryptionOverhead(encrypted, zipCrypto, encryptionStrength);
|
|
1767
|
+
extraFieldZip64.writeUint64(passThroughCompression ? 0 : uncompressedSize + encryptionOverhead);
|
|
1593
1768
|
}
|
|
1594
1769
|
}
|
|
1595
1770
|
} else {
|
|
@@ -1608,6 +1783,7 @@ function getHeaderInfo(options) {
|
|
|
1608
1783
|
let rawExtraFieldNTFS;
|
|
1609
1784
|
let rawExtraFieldExtendedTimestamp;
|
|
1610
1785
|
let extraFieldExtendedTimestampFlag;
|
|
1786
|
+
let extraFieldExtendedTimestampTime;
|
|
1611
1787
|
if (extendedTimestamp) {
|
|
1612
1788
|
const lastModTimeUnix = getTimeUnix(lastModDate);
|
|
1613
1789
|
const lastModTimeUnixInRange = inUnixTimeRange(lastModTimeUnix);
|
|
@@ -1615,6 +1791,7 @@ function getHeaderInfo(options) {
|
|
|
1615
1791
|
const extraFieldTimestampLength = 9 + (lastAccessDate ? 4 : 0) + (creationDate ? 4 : 0);
|
|
1616
1792
|
const extraFieldTimestamp = createRecordWriter(extraFieldTimestampLength);
|
|
1617
1793
|
extraFieldExtendedTimestampFlag = 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0);
|
|
1794
|
+
extraFieldExtendedTimestampTime = lastModTimeUnix;
|
|
1618
1795
|
extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
1619
1796
|
extraFieldTimestamp.writeUint16(extraFieldTimestampLength - 4);
|
|
1620
1797
|
extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
|
|
@@ -1698,7 +1875,7 @@ function getHeaderInfo(options) {
|
|
|
1698
1875
|
}
|
|
1699
1876
|
if (encrypted && !zipCrypto) {
|
|
1700
1877
|
version = version > VERSION_AES ? version : VERSION_AES;
|
|
1701
|
-
if (
|
|
1878
|
+
if (passThroughCompression && crc32 !== UNDEFINED_VALUE) {
|
|
1702
1879
|
rawExtraFieldAES[EXTRAFIELD_OFFSET_AES_VENDOR_VERSION] = VENDOR_VERSION_AE_1;
|
|
1703
1880
|
}
|
|
1704
1881
|
setUint16(getDataView(rawExtraFieldAES), EXTRAFIELD_OFFSET_AES_COMPRESSION_METHOD, compressionMethod);
|
|
@@ -1760,12 +1937,14 @@ function getHeaderInfo(options) {
|
|
|
1760
1937
|
headerArray,
|
|
1761
1938
|
headerView,
|
|
1762
1939
|
lastModDate: storedLastModDate,
|
|
1940
|
+
lastModDateClamped: storedLastModDate === clampedLastModDate && dosLastModDate.getTime() != clampedLastModDate.getTime(),
|
|
1763
1941
|
rawLastModDate,
|
|
1764
1942
|
encrypted,
|
|
1765
1943
|
compressed,
|
|
1766
1944
|
version,
|
|
1767
1945
|
compressionMethod,
|
|
1768
1946
|
extraFieldExtendedTimestampFlag,
|
|
1947
|
+
extraFieldExtendedTimestampTime,
|
|
1769
1948
|
rawExtraFieldZip64: EMPTY_UINT8_ARRAY,
|
|
1770
1949
|
localExtraFieldZip64Length,
|
|
1771
1950
|
rawExtraFieldExtendedTimestamp,
|
|
@@ -1868,7 +2047,7 @@ function setEntryInfo({
|
|
|
1868
2047
|
}, {
|
|
1869
2048
|
zip64,
|
|
1870
2049
|
zipCrypto,
|
|
1871
|
-
|
|
2050
|
+
passThroughCompression,
|
|
1872
2051
|
dataDescriptor
|
|
1873
2052
|
}) {
|
|
1874
2053
|
const {
|
|
@@ -1879,7 +2058,7 @@ function setEntryInfo({
|
|
|
1879
2058
|
dataDescriptorView,
|
|
1880
2059
|
dataDescriptorOffset
|
|
1881
2060
|
} = dataDescriptorInfo;
|
|
1882
|
-
if ((!encrypted || zipCrypto ||
|
|
2061
|
+
if ((!encrypted || zipCrypto || passThroughCompression) && crc32 !== UNDEFINED_VALUE) {
|
|
1883
2062
|
setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
|
|
1884
2063
|
if (dataDescriptor) {
|
|
1885
2064
|
setUint32(dataDescriptorView, dataDescriptorOffset, crc32);
|
|
@@ -1910,9 +2089,9 @@ function updateLocalHeader({
|
|
|
1910
2089
|
uncompressedSize,
|
|
1911
2090
|
zip64UncompressedSize,
|
|
1912
2091
|
zip64CompressedSize
|
|
1913
|
-
}, localHeaderView, { dataDescriptor,
|
|
2092
|
+
}, localHeaderView, { dataDescriptor, passThroughCompression }) {
|
|
1914
2093
|
if (!dataDescriptor) {
|
|
1915
|
-
if (!encrypted || (
|
|
2094
|
+
if (!encrypted || (passThroughCompression && crc32 !== UNDEFINED_VALUE)) {
|
|
1916
2095
|
setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, crc32);
|
|
1917
2096
|
}
|
|
1918
2097
|
if (!zip64CompressedSize) {
|
|
@@ -1949,9 +2128,8 @@ function createDirectoryRecords(files) {
|
|
|
1949
2128
|
rawExtraFieldUnix,
|
|
1950
2129
|
rawExtraField,
|
|
1951
2130
|
rawCentralExtraField,
|
|
1952
|
-
extendedTimestamp,
|
|
1953
2131
|
extraFieldExtendedTimestampFlag,
|
|
1954
|
-
|
|
2132
|
+
extraFieldExtendedTimestampTime,
|
|
1955
2133
|
zip64Enabled,
|
|
1956
2134
|
uncompressedSize,
|
|
1957
2135
|
compressedSize
|
|
@@ -1994,16 +2172,15 @@ function createDirectoryRecords(files) {
|
|
|
1994
2172
|
fileEntry.zip64Offset = zip64Offset;
|
|
1995
2173
|
fileEntry.zip64DiskNumberStart = zip64DiskNumberStart;
|
|
1996
2174
|
let rawExtraFieldTimestamp;
|
|
1997
|
-
|
|
1998
|
-
|
|
2175
|
+
if (extraFieldExtendedTimestampTime === UNDEFINED_VALUE) {
|
|
2176
|
+
rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
|
|
2177
|
+
} else {
|
|
1999
2178
|
const extraFieldTimestamp = createRecordWriter(9);
|
|
2000
2179
|
extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
2001
2180
|
extraFieldTimestamp.writeUint16(5);
|
|
2002
2181
|
extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
|
|
2003
|
-
extraFieldTimestamp.writeUint32(
|
|
2182
|
+
extraFieldTimestamp.writeUint32(extraFieldExtendedTimestampTime);
|
|
2004
2183
|
rawExtraFieldTimestamp = extraFieldTimestamp.array;
|
|
2005
|
-
} else {
|
|
2006
|
-
rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
|
|
2007
2184
|
}
|
|
2008
2185
|
fileEntry.rawExtraFieldExtendedTimestamp = rawExtraFieldTimestamp;
|
|
2009
2186
|
const extraFieldLength = getLength(
|
|
@@ -2503,6 +2680,11 @@ function getHeaderArrayData({
|
|
|
2503
2680
|
};
|
|
2504
2681
|
}
|
|
2505
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
|
+
|
|
2506
2688
|
function getBitFlag(level, useUnicodeFileNames, dataDescriptor, encrypted, compressionMethod) {
|
|
2507
2689
|
let bitFlag = 0;
|
|
2508
2690
|
if (useUnicodeFileNames) {
|