@zip.js/zip.js 2.8.43 → 2.8.45
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/README.md +0 -37
- package/deno.json +21 -1
- package/dist/zip-core-external.js +194 -159
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +194 -131
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +246 -167
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +244 -139
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +267 -1761
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +269 -1735
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +268 -1734
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +196 -133
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +196 -133
- 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 +195 -132
- package/dist/zip.min.js +1 -1
- package/eslint.config.mjs +31 -2
- package/index-native.cjs +269 -1735
- package/index-native.min.js +1 -1
- package/index.cjs +268 -1734
- package/index.d.cts +129 -8
- package/index.d.ts +129 -8
- package/index.min.js +1 -1
- package/lib/core/codec-pool.js +6 -2
- package/lib/core/codec-worker.js +2 -2
- package/lib/core/constants.js +4 -0
- package/lib/core/options.js +6 -0
- package/lib/core/streams/aes-crypto-stream.js +18 -21
- package/lib/core/streams/codec-stream.js +6 -2
- package/lib/core/streams/common-crypto.js +2 -0
- package/lib/core/streams/zip-entry-stream.js +16 -17
- package/lib/core/util/mime-type-data.js +3 -0
- package/lib/core/util/mime-type.js +23 -1596
- package/lib/core/web-worker-base.js +2 -2
- package/lib/core/web-worker-inline-native.js +1 -1
- package/lib/core/web-worker-inline-wasm.js +1 -1
- package/lib/core/web-worker-wasm.js +4 -8
- package/lib/core/zip-entry.js +11 -1
- package/lib/core/zip-fs.js +62 -5
- package/lib/core/zip-reader.js +80 -43
- package/lib/core/zip-writer.js +68 -45
- package/lib/zip-core-external.js +2 -0
- package/lib/zip-core-reader.js +2 -0
- package/lib/zip-fs-core-external.js +2 -0
- package/lib/zip-fs-external.js +2 -0
- package/lib/zip-mime-types.js +2 -0
- package/package.json +9 -3
- package/worker-message-property-names.js +1 -1
package/lib/core/zip-reader.js
CHANGED
|
@@ -57,6 +57,8 @@ import {
|
|
|
57
57
|
EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP,
|
|
58
58
|
EXTRAFIELD_TYPE_INFOZIP,
|
|
59
59
|
EXTRAFIELD_TYPE_UNIX,
|
|
60
|
+
EXTRAFIELD_TYPE_UNIX_TYPE1,
|
|
61
|
+
EXTRAFIELD_TYPE_PKWARE_UNIX,
|
|
60
62
|
EXTRAFIELD_TYPE_USDZ,
|
|
61
63
|
END_OF_CENTRAL_DIR_LENGTH,
|
|
62
64
|
ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH,
|
|
@@ -93,6 +95,8 @@ import {
|
|
|
93
95
|
runWorker,
|
|
94
96
|
CODEC_INFLATE,
|
|
95
97
|
ERR_INVALID_SIGNATURE,
|
|
98
|
+
ERR_INVALID_CRC32,
|
|
99
|
+
ERR_INVALID_AUTHENTICATION_CODE,
|
|
96
100
|
ERR_INVALID_PASSWORD,
|
|
97
101
|
ERR_INVALID_UNCOMPRESSED_SIZE,
|
|
98
102
|
ERR_INVALID_COMPRESSED_DATA,
|
|
@@ -141,6 +145,8 @@ import {
|
|
|
141
145
|
OPTION_CHECK_OVERLAPPING_ENTRY,
|
|
142
146
|
OPTION_CHECK_AMBIGUITY,
|
|
143
147
|
OPTION_CHECK_SIGNATURE,
|
|
148
|
+
OPTION_CHECK_CRC32,
|
|
149
|
+
OPTION_CHECK_AUTHENTICATION_CODE,
|
|
144
150
|
OPTION_STRICTNESS,
|
|
145
151
|
OPTION_MAX_APPENDED_DATA_SIZE,
|
|
146
152
|
STRICTNESS_STRICT,
|
|
@@ -169,6 +175,7 @@ const CHARSET_UTF8 = "utf-8";
|
|
|
169
175
|
const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
|
|
170
176
|
const CHARSET_CP437 = "cp437";
|
|
171
177
|
const BITFLAG_AMBIGUITY_MASK = BITFLAG_ENCRYPTED | BITFLAG_DATA_DESCRIPTOR | BITFLAG_LANG_ENCODING_FLAG;
|
|
178
|
+
const VENDOR_VERSION_AE_1 = 1;
|
|
172
179
|
const ZIP64_PROPERTIES = [
|
|
173
180
|
[PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
|
|
174
181
|
[PROPERTY_NAME_COMPRESSED_SIZE, MAX_32_BITS],
|
|
@@ -551,6 +558,8 @@ export {
|
|
|
551
558
|
ERR_UNSUPPORTED_ENCRYPTION,
|
|
552
559
|
ERR_UNSUPPORTED_COMPRESSION,
|
|
553
560
|
ERR_INVALID_SIGNATURE,
|
|
561
|
+
ERR_INVALID_CRC32,
|
|
562
|
+
ERR_INVALID_AUTHENTICATION_CODE,
|
|
554
563
|
ERR_INVALID_PASSWORD,
|
|
555
564
|
ERR_INVALID_UNCOMPRESSED_SIZE,
|
|
556
565
|
ERR_INVALID_COMPRESSED_DATA,
|
|
@@ -583,7 +592,7 @@ class ZipEntry {
|
|
|
583
592
|
config,
|
|
584
593
|
bitFlag,
|
|
585
594
|
rawBitFlag,
|
|
586
|
-
|
|
595
|
+
crc32,
|
|
587
596
|
rawLastModDate,
|
|
588
597
|
uncompressedSize,
|
|
589
598
|
compressedSize
|
|
@@ -670,6 +679,11 @@ class ZipEntry {
|
|
|
670
679
|
if (deflate64) {
|
|
671
680
|
useCompressionStream = false;
|
|
672
681
|
}
|
|
682
|
+
const checkCrc32Option = getOptionValue(zipEntry, options, OPTION_CHECK_CRC32);
|
|
683
|
+
const checkCrc32 = (checkCrc32Option === UNDEFINED_VALUE ?
|
|
684
|
+
getOptionValue(zipEntry, options, OPTION_CHECK_SIGNATURE) :
|
|
685
|
+
checkCrc32Option) && !passThrough &&
|
|
686
|
+
(!encrypted || zipCrypto || (extraFieldAES && extraFieldAES.vendorVersion == VENDOR_VERSION_AE_1));
|
|
673
687
|
const workerOptions = {
|
|
674
688
|
options: {
|
|
675
689
|
codecType: CODEC_INFLATE,
|
|
@@ -677,10 +691,11 @@ class ZipEntry {
|
|
|
677
691
|
rawPassword,
|
|
678
692
|
zipCrypto,
|
|
679
693
|
encryptionStrength: extraFieldAES && extraFieldAES.strength,
|
|
680
|
-
|
|
681
|
-
|
|
694
|
+
checkCrc32,
|
|
695
|
+
checkAuthenticationCode: getOptionValue(zipEntry, options, OPTION_CHECK_AUTHENTICATION_CODE),
|
|
696
|
+
passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((crc32 >>> 24) & MAX_8_BITS)),
|
|
682
697
|
outputSize: passThrough ? compressedSize : uncompressedSize,
|
|
683
|
-
|
|
698
|
+
crc32,
|
|
684
699
|
compressed: compressionMethod != 0 && !passThrough,
|
|
685
700
|
encrypted,
|
|
686
701
|
useWebWorkers: getOptionValue(zipEntry, options, OPTION_USE_WEB_WORKERS),
|
|
@@ -702,7 +717,7 @@ class ZipEntry {
|
|
|
702
717
|
fileEntry,
|
|
703
718
|
index,
|
|
704
719
|
offset: localHeaderOffset,
|
|
705
|
-
|
|
720
|
+
crc32,
|
|
706
721
|
compressedSize,
|
|
707
722
|
uncompressedSize,
|
|
708
723
|
dataOffset,
|
|
@@ -793,6 +808,7 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
|
|
|
793
808
|
const compressionMethod = getUint16(dataView, offset + 4);
|
|
794
809
|
Object.assign(directory, {
|
|
795
810
|
signature: getUint32(dataView, offset + HEADER_OFFSET_SIGNATURE),
|
|
811
|
+
crc32: getUint32(dataView, offset + HEADER_OFFSET_SIGNATURE),
|
|
796
812
|
compressedSize: getUint32(dataView, offset + HEADER_OFFSET_COMPRESSED_SIZE),
|
|
797
813
|
uncompressedSize: getUint32(dataView, offset + HEADER_OFFSET_UNCOMPRESSED_SIZE)
|
|
798
814
|
});
|
|
@@ -818,6 +834,16 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
|
|
|
818
834
|
} else {
|
|
819
835
|
directory.compressionMethod = compressionMethod;
|
|
820
836
|
}
|
|
837
|
+
const extraFieldPkwareUnix = extraField.get(EXTRAFIELD_TYPE_PKWARE_UNIX);
|
|
838
|
+
if (extraFieldPkwareUnix) {
|
|
839
|
+
readExtraFieldUnixDates(extraFieldPkwareUnix, directory);
|
|
840
|
+
directory.extraFieldPkwareUnix = extraFieldPkwareUnix;
|
|
841
|
+
}
|
|
842
|
+
const extraFieldUnixType1 = extraField.get(EXTRAFIELD_TYPE_UNIX_TYPE1);
|
|
843
|
+
if (extraFieldUnixType1) {
|
|
844
|
+
readExtraFieldUnixDates(extraFieldUnixType1, directory);
|
|
845
|
+
directory.extraFieldUnixType1 = extraFieldUnixType1;
|
|
846
|
+
}
|
|
821
847
|
const extraFieldNTFS = extraField.get(EXTRAFIELD_TYPE_NTFS);
|
|
822
848
|
if (extraFieldNTFS) {
|
|
823
849
|
readExtraFieldNTFS(extraFieldNTFS, directory);
|
|
@@ -867,15 +893,15 @@ function readExtraFieldUnicode(extraFieldUnicode, propertyName, rawPropertyName,
|
|
|
867
893
|
return;
|
|
868
894
|
}
|
|
869
895
|
const extraFieldView = getDataView(extraFieldUnicode.data);
|
|
870
|
-
const
|
|
871
|
-
|
|
872
|
-
const
|
|
873
|
-
|
|
874
|
-
const
|
|
896
|
+
const computedCrc32 = new Crc32();
|
|
897
|
+
computedCrc32.append(fileEntry[rawPropertyName]);
|
|
898
|
+
const computedCrc32View = getDataView(new Uint8Array(4));
|
|
899
|
+
computedCrc32View.setUint32(0, computedCrc32.get(), true);
|
|
900
|
+
const nameCrc32 = getUint32(extraFieldView, 1);
|
|
875
901
|
Object.assign(extraFieldUnicode, {
|
|
876
902
|
version: getUint8(extraFieldView, 0),
|
|
877
903
|
[propertyName]: decodeText(extraFieldUnicode.data.subarray(5)),
|
|
878
|
-
valid: !fileEntry.bitFlag.languageEncodingFlag &&
|
|
904
|
+
valid: !fileEntry.bitFlag.languageEncodingFlag && nameCrc32 == getUint32(computedCrc32View, 0)
|
|
879
905
|
});
|
|
880
906
|
if (extraFieldUnicode.valid) {
|
|
881
907
|
directory[propertyName] = extraFieldUnicode[propertyName];
|
|
@@ -894,6 +920,9 @@ function readExtraFieldAES(extraFieldAES, directory, compressionMethod) {
|
|
|
894
920
|
compressionMethod: getUint16(extraFieldView, 5)
|
|
895
921
|
});
|
|
896
922
|
directory.compressionMethod = extraFieldAES.compressionMethod;
|
|
923
|
+
if (extraFieldAES.vendorVersion != VENDOR_VERSION_AE_1) {
|
|
924
|
+
directory.crc32 = UNDEFINED_VALUE;
|
|
925
|
+
}
|
|
897
926
|
}
|
|
898
927
|
|
|
899
928
|
function readExtraFieldNTFS(extraFieldNTFS, directory) {
|
|
@@ -912,29 +941,41 @@ function readExtraFieldNTFS(extraFieldNTFS, directory) {
|
|
|
912
941
|
} catch {
|
|
913
942
|
// ignored
|
|
914
943
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
Object.assign(directory, extraFieldData);
|
|
932
|
-
}
|
|
933
|
-
} catch {
|
|
934
|
-
// ignored
|
|
944
|
+
if (tag1Data && tag1Data.length == 24) {
|
|
945
|
+
const tag1View = getDataView(tag1Data);
|
|
946
|
+
const rawLastModDate = tag1View.getBigUint64(0, true);
|
|
947
|
+
const rawLastAccessDate = tag1View.getBigUint64(8, true);
|
|
948
|
+
const rawCreationDate = tag1View.getBigUint64(16, true);
|
|
949
|
+
Object.assign(extraFieldNTFS, {
|
|
950
|
+
rawLastModDate,
|
|
951
|
+
rawLastAccessDate,
|
|
952
|
+
rawCreationDate
|
|
953
|
+
});
|
|
954
|
+
const lastModDate = getDateNTFS(rawLastModDate);
|
|
955
|
+
const lastAccessDate = getDateNTFS(rawLastAccessDate);
|
|
956
|
+
const creationDate = getDateNTFS(rawCreationDate);
|
|
957
|
+
const extraFieldData = { lastModDate, lastAccessDate, creationDate };
|
|
958
|
+
Object.assign(extraFieldNTFS, extraFieldData);
|
|
959
|
+
Object.assign(directory, extraFieldData);
|
|
935
960
|
}
|
|
936
961
|
}
|
|
937
962
|
|
|
963
|
+
function readExtraFieldUnixDates(extraField, directory) {
|
|
964
|
+
if (extraField.data.length < 8) {
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
const extraFieldView = getDataView(extraField.data);
|
|
968
|
+
const lastAccessDate = new Date(getUint32(extraFieldView, 0) * 1000);
|
|
969
|
+
const lastModDate = new Date(getUint32(extraFieldView, 4) * 1000);
|
|
970
|
+
const extraFieldData = { lastAccessDate, lastModDate };
|
|
971
|
+
if (extraField.data.length >= 12) {
|
|
972
|
+
extraFieldData.uid = getUint16(extraFieldView, 8);
|
|
973
|
+
extraFieldData.gid = getUint16(extraFieldView, 10);
|
|
974
|
+
}
|
|
975
|
+
Object.assign(extraField, extraFieldData);
|
|
976
|
+
Object.assign(directory, extraFieldData);
|
|
977
|
+
}
|
|
978
|
+
|
|
938
979
|
function readExtraFieldUnix(extraField, directory, isInfoZip) {
|
|
939
980
|
try {
|
|
940
981
|
const view = getDataView(extraField.data);
|
|
@@ -1013,7 +1054,7 @@ async function detectOverlappingEntry({
|
|
|
1013
1054
|
fileEntry,
|
|
1014
1055
|
index,
|
|
1015
1056
|
offset,
|
|
1016
|
-
|
|
1057
|
+
crc32,
|
|
1017
1058
|
compressedSize,
|
|
1018
1059
|
uncompressedSize,
|
|
1019
1060
|
dataOffset,
|
|
@@ -1034,7 +1075,7 @@ async function detectOverlappingEntry({
|
|
|
1034
1075
|
const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
|
|
1035
1076
|
getUint32(getDataView(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
|
|
1036
1077
|
if (dataDescriptorSignature) {
|
|
1037
|
-
const
|
|
1078
|
+
const readCrc32 = getUint32(getDataView(dataDescriptorArray), 4);
|
|
1038
1079
|
let readCompressedSize;
|
|
1039
1080
|
let readUncompressedSize;
|
|
1040
1081
|
if (extraFieldZip64) {
|
|
@@ -1044,8 +1085,8 @@ async function detectOverlappingEntry({
|
|
|
1044
1085
|
readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
|
|
1045
1086
|
readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
|
|
1046
1087
|
}
|
|
1047
|
-
const
|
|
1048
|
-
if (
|
|
1088
|
+
const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || readCrc32 == crc32;
|
|
1089
|
+
if (matchCrc32 &&
|
|
1049
1090
|
readCompressedSize == compressedSize &&
|
|
1050
1091
|
readUncompressedSize == uncompressedSize) {
|
|
1051
1092
|
dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
|
|
@@ -1214,11 +1255,11 @@ function checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename) {
|
|
|
1214
1255
|
throwAmbiguousArchive("mismatched local file header (compression method)");
|
|
1215
1256
|
}
|
|
1216
1257
|
if (!localDirectory.bitFlag.dataDescriptor &&
|
|
1217
|
-
(localDirectory.
|
|
1218
|
-
(localDirectory.
|
|
1258
|
+
(localDirectory.crc32 || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
|
|
1259
|
+
(localDirectory.crc32 != zipEntry.crc32 ||
|
|
1219
1260
|
localDirectory.compressedSize != zipEntry.compressedSize ||
|
|
1220
1261
|
localDirectory.uncompressedSize != zipEntry.uncompressedSize)) {
|
|
1221
|
-
throwAmbiguousArchive("mismatched local file header (
|
|
1262
|
+
throwAmbiguousArchive("mismatched local file header (crc32 or sizes)");
|
|
1222
1263
|
}
|
|
1223
1264
|
}
|
|
1224
1265
|
|
|
@@ -1234,11 +1275,7 @@ function getOptionValue(zipReader, options, name) {
|
|
|
1234
1275
|
|
|
1235
1276
|
function getDate(timeRaw) {
|
|
1236
1277
|
const date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & MAX_16_BITS;
|
|
1237
|
-
|
|
1238
|
-
return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
|
|
1239
|
-
} catch {
|
|
1240
|
-
// ignored
|
|
1241
|
-
}
|
|
1278
|
+
return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
|
|
1242
1279
|
}
|
|
1243
1280
|
|
|
1244
1281
|
function getDateNTFS(timeRaw) {
|
package/lib/core/zip-writer.js
CHANGED
|
@@ -208,7 +208,8 @@ import {
|
|
|
208
208
|
OPTION_ENCODE_TEXT,
|
|
209
209
|
OPTION_OFFSET,
|
|
210
210
|
OPTION_USDZ,
|
|
211
|
-
OPTION_UNIX_EXTRA_FIELD_TYPE
|
|
211
|
+
OPTION_UNIX_EXTRA_FIELD_TYPE,
|
|
212
|
+
OPTION_LOCAL_EXTRA_FIELD
|
|
212
213
|
} from "./options.js";
|
|
213
214
|
|
|
214
215
|
const ERR_DUPLICATED_NAME = "File already exists";
|
|
@@ -223,6 +224,8 @@ const ERR_INVALID_EXTRAFIELD_DATA = "Extra field data exceeds 64KB";
|
|
|
223
224
|
const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
|
|
224
225
|
const MIN_UNIX_TIME = -2147483648;
|
|
225
226
|
const MAX_UNIX_TIME = 2147483647;
|
|
227
|
+
const MIN_NTFS_TIME = BigInt(0);
|
|
228
|
+
const MAX_NTFS_TIME = BigInt("0x7fffffffffffffff");
|
|
226
229
|
const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
|
|
227
230
|
const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
|
|
228
231
|
const ERR_UNDEFINED_READER = "Undefined reader";
|
|
@@ -236,6 +239,8 @@ const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be intege
|
|
|
236
239
|
const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
|
|
237
240
|
|
|
238
241
|
const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
|
|
242
|
+
const EXTRAFIELD_OFFSET_AES_VENDOR_VERSION = 4;
|
|
243
|
+
const VENDOR_VERSION_AE_1 = 1;
|
|
239
244
|
const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
|
|
240
245
|
const UNIX_EXTRA_FIELD_TYPE = "unix";
|
|
241
246
|
|
|
@@ -330,9 +335,9 @@ class ZipWriter {
|
|
|
330
335
|
zip64UncompressedSize,
|
|
331
336
|
extraFieldLength
|
|
332
337
|
});
|
|
333
|
-
const {
|
|
334
|
-
if (
|
|
335
|
-
setUint32(headerView, HEADER_OFFSET_SIGNATURE,
|
|
338
|
+
const { crc32 } = entry;
|
|
339
|
+
if (crc32 !== UNDEFINED_VALUE) {
|
|
340
|
+
setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
|
|
336
341
|
}
|
|
337
342
|
Object.assign(entry, {
|
|
338
343
|
zip64UncompressedSize,
|
|
@@ -535,6 +540,7 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
535
540
|
internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
|
|
536
541
|
externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
|
|
537
542
|
signature: options[PROPERTY_NAME_SIGNATURE],
|
|
543
|
+
crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
|
|
538
544
|
offset: zipWriter.offset - diskOffset,
|
|
539
545
|
diskNumberStart: diskNumber
|
|
540
546
|
});
|
|
@@ -751,27 +757,8 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
751
757
|
if (!zipCrypto && (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) && !(encryptionStrength >= 1 && encryptionStrength <= 3)) {
|
|
752
758
|
throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
|
|
753
759
|
}
|
|
754
|
-
|
|
755
|
-
const
|
|
756
|
-
if (extraField) {
|
|
757
|
-
let extraFieldSize = 0;
|
|
758
|
-
let offset = 0;
|
|
759
|
-
extraField.forEach(data => extraFieldSize += 4 + getLength(data));
|
|
760
|
-
rawExtraField = new Uint8Array(extraFieldSize);
|
|
761
|
-
const rawExtraFieldView = getDataView(rawExtraField);
|
|
762
|
-
extraField.forEach((data, type) => {
|
|
763
|
-
if (type > MAX_16_BITS) {
|
|
764
|
-
throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
|
|
765
|
-
}
|
|
766
|
-
if (getLength(data) > MAX_16_BITS) {
|
|
767
|
-
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
768
|
-
}
|
|
769
|
-
setUint16(rawExtraFieldView, offset, type);
|
|
770
|
-
setUint16(rawExtraFieldView, offset + 2, getLength(data));
|
|
771
|
-
arraySet(rawExtraField, data, offset + 4);
|
|
772
|
-
offset += 4 + getLength(data);
|
|
773
|
-
});
|
|
774
|
-
}
|
|
760
|
+
const rawExtraField = serializeExtraField(options[PROPERTY_NAME_EXTRA_FIELD]);
|
|
761
|
+
const rawLocalExtraField = serializeExtraField(options[OPTION_LOCAL_EXTRA_FIELD]);
|
|
775
762
|
return {
|
|
776
763
|
comment,
|
|
777
764
|
resolvedOptions: {
|
|
@@ -805,11 +792,36 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
805
792
|
useCompressionStream,
|
|
806
793
|
dataDescriptor,
|
|
807
794
|
zip64,
|
|
808
|
-
rawExtraField
|
|
795
|
+
rawExtraField,
|
|
796
|
+
rawLocalExtraField
|
|
809
797
|
}
|
|
810
798
|
};
|
|
811
799
|
}
|
|
812
800
|
|
|
801
|
+
function serializeExtraField(extraField) {
|
|
802
|
+
if (!extraField) {
|
|
803
|
+
return EMPTY_UINT8_ARRAY;
|
|
804
|
+
}
|
|
805
|
+
let extraFieldSize = 0;
|
|
806
|
+
let offset = 0;
|
|
807
|
+
extraField.forEach(data => extraFieldSize += 4 + getLength(data));
|
|
808
|
+
const rawExtraField = new Uint8Array(extraFieldSize);
|
|
809
|
+
const rawExtraFieldView = getDataView(rawExtraField);
|
|
810
|
+
extraField.forEach((data, type) => {
|
|
811
|
+
if (type > MAX_16_BITS) {
|
|
812
|
+
throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
|
|
813
|
+
}
|
|
814
|
+
if (getLength(data) > MAX_16_BITS) {
|
|
815
|
+
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
816
|
+
}
|
|
817
|
+
setUint16(rawExtraFieldView, offset, type);
|
|
818
|
+
setUint16(rawExtraFieldView, offset + 2, getLength(data));
|
|
819
|
+
arraySet(rawExtraField, data, offset + 4);
|
|
820
|
+
offset += 4 + getLength(data);
|
|
821
|
+
});
|
|
822
|
+
return rawExtraField;
|
|
823
|
+
}
|
|
824
|
+
|
|
813
825
|
async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
|
|
814
826
|
const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
|
|
815
827
|
let { dataDescriptor, zip64, level, compressionMethod } = metadata;
|
|
@@ -1134,7 +1146,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
|
|
|
1134
1146
|
msdosAttributes
|
|
1135
1147
|
};
|
|
1136
1148
|
let {
|
|
1137
|
-
|
|
1149
|
+
crc32,
|
|
1138
1150
|
uncompressedSize
|
|
1139
1151
|
} = options;
|
|
1140
1152
|
let compressedSize = 0;
|
|
@@ -1154,7 +1166,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
|
|
|
1154
1166
|
encryptionStrength,
|
|
1155
1167
|
zipCrypto: encrypted && zipCrypto,
|
|
1156
1168
|
passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & MAX_8_BITS,
|
|
1157
|
-
|
|
1169
|
+
computeCrc32: !passThrough,
|
|
1158
1170
|
compressed: compressed && !passThrough,
|
|
1159
1171
|
encrypted: encrypted && !passThrough,
|
|
1160
1172
|
useWebWorkers,
|
|
@@ -1173,7 +1185,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
|
|
|
1173
1185
|
writer.size += compressedSize;
|
|
1174
1186
|
if (!passThrough) {
|
|
1175
1187
|
uncompressedSize = result.inputSize;
|
|
1176
|
-
|
|
1188
|
+
if (!encrypted || zipCrypto) {
|
|
1189
|
+
crc32 = result.crc32;
|
|
1190
|
+
}
|
|
1177
1191
|
}
|
|
1178
1192
|
if ((!zip64CompressedSize && compressedSize >= MAX_32_BITS) ||
|
|
1179
1193
|
(!zip64UncompressedSize && uncompressedSize >= MAX_32_BITS)) {
|
|
@@ -1188,7 +1202,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
|
|
|
1188
1202
|
|
|
1189
1203
|
}
|
|
1190
1204
|
setEntryInfo({
|
|
1191
|
-
|
|
1205
|
+
crc32,
|
|
1192
1206
|
compressedSize,
|
|
1193
1207
|
uncompressedSize,
|
|
1194
1208
|
headerInfo,
|
|
@@ -1211,7 +1225,8 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
|
|
|
1211
1225
|
version,
|
|
1212
1226
|
headerArray,
|
|
1213
1227
|
headerView,
|
|
1214
|
-
signature,
|
|
1228
|
+
signature: crc32,
|
|
1229
|
+
crc32: encrypted && !zipCrypto && !passThrough ? UNDEFINED_VALUE : crc32,
|
|
1215
1230
|
extraFieldExtendedTimestampFlag,
|
|
1216
1231
|
zip64UncompressedSize,
|
|
1217
1232
|
zip64CompressedSize
|
|
@@ -1232,6 +1247,7 @@ function getHeaderInfo(options) {
|
|
|
1232
1247
|
dataDescriptor,
|
|
1233
1248
|
directory,
|
|
1234
1249
|
rawExtraField,
|
|
1250
|
+
rawLocalExtraField,
|
|
1235
1251
|
encryptionStrength,
|
|
1236
1252
|
extendedTimestamp,
|
|
1237
1253
|
ntfsTimestamp,
|
|
@@ -1239,7 +1255,8 @@ function getHeaderInfo(options) {
|
|
|
1239
1255
|
encrypted,
|
|
1240
1256
|
zip64UncompressedSize,
|
|
1241
1257
|
zip64CompressedSize,
|
|
1242
|
-
uncompressedSize
|
|
1258
|
+
uncompressedSize,
|
|
1259
|
+
crc32
|
|
1243
1260
|
} = options;
|
|
1244
1261
|
let { version, compressionMethod } = options;
|
|
1245
1262
|
const compressed = !directory && (compressionMethod === UNDEFINED_VALUE
|
|
@@ -1312,8 +1329,8 @@ function getHeaderInfo(options) {
|
|
|
1312
1329
|
extraFieldNTFS.uint16(EXTRAFIELD_TYPE_NTFS_TAG1);
|
|
1313
1330
|
extraFieldNTFS.uint16(24);
|
|
1314
1331
|
extraFieldNTFS.uint64(lastModTimeNTFS);
|
|
1315
|
-
extraFieldNTFS.uint64(getTimeNTFS(lastAccessDate)
|
|
1316
|
-
extraFieldNTFS.uint64(getTimeNTFS(creationDate)
|
|
1332
|
+
extraFieldNTFS.uint64(lastAccessDate ? getTimeNTFS(lastAccessDate) : lastModTimeNTFS);
|
|
1333
|
+
extraFieldNTFS.uint64(creationDate ? getTimeNTFS(creationDate) : lastModTimeNTFS);
|
|
1317
1334
|
rawExtraFieldNTFS = extraFieldNTFS.array;
|
|
1318
1335
|
} catch {
|
|
1319
1336
|
rawExtraFieldNTFS = EMPTY_UINT8_ARRAY;
|
|
@@ -1365,15 +1382,18 @@ function getHeaderInfo(options) {
|
|
|
1365
1382
|
}
|
|
1366
1383
|
if (encrypted && !zipCrypto) {
|
|
1367
1384
|
version = version > VERSION_AES ? version : VERSION_AES;
|
|
1385
|
+
if (passThrough && crc32 !== UNDEFINED_VALUE) {
|
|
1386
|
+
rawExtraFieldAES[EXTRAFIELD_OFFSET_AES_VENDOR_VERSION] = VENDOR_VERSION_AE_1;
|
|
1387
|
+
}
|
|
1368
1388
|
rawExtraFieldAES[9] = compressionMethod;
|
|
1369
1389
|
compressionMethod = COMPRESSION_METHOD_AES;
|
|
1370
1390
|
}
|
|
1371
1391
|
const localExtraFieldZip64Length = writeLocalExtraFieldZip64 ? getLength(rawLocalExtraFieldZip64) : 0;
|
|
1372
|
-
const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
|
|
1392
|
+
const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField, rawLocalExtraField);
|
|
1373
1393
|
if (extraFieldLength > MAX_16_BITS) {
|
|
1374
1394
|
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
1375
1395
|
}
|
|
1376
|
-
const dosLastModDate = new Date(Math.ceil(lastModDate.getTime() /
|
|
1396
|
+
const dosLastModDate = new Date(Math.ceil(Math.floor(lastModDate.getTime() / 1000) / 2) * 2000);
|
|
1377
1397
|
const {
|
|
1378
1398
|
headerArray,
|
|
1379
1399
|
headerView,
|
|
@@ -1403,6 +1423,7 @@ function getHeaderInfo(options) {
|
|
|
1403
1423
|
localHeader.bytes(rawExtraFieldNTFS);
|
|
1404
1424
|
localHeader.bytes(rawExtraFieldUnix);
|
|
1405
1425
|
localHeader.bytes(rawExtraField);
|
|
1426
|
+
localHeader.bytes(rawLocalExtraField);
|
|
1406
1427
|
if (dataDescriptor) {
|
|
1407
1428
|
if (!zip64CompressedSize) {
|
|
1408
1429
|
setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
|
|
@@ -1521,7 +1542,7 @@ function getDataDescriptorInfo({
|
|
|
1521
1542
|
}
|
|
1522
1543
|
|
|
1523
1544
|
function setEntryInfo({
|
|
1524
|
-
|
|
1545
|
+
crc32,
|
|
1525
1546
|
compressedSize,
|
|
1526
1547
|
uncompressedSize,
|
|
1527
1548
|
headerInfo,
|
|
@@ -1529,6 +1550,7 @@ function setEntryInfo({
|
|
|
1529
1550
|
}, {
|
|
1530
1551
|
zip64,
|
|
1531
1552
|
zipCrypto,
|
|
1553
|
+
passThrough,
|
|
1532
1554
|
dataDescriptor
|
|
1533
1555
|
}) {
|
|
1534
1556
|
const {
|
|
@@ -1539,10 +1561,10 @@ function setEntryInfo({
|
|
|
1539
1561
|
dataDescriptorView,
|
|
1540
1562
|
dataDescriptorOffset
|
|
1541
1563
|
} = dataDescriptorInfo;
|
|
1542
|
-
if ((!encrypted || zipCrypto) &&
|
|
1543
|
-
setUint32(headerView, HEADER_OFFSET_SIGNATURE,
|
|
1564
|
+
if ((!encrypted || zipCrypto || passThrough) && crc32 !== UNDEFINED_VALUE) {
|
|
1565
|
+
setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
|
|
1544
1566
|
if (dataDescriptor) {
|
|
1545
|
-
setUint32(dataDescriptorView, dataDescriptorOffset,
|
|
1567
|
+
setUint32(dataDescriptorView, dataDescriptorOffset, crc32);
|
|
1546
1568
|
}
|
|
1547
1569
|
}
|
|
1548
1570
|
if (zip64) {
|
|
@@ -1565,15 +1587,15 @@ function updateLocalHeader({
|
|
|
1565
1587
|
encrypted,
|
|
1566
1588
|
zip64,
|
|
1567
1589
|
localExtraFieldZip64Length,
|
|
1568
|
-
|
|
1590
|
+
crc32,
|
|
1569
1591
|
compressedSize,
|
|
1570
1592
|
uncompressedSize,
|
|
1571
1593
|
zip64UncompressedSize,
|
|
1572
1594
|
zip64CompressedSize
|
|
1573
|
-
}, localHeaderView, { dataDescriptor }) {
|
|
1595
|
+
}, localHeaderView, { dataDescriptor, passThrough }) {
|
|
1574
1596
|
if (!dataDescriptor) {
|
|
1575
|
-
if (!encrypted) {
|
|
1576
|
-
setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET,
|
|
1597
|
+
if (!encrypted || (passThrough && crc32 !== UNDEFINED_VALUE)) {
|
|
1598
|
+
setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, crc32);
|
|
1577
1599
|
}
|
|
1578
1600
|
if (!zip64CompressedSize) {
|
|
1579
1601
|
setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, compressedSize);
|
|
@@ -1882,7 +1904,8 @@ async function flushBufferedData(readable, writer, signal, onChunkWritten) {
|
|
|
1882
1904
|
|
|
1883
1905
|
function getTimeNTFS(date) {
|
|
1884
1906
|
if (date) {
|
|
1885
|
-
|
|
1907
|
+
const timeNTFS = ((BigInt(date.getTime()) + BigInt(11644473600000)) * BigInt(10000));
|
|
1908
|
+
return timeNTFS < MIN_NTFS_TIME ? MIN_NTFS_TIME : timeNTFS > MAX_NTFS_TIME ? MAX_NTFS_TIME : timeNTFS;
|
|
1886
1909
|
}
|
|
1887
1910
|
}
|
|
1888
1911
|
|
package/lib/zip-core-external.js
CHANGED
package/lib/zip-core-reader.js
CHANGED
package/lib/zip-fs-external.js
CHANGED
package/lib/zip-mime-types.js
CHANGED
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "A JavaScript library to zip and unzip files in the browser, Deno and Node.js",
|
|
4
4
|
"author": "Gildas Lormeau",
|
|
5
5
|
"license": "BSD-3-Clause",
|
|
6
|
-
"version": "2.8.
|
|
6
|
+
"version": "2.8.45",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"keywords": [
|
|
9
9
|
"zip",
|
|
@@ -34,6 +34,10 @@
|
|
|
34
34
|
"bun": ">=0.7.0"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
|
+
"lint": "npx eslint . && deno lint",
|
|
38
|
+
"test": "npm run test-node && npm run test-deno && npm run test-bun && npm run test-node-dist && npm run test-deno-dist && npm run test-bun-dist && npm run test-web-streams-polyfill && npm run test-types",
|
|
39
|
+
"test-browsers": "npm run test-chrome && npm run test-firefox && npm run test-webkit",
|
|
40
|
+
"test-all": "npm run lint && npm run test && npm run test-browsers",
|
|
37
41
|
"build": "npx rollup -c",
|
|
38
42
|
"build-dev": "npx rollup -c rollup.config.dev.js",
|
|
39
43
|
"build-doc-api": "npx typedoc",
|
|
@@ -46,8 +50,9 @@
|
|
|
46
50
|
"test-node-dist": "./tests/dist-runner.sh node",
|
|
47
51
|
"test-bun-dist": "./tests/dist-runner.sh bun",
|
|
48
52
|
"test-types": "tsc -p ./tests/types/tsconfig.json",
|
|
49
|
-
"test-firefox": "
|
|
50
|
-
"test-chrome": "
|
|
53
|
+
"test-firefox": "node ./tests/browser-runner.js firefox",
|
|
54
|
+
"test-chrome": "node ./tests/browser-runner.js chrome",
|
|
55
|
+
"test-webkit": "node ./tests/browser-runner.js webkit"
|
|
51
56
|
},
|
|
52
57
|
"main": "./index.cjs",
|
|
53
58
|
"module": "./index.js",
|
|
@@ -236,6 +241,7 @@
|
|
|
236
241
|
"@rollup/plugin-terser": "^1.0.0",
|
|
237
242
|
"eslint": "^10.8.1",
|
|
238
243
|
"http-server": "^14.1.1",
|
|
244
|
+
"playwright": "^1.62.1",
|
|
239
245
|
"rollup": "^4.62.4",
|
|
240
246
|
"typedoc": "^0.28.20",
|
|
241
247
|
"typedoc-plugin-markdown": "^4.12.0",
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
const WORKER_MESSAGE_PROPERTY_NAMES = ["baseURI", "cause", "checkPasswordOnly", "chunkSize", "code", "codecType", "codecURI", "compressed", "compressionMethod", "config", "deflate64", "done", "encrypted", "encryptionStrength", "error", "format", "inputSize", "level", "message", "messageId", "name", "options", "outputSize", "password", "passwordVerification", "rawBitFlag", "rawPassword", "readable", "result", "
|
|
1
|
+
const WORKER_MESSAGE_PROPERTY_NAMES = ["baseURI", "cause", "checkAuthenticationCode", "checkCrc32", "checkPasswordOnly", "chunkSize", "code", "codecType", "codecURI", "compressed", "compressionMethod", "computeCrc32", "config", "crc32", "deflate64", "done", "encrypted", "encryptionStrength", "error", "format", "inputSize", "level", "message", "messageId", "name", "options", "outputSize", "password", "passwordVerification", "rawBitFlag", "rawPassword", "readable", "result", "stack", "transferStreams", "type", "useCompressionStream", "useWebWorkers", "value", "wasmURI", "workerStartupTimeout", "writable", "zipCrypto"];
|
|
2
2
|
|
|
3
3
|
export { WORKER_MESSAGE_PROPERTY_NAMES };
|