@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/dist/zip-fs-core.js
CHANGED
|
@@ -70,6 +70,8 @@
|
|
|
70
70
|
const EXTRAFIELD_TYPE_USDZ = 0x1986;
|
|
71
71
|
const EXTRAFIELD_TYPE_INFOZIP = 0x7875;
|
|
72
72
|
const EXTRAFIELD_TYPE_UNIX = 0x7855;
|
|
73
|
+
const EXTRAFIELD_TYPE_UNIX_TYPE1 = 0x5855;
|
|
74
|
+
const EXTRAFIELD_TYPE_PKWARE_UNIX = 0x000d;
|
|
73
75
|
|
|
74
76
|
const BITFLAG_ENCRYPTED = 0b1;
|
|
75
77
|
const BITFLAG_LEVEL = 0b0110;
|
|
@@ -2315,6 +2317,7 @@
|
|
|
2315
2317
|
|
|
2316
2318
|
const ERR_INVALID_PASSWORD = "Invalid password";
|
|
2317
2319
|
const ERR_INVALID_SIGNATURE = "Invalid signature";
|
|
2320
|
+
const ERR_INVALID_AUTHENTICATION_CODE = ERR_INVALID_SIGNATURE;
|
|
2318
2321
|
const ERR_ABORT_CHECK_PASSWORD = "zipjs-abort-check-password";
|
|
2319
2322
|
const ERR_UNSUPPORTED_CRYPTO_API = "Crypto API not supported";
|
|
2320
2323
|
|
|
@@ -2365,7 +2368,7 @@
|
|
|
2365
2368
|
const DERIVED_BITS_USAGE = ["deriveBits"];
|
|
2366
2369
|
const SALT_LENGTH = [8, 12, 16];
|
|
2367
2370
|
const KEY_LENGTH = [16, 24, 32];
|
|
2368
|
-
const
|
|
2371
|
+
const AUTHENTICATION_CODE_LENGTH = 10;
|
|
2369
2372
|
const COUNTER_DEFAULT_VALUE = [0, 0, 0, 0];
|
|
2370
2373
|
// deno-lint-ignore valid-typeof
|
|
2371
2374
|
const CRYPTO_API_SUPPORTED = typeof crypto != UNDEFINED_TYPE;
|
|
@@ -2381,7 +2384,7 @@
|
|
|
2381
2384
|
|
|
2382
2385
|
class AESDecryptionStream extends TransformStream {
|
|
2383
2386
|
|
|
2384
|
-
constructor({ password, rawPassword, encryptionStrength, checkPasswordOnly }) {
|
|
2387
|
+
constructor({ password, rawPassword, encryptionStrength, checkPasswordOnly, checkAuthenticationCode = true }) {
|
|
2385
2388
|
super({
|
|
2386
2389
|
start() {
|
|
2387
2390
|
initAesCrypto(this, password, rawPassword, encryptionStrength);
|
|
@@ -2405,8 +2408,8 @@
|
|
|
2405
2408
|
} else {
|
|
2406
2409
|
await ready;
|
|
2407
2410
|
}
|
|
2408
|
-
const output = new Uint8Array(chunk.length -
|
|
2409
|
-
controller.enqueue(append(aesCrypto, chunk, output, 0,
|
|
2411
|
+
const output = new Uint8Array(chunk.length - AUTHENTICATION_CODE_LENGTH - ((chunk.length - AUTHENTICATION_CODE_LENGTH) % BLOCK_LENGTH));
|
|
2412
|
+
controller.enqueue(append(aesCrypto, chunk, output, 0, AUTHENTICATION_CODE_LENGTH, true));
|
|
2410
2413
|
},
|
|
2411
2414
|
async flush(controller) {
|
|
2412
2415
|
const {
|
|
@@ -2417,8 +2420,8 @@
|
|
|
2417
2420
|
} = this;
|
|
2418
2421
|
if (hmac && ctr) {
|
|
2419
2422
|
await ready;
|
|
2420
|
-
const chunkToDecrypt = subarray(pending, 0, pending.length -
|
|
2421
|
-
const
|
|
2423
|
+
const chunkToDecrypt = subarray(pending, 0, pending.length - AUTHENTICATION_CODE_LENGTH);
|
|
2424
|
+
const originalAuthenticationCode = subarray(pending, pending.length - AUTHENTICATION_CODE_LENGTH);
|
|
2422
2425
|
let decryptedChunkArray = EMPTY_UINT8_ARRAY;
|
|
2423
2426
|
if (chunkToDecrypt.length) {
|
|
2424
2427
|
const encryptedChunk = toBits(codecBytes, chunkToDecrypt);
|
|
@@ -2426,13 +2429,13 @@
|
|
|
2426
2429
|
const decryptedChunk = ctr.update(encryptedChunk);
|
|
2427
2430
|
decryptedChunkArray = fromBits(codecBytes, decryptedChunk);
|
|
2428
2431
|
}
|
|
2429
|
-
const
|
|
2430
|
-
let
|
|
2431
|
-
for (let
|
|
2432
|
-
|
|
2432
|
+
const authenticationCode = subarray(fromBits(codecBytes, hmac.digest()), 0, AUTHENTICATION_CODE_LENGTH);
|
|
2433
|
+
let invalidAuthenticationCode = pending.length < AUTHENTICATION_CODE_LENGTH ? 1 : 0;
|
|
2434
|
+
for (let indexByte = 0; indexByte < AUTHENTICATION_CODE_LENGTH; indexByte++) {
|
|
2435
|
+
invalidAuthenticationCode |= authenticationCode[indexByte] ^ originalAuthenticationCode[indexByte];
|
|
2433
2436
|
}
|
|
2434
|
-
if (
|
|
2435
|
-
throw new Error(
|
|
2437
|
+
if (invalidAuthenticationCode && checkAuthenticationCode) {
|
|
2438
|
+
throw new Error(ERR_INVALID_AUTHENTICATION_CODE);
|
|
2436
2439
|
}
|
|
2437
2440
|
controller.enqueue(decryptedChunkArray);
|
|
2438
2441
|
}
|
|
@@ -2444,8 +2447,6 @@
|
|
|
2444
2447
|
class AESEncryptionStream extends TransformStream {
|
|
2445
2448
|
|
|
2446
2449
|
constructor({ password, rawPassword, encryptionStrength }) {
|
|
2447
|
-
// deno-lint-ignore prefer-const
|
|
2448
|
-
let stream;
|
|
2449
2450
|
super({
|
|
2450
2451
|
start() {
|
|
2451
2452
|
initAesCrypto(this, password, rawPassword, encryptionStrength);
|
|
@@ -2484,12 +2485,11 @@
|
|
|
2484
2485
|
hmac.update(encryptedChunk);
|
|
2485
2486
|
encryptedChunkArray = fromBits(codecBytes, encryptedChunk);
|
|
2486
2487
|
}
|
|
2487
|
-
|
|
2488
|
-
controller.enqueue(concat(encryptedChunkArray,
|
|
2488
|
+
const authenticationCode = fromBits(codecBytes, hmac.digest()).slice(0, AUTHENTICATION_CODE_LENGTH);
|
|
2489
|
+
controller.enqueue(concat(encryptedChunkArray, authenticationCode));
|
|
2489
2490
|
}
|
|
2490
2491
|
}
|
|
2491
2492
|
});
|
|
2492
|
-
stream = this;
|
|
2493
2493
|
}
|
|
2494
2494
|
}
|
|
2495
2495
|
|
|
@@ -2502,7 +2502,7 @@
|
|
|
2502
2502
|
});
|
|
2503
2503
|
}
|
|
2504
2504
|
|
|
2505
|
-
function append(aesCrypto, input, output, paddingStart, paddingEnd,
|
|
2505
|
+
function append(aesCrypto, input, output, paddingStart, paddingEnd, verifyAuthenticationCode) {
|
|
2506
2506
|
const {
|
|
2507
2507
|
ctr,
|
|
2508
2508
|
hmac,
|
|
@@ -2516,11 +2516,11 @@
|
|
|
2516
2516
|
let offset;
|
|
2517
2517
|
for (offset = 0; offset <= inputLength - BLOCK_LENGTH; offset += BLOCK_LENGTH) {
|
|
2518
2518
|
const inputChunk = toBits(codecBytes, subarray(input, offset, offset + BLOCK_LENGTH));
|
|
2519
|
-
if (
|
|
2519
|
+
if (verifyAuthenticationCode) {
|
|
2520
2520
|
hmac.update(inputChunk);
|
|
2521
2521
|
}
|
|
2522
2522
|
const outputChunk = ctr.update(inputChunk);
|
|
2523
|
-
if (!
|
|
2523
|
+
if (!verifyAuthenticationCode) {
|
|
2524
2524
|
hmac.update(outputChunk);
|
|
2525
2525
|
}
|
|
2526
2526
|
output.set(fromBits(codecBytes, outputChunk), offset + paddingStart);
|
|
@@ -2803,6 +2803,7 @@
|
|
|
2803
2803
|
|
|
2804
2804
|
const ERR_INVALID_UNCOMPRESSED_SIZE = "Invalid uncompressed size";
|
|
2805
2805
|
const ERR_INVALID_COMPRESSED_DATA = "Invalid compressed data";
|
|
2806
|
+
const ERR_INVALID_CRC32 = ERR_INVALID_SIGNATURE;
|
|
2806
2807
|
const ERR_UNSUPPORTED_COMPRESSION$2 = "Compression method not supported";
|
|
2807
2808
|
const FORMAT_DEFLATE_RAW = "deflate-raw";
|
|
2808
2809
|
const FORMAT_DEFLATE64_RAW = "deflate64-raw";
|
|
@@ -2816,14 +2817,14 @@
|
|
|
2816
2817
|
|
|
2817
2818
|
constructor(options, { chunkSize, CompressionStreamZlib, CompressionStream }) {
|
|
2818
2819
|
super({});
|
|
2819
|
-
const { compressed, encrypted, useCompressionStream, zipCrypto,
|
|
2820
|
+
const { compressed, encrypted, useCompressionStream, zipCrypto, computeCrc32, level, deflate64, format, compressionMethod } = options;
|
|
2820
2821
|
const stream = this;
|
|
2821
2822
|
let crc32Stream, encryptionStream, gzipCrc32Stream;
|
|
2822
2823
|
let readable = super.readable;
|
|
2823
2824
|
const codecStreams = format && getCodecStreams(format);
|
|
2824
|
-
const useGzipCrc32 =
|
|
2825
|
+
const useGzipCrc32 = computeCrc32 && compressed && !deflate64 && !codecStreams && (!encrypted || zipCrypto) &&
|
|
2825
2826
|
Boolean(useCompressionStream && CompressionStream);
|
|
2826
|
-
if ((!encrypted || zipCrypto) &&
|
|
2827
|
+
if ((!encrypted || zipCrypto) && computeCrc32 && !useGzipCrc32) {
|
|
2827
2828
|
crc32Stream = new Crc32Stream();
|
|
2828
2829
|
readable = pipeThrough(readable, crc32Stream);
|
|
2829
2830
|
}
|
|
@@ -2858,14 +2859,9 @@
|
|
|
2858
2859
|
}
|
|
2859
2860
|
}
|
|
2860
2861
|
setReadable(stream, readable, () => {
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
signature = encryptionStream.signature;
|
|
2864
|
-
}
|
|
2865
|
-
if ((!encrypted || zipCrypto) && signed) {
|
|
2866
|
-
signature = useGzipCrc32 ? gzipCrc32Stream.signature : new DataView(crc32Stream.value.buffer).getUint32(0);
|
|
2862
|
+
if ((!encrypted || zipCrypto) && computeCrc32) {
|
|
2863
|
+
stream.crc32 = useGzipCrc32 ? gzipCrc32Stream.crc32 : new DataView(crc32Stream.value.buffer).getUint32(0);
|
|
2867
2864
|
}
|
|
2868
|
-
stream.signature = signature;
|
|
2869
2865
|
});
|
|
2870
2866
|
}
|
|
2871
2867
|
}
|
|
@@ -2903,7 +2899,7 @@
|
|
|
2903
2899
|
},
|
|
2904
2900
|
flush() {
|
|
2905
2901
|
const dataView = getDataView(trailerCandidate);
|
|
2906
|
-
stream.
|
|
2902
|
+
stream.crc32 = dataView.getUint32(0, true);
|
|
2907
2903
|
stream.uncompressedSize = dataView.getUint32(4, true);
|
|
2908
2904
|
}
|
|
2909
2905
|
});
|
|
@@ -2985,7 +2981,7 @@
|
|
|
2985
2981
|
|
|
2986
2982
|
constructor(options, { chunkSize, DecompressionStreamZlib, DecompressionStream }) {
|
|
2987
2983
|
super({});
|
|
2988
|
-
const { zipCrypto, encrypted,
|
|
2984
|
+
const { zipCrypto, encrypted, checkCrc32, crc32, compressed, useCompressionStream, deflate64, format, compressionMethod, rawBitFlag, outputSize } = options;
|
|
2989
2985
|
let crc32Stream, decryptionStream;
|
|
2990
2986
|
let readable = super.readable;
|
|
2991
2987
|
if (encrypted) {
|
|
@@ -3018,15 +3014,15 @@
|
|
|
3018
3014
|
}
|
|
3019
3015
|
readable = mapInflateStreamError(readable);
|
|
3020
3016
|
}
|
|
3021
|
-
if (
|
|
3017
|
+
if (checkCrc32) {
|
|
3022
3018
|
crc32Stream = new Crc32Stream();
|
|
3023
3019
|
readable = pipeThrough(readable, crc32Stream);
|
|
3024
3020
|
}
|
|
3025
3021
|
setReadable(this, readable, () => {
|
|
3026
|
-
if (
|
|
3027
|
-
const
|
|
3028
|
-
if (
|
|
3029
|
-
throw new Error(
|
|
3022
|
+
if (checkCrc32) {
|
|
3023
|
+
const computedCrc32View = new DataView(crc32Stream.value.buffer);
|
|
3024
|
+
if (crc32 != computedCrc32View.getUint32(0, false)) {
|
|
3025
|
+
throw new Error(ERR_INVALID_CRC32);
|
|
3030
3026
|
}
|
|
3031
3027
|
}
|
|
3032
3028
|
});
|
|
@@ -3250,9 +3246,9 @@
|
|
|
3250
3246
|
}
|
|
3251
3247
|
},
|
|
3252
3248
|
flush() {
|
|
3253
|
-
const {
|
|
3249
|
+
const { crc32 } = stream;
|
|
3254
3250
|
Object.assign(codec, {
|
|
3255
|
-
|
|
3251
|
+
crc32,
|
|
3256
3252
|
inputSize
|
|
3257
3253
|
});
|
|
3258
3254
|
}
|
|
@@ -3547,12 +3543,12 @@
|
|
|
3547
3543
|
.pipeThrough(new ChunkStream(getChunkSize(config)))
|
|
3548
3544
|
.pipeTo(writable, { preventClose: true, preventAbort: true });
|
|
3549
3545
|
const {
|
|
3550
|
-
|
|
3546
|
+
crc32,
|
|
3551
3547
|
inputSize,
|
|
3552
3548
|
outputSize
|
|
3553
3549
|
} = codecStream;
|
|
3554
3550
|
return {
|
|
3555
|
-
|
|
3551
|
+
crc32,
|
|
3556
3552
|
inputSize,
|
|
3557
3553
|
outputSize
|
|
3558
3554
|
};
|
|
@@ -3913,7 +3909,7 @@
|
|
|
3913
3909
|
|
|
3914
3910
|
async function runWorker(stream, workerOptions) {
|
|
3915
3911
|
const { options, config } = workerOptions;
|
|
3916
|
-
const { transferStreams, useWebWorkers, useCompressionStream, compressed,
|
|
3912
|
+
const { transferStreams, useWebWorkers, useCompressionStream, compressed, checkCrc32, computeCrc32, encrypted, format, codecURI } = options;
|
|
3917
3913
|
const { workerURI, maxWorkers } = config;
|
|
3918
3914
|
if (format) {
|
|
3919
3915
|
if (codecURI) {
|
|
@@ -3922,7 +3918,7 @@
|
|
|
3922
3918
|
await ensureCodecStreams(format, options.codecURI);
|
|
3923
3919
|
}
|
|
3924
3920
|
workerOptions.transferStreams = transferStreams || (transferStreams === UNDEFINED_VALUE && config.transferStreams);
|
|
3925
|
-
const streamCopy = !compressed && !
|
|
3921
|
+
const streamCopy = !compressed && !checkCrc32 && !computeCrc32 && !encrypted;
|
|
3926
3922
|
const workerSupported = format === UNDEFINED_VALUE || Boolean(options.codecURI);
|
|
3927
3923
|
workerOptions.useWebWorkers = !streamCopy && workerSupported && (useWebWorkers || (useWebWorkers === UNDEFINED_VALUE && config.useWebWorkers));
|
|
3928
3924
|
workerOptions.workerURI = workerOptions.useWebWorkers && workerURI ? workerURI : UNDEFINED_VALUE;
|
|
@@ -4165,9 +4161,12 @@
|
|
|
4165
4161
|
const PROPERTY_NAME_EXECUTABLE = "executable";
|
|
4166
4162
|
const PROPERTY_NAME_COMPRESSION_METHOD = "compressionMethod";
|
|
4167
4163
|
const PROPERTY_NAME_SIGNATURE = "signature";
|
|
4164
|
+
const PROPERTY_NAME_CRC32 = "crc32";
|
|
4168
4165
|
const PROPERTY_NAME_EXTRA_FIELD = "extraField";
|
|
4169
4166
|
const PROPERTY_NAME_EXTRA_FIELD_INFOZIP = "extraFieldInfoZip";
|
|
4170
4167
|
const PROPERTY_NAME_EXTRA_FIELD_UNIX = "extraFieldUnix";
|
|
4168
|
+
const PROPERTY_NAME_EXTRA_FIELD_UNIX_TYPE1 = "extraFieldUnixType1";
|
|
4169
|
+
const PROPERTY_NAME_EXTRA_FIELD_PKWARE_UNIX = "extraFieldPkwareUnix";
|
|
4171
4170
|
const PROPERTY_NAME_UID = "uid";
|
|
4172
4171
|
const PROPERTY_NAME_GID = "gid";
|
|
4173
4172
|
const PROPERTY_NAME_UNIX_MODE = "unixMode";
|
|
@@ -4184,6 +4183,7 @@
|
|
|
4184
4183
|
const PROPERTY_NAME_EXTRA_FIELD_AES = "extraFieldAES";
|
|
4185
4184
|
const PROPERTY_NAME_EXTRA_FIELD_NTFS = "extraFieldNTFS";
|
|
4186
4185
|
const PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP = "extraFieldExtendedTimestamp";
|
|
4186
|
+
const PROPERTY_NAME_EXTRA_FIELD_USDZ = "extraFieldUSDZ";
|
|
4187
4187
|
|
|
4188
4188
|
const PROPERTY_NAMES = [
|
|
4189
4189
|
PROPERTY_NAME_FILENAME,
|
|
@@ -4195,6 +4195,7 @@
|
|
|
4195
4195
|
PROPERTY_NAME_COMMENT,
|
|
4196
4196
|
PROPERTY_NAME_RAW_COMMENT,
|
|
4197
4197
|
PROPERTY_NAME_LAST_ACCESS_DATE,
|
|
4198
|
+
PROPERTY_NAME_RAW_LAST_ACCESS_DATE,
|
|
4198
4199
|
PROPERTY_NAME_CREATION_DATE,
|
|
4199
4200
|
PROPERTY_NAME_RAW_CREATION_DATE,
|
|
4200
4201
|
PROPERTY_NAME_OFFSET,
|
|
@@ -4213,9 +4214,12 @@
|
|
|
4213
4214
|
PROPERTY_NAME_EXECUTABLE,
|
|
4214
4215
|
PROPERTY_NAME_COMPRESSION_METHOD,
|
|
4215
4216
|
PROPERTY_NAME_SIGNATURE,
|
|
4217
|
+
PROPERTY_NAME_CRC32,
|
|
4216
4218
|
PROPERTY_NAME_EXTRA_FIELD,
|
|
4217
4219
|
PROPERTY_NAME_EXTRA_FIELD_UNIX,
|
|
4218
4220
|
PROPERTY_NAME_EXTRA_FIELD_INFOZIP,
|
|
4221
|
+
PROPERTY_NAME_EXTRA_FIELD_UNIX_TYPE1,
|
|
4222
|
+
PROPERTY_NAME_EXTRA_FIELD_PKWARE_UNIX,
|
|
4219
4223
|
PROPERTY_NAME_UID,
|
|
4220
4224
|
PROPERTY_NAME_GID,
|
|
4221
4225
|
PROPERTY_NAME_UNIX_MODE,
|
|
@@ -4231,7 +4235,8 @@
|
|
|
4231
4235
|
PROPERTY_NAME_EXTRA_FIELD_UNICODE_COMMENT,
|
|
4232
4236
|
PROPERTY_NAME_EXTRA_FIELD_AES,
|
|
4233
4237
|
PROPERTY_NAME_EXTRA_FIELD_NTFS,
|
|
4234
|
-
PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP
|
|
4238
|
+
PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP,
|
|
4239
|
+
PROPERTY_NAME_EXTRA_FIELD_USDZ
|
|
4235
4240
|
];
|
|
4236
4241
|
|
|
4237
4242
|
class Entry {
|
|
@@ -4284,6 +4289,8 @@
|
|
|
4284
4289
|
const OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
|
|
4285
4290
|
const OPTION_CHECK_AMBIGUITY = "checkAmbiguity";
|
|
4286
4291
|
const OPTION_CHECK_SIGNATURE = "checkSignature";
|
|
4292
|
+
const OPTION_CHECK_CRC32 = "checkCrc32";
|
|
4293
|
+
const OPTION_CHECK_AUTHENTICATION_CODE = "checkAuthenticationCode";
|
|
4287
4294
|
const OPTION_USE_WEB_WORKERS = "useWebWorkers";
|
|
4288
4295
|
const OPTION_USE_COMPRESSION_STREAM = "useCompressionStream";
|
|
4289
4296
|
const OPTION_TRANSFER_STREAMS = "transferStreams";
|
|
@@ -4303,6 +4310,7 @@
|
|
|
4303
4310
|
const OPTION_OFFSET = "offset";
|
|
4304
4311
|
const OPTION_USDZ = "usdz";
|
|
4305
4312
|
const OPTION_UNIX_EXTRA_FIELD_TYPE = "unixExtraFieldType";
|
|
4313
|
+
const OPTION_LOCAL_EXTRA_FIELD = "localExtraField";
|
|
4306
4314
|
const OPTION_STRICTNESS = "strictness";
|
|
4307
4315
|
const OPTION_MAX_APPENDED_DATA_SIZE = "maxAppendedDataSize";
|
|
4308
4316
|
const STRICTNESS_STRICT = "strict";
|
|
@@ -4355,6 +4363,7 @@
|
|
|
4355
4363
|
const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
|
|
4356
4364
|
const CHARSET_CP437 = "cp437";
|
|
4357
4365
|
const BITFLAG_AMBIGUITY_MASK = BITFLAG_ENCRYPTED | BITFLAG_DATA_DESCRIPTOR | BITFLAG_LANG_ENCODING_FLAG;
|
|
4366
|
+
const VENDOR_VERSION_AE_1$1 = 1;
|
|
4358
4367
|
const ZIP64_PROPERTIES = [
|
|
4359
4368
|
[PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
|
|
4360
4369
|
[PROPERTY_NAME_COMPRESSED_SIZE, MAX_32_BITS],
|
|
@@ -4707,7 +4716,7 @@
|
|
|
4707
4716
|
config,
|
|
4708
4717
|
bitFlag,
|
|
4709
4718
|
rawBitFlag,
|
|
4710
|
-
|
|
4719
|
+
crc32,
|
|
4711
4720
|
rawLastModDate,
|
|
4712
4721
|
uncompressedSize,
|
|
4713
4722
|
compressedSize
|
|
@@ -4794,6 +4803,11 @@
|
|
|
4794
4803
|
if (deflate64) {
|
|
4795
4804
|
useCompressionStream = false;
|
|
4796
4805
|
}
|
|
4806
|
+
const checkCrc32Option = getOptionValue$1(zipEntry, options, OPTION_CHECK_CRC32);
|
|
4807
|
+
const checkCrc32 = (checkCrc32Option === UNDEFINED_VALUE ?
|
|
4808
|
+
getOptionValue$1(zipEntry, options, OPTION_CHECK_SIGNATURE) :
|
|
4809
|
+
checkCrc32Option) && !passThrough &&
|
|
4810
|
+
(!encrypted || zipCrypto || (extraFieldAES && extraFieldAES.vendorVersion == VENDOR_VERSION_AE_1$1));
|
|
4797
4811
|
const workerOptions = {
|
|
4798
4812
|
options: {
|
|
4799
4813
|
codecType: CODEC_INFLATE,
|
|
@@ -4801,10 +4815,11 @@
|
|
|
4801
4815
|
rawPassword,
|
|
4802
4816
|
zipCrypto,
|
|
4803
4817
|
encryptionStrength: extraFieldAES && extraFieldAES.strength,
|
|
4804
|
-
|
|
4805
|
-
|
|
4818
|
+
checkCrc32,
|
|
4819
|
+
checkAuthenticationCode: getOptionValue$1(zipEntry, options, OPTION_CHECK_AUTHENTICATION_CODE),
|
|
4820
|
+
passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((crc32 >>> 24) & MAX_8_BITS)),
|
|
4806
4821
|
outputSize: passThrough ? compressedSize : uncompressedSize,
|
|
4807
|
-
|
|
4822
|
+
crc32,
|
|
4808
4823
|
compressed: compressionMethod != 0 && !passThrough,
|
|
4809
4824
|
encrypted,
|
|
4810
4825
|
useWebWorkers: getOptionValue$1(zipEntry, options, OPTION_USE_WEB_WORKERS),
|
|
@@ -4826,7 +4841,7 @@
|
|
|
4826
4841
|
fileEntry,
|
|
4827
4842
|
index,
|
|
4828
4843
|
offset: localHeaderOffset,
|
|
4829
|
-
|
|
4844
|
+
crc32,
|
|
4830
4845
|
compressedSize,
|
|
4831
4846
|
uncompressedSize,
|
|
4832
4847
|
dataOffset,
|
|
@@ -4917,6 +4932,7 @@
|
|
|
4917
4932
|
const compressionMethod = getUint16(dataView, offset + 4);
|
|
4918
4933
|
Object.assign(directory, {
|
|
4919
4934
|
signature: getUint32(dataView, offset + HEADER_OFFSET_SIGNATURE),
|
|
4935
|
+
crc32: getUint32(dataView, offset + HEADER_OFFSET_SIGNATURE),
|
|
4920
4936
|
compressedSize: getUint32(dataView, offset + HEADER_OFFSET_COMPRESSED_SIZE),
|
|
4921
4937
|
uncompressedSize: getUint32(dataView, offset + HEADER_OFFSET_UNCOMPRESSED_SIZE)
|
|
4922
4938
|
});
|
|
@@ -4942,6 +4958,16 @@
|
|
|
4942
4958
|
} else {
|
|
4943
4959
|
directory.compressionMethod = compressionMethod;
|
|
4944
4960
|
}
|
|
4961
|
+
const extraFieldPkwareUnix = extraField.get(EXTRAFIELD_TYPE_PKWARE_UNIX);
|
|
4962
|
+
if (extraFieldPkwareUnix) {
|
|
4963
|
+
readExtraFieldUnixDates(extraFieldPkwareUnix, directory);
|
|
4964
|
+
directory.extraFieldPkwareUnix = extraFieldPkwareUnix;
|
|
4965
|
+
}
|
|
4966
|
+
const extraFieldUnixType1 = extraField.get(EXTRAFIELD_TYPE_UNIX_TYPE1);
|
|
4967
|
+
if (extraFieldUnixType1) {
|
|
4968
|
+
readExtraFieldUnixDates(extraFieldUnixType1, directory);
|
|
4969
|
+
directory.extraFieldUnixType1 = extraFieldUnixType1;
|
|
4970
|
+
}
|
|
4945
4971
|
const extraFieldNTFS = extraField.get(EXTRAFIELD_TYPE_NTFS);
|
|
4946
4972
|
if (extraFieldNTFS) {
|
|
4947
4973
|
readExtraFieldNTFS(extraFieldNTFS, directory);
|
|
@@ -4991,15 +5017,15 @@
|
|
|
4991
5017
|
return;
|
|
4992
5018
|
}
|
|
4993
5019
|
const extraFieldView = getDataView(extraFieldUnicode.data);
|
|
4994
|
-
const
|
|
4995
|
-
|
|
4996
|
-
const
|
|
4997
|
-
|
|
4998
|
-
const
|
|
5020
|
+
const computedCrc32 = new Crc32();
|
|
5021
|
+
computedCrc32.append(fileEntry[rawPropertyName]);
|
|
5022
|
+
const computedCrc32View = getDataView(new Uint8Array(4));
|
|
5023
|
+
computedCrc32View.setUint32(0, computedCrc32.get(), true);
|
|
5024
|
+
const nameCrc32 = getUint32(extraFieldView, 1);
|
|
4999
5025
|
Object.assign(extraFieldUnicode, {
|
|
5000
5026
|
version: getUint8(extraFieldView, 0),
|
|
5001
5027
|
[propertyName]: decodeText(extraFieldUnicode.data.subarray(5)),
|
|
5002
|
-
valid: !fileEntry.bitFlag.languageEncodingFlag &&
|
|
5028
|
+
valid: !fileEntry.bitFlag.languageEncodingFlag && nameCrc32 == getUint32(computedCrc32View, 0)
|
|
5003
5029
|
});
|
|
5004
5030
|
if (extraFieldUnicode.valid) {
|
|
5005
5031
|
directory[propertyName] = extraFieldUnicode[propertyName];
|
|
@@ -5018,6 +5044,9 @@
|
|
|
5018
5044
|
compressionMethod: getUint16(extraFieldView, 5)
|
|
5019
5045
|
});
|
|
5020
5046
|
directory.compressionMethod = extraFieldAES.compressionMethod;
|
|
5047
|
+
if (extraFieldAES.vendorVersion != VENDOR_VERSION_AE_1$1) {
|
|
5048
|
+
directory.crc32 = UNDEFINED_VALUE;
|
|
5049
|
+
}
|
|
5021
5050
|
}
|
|
5022
5051
|
|
|
5023
5052
|
function readExtraFieldNTFS(extraFieldNTFS, directory) {
|
|
@@ -5036,29 +5065,41 @@
|
|
|
5036
5065
|
} catch {
|
|
5037
5066
|
// ignored
|
|
5038
5067
|
}
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
Object.assign(directory, extraFieldData);
|
|
5056
|
-
}
|
|
5057
|
-
} catch {
|
|
5058
|
-
// ignored
|
|
5068
|
+
if (tag1Data && tag1Data.length == 24) {
|
|
5069
|
+
const tag1View = getDataView(tag1Data);
|
|
5070
|
+
const rawLastModDate = tag1View.getBigUint64(0, true);
|
|
5071
|
+
const rawLastAccessDate = tag1View.getBigUint64(8, true);
|
|
5072
|
+
const rawCreationDate = tag1View.getBigUint64(16, true);
|
|
5073
|
+
Object.assign(extraFieldNTFS, {
|
|
5074
|
+
rawLastModDate,
|
|
5075
|
+
rawLastAccessDate,
|
|
5076
|
+
rawCreationDate
|
|
5077
|
+
});
|
|
5078
|
+
const lastModDate = getDateNTFS(rawLastModDate);
|
|
5079
|
+
const lastAccessDate = getDateNTFS(rawLastAccessDate);
|
|
5080
|
+
const creationDate = getDateNTFS(rawCreationDate);
|
|
5081
|
+
const extraFieldData = { lastModDate, lastAccessDate, creationDate };
|
|
5082
|
+
Object.assign(extraFieldNTFS, extraFieldData);
|
|
5083
|
+
Object.assign(directory, extraFieldData);
|
|
5059
5084
|
}
|
|
5060
5085
|
}
|
|
5061
5086
|
|
|
5087
|
+
function readExtraFieldUnixDates(extraField, directory) {
|
|
5088
|
+
if (extraField.data.length < 8) {
|
|
5089
|
+
return;
|
|
5090
|
+
}
|
|
5091
|
+
const extraFieldView = getDataView(extraField.data);
|
|
5092
|
+
const lastAccessDate = new Date(getUint32(extraFieldView, 0) * 1000);
|
|
5093
|
+
const lastModDate = new Date(getUint32(extraFieldView, 4) * 1000);
|
|
5094
|
+
const extraFieldData = { lastAccessDate, lastModDate };
|
|
5095
|
+
if (extraField.data.length >= 12) {
|
|
5096
|
+
extraFieldData.uid = getUint16(extraFieldView, 8);
|
|
5097
|
+
extraFieldData.gid = getUint16(extraFieldView, 10);
|
|
5098
|
+
}
|
|
5099
|
+
Object.assign(extraField, extraFieldData);
|
|
5100
|
+
Object.assign(directory, extraFieldData);
|
|
5101
|
+
}
|
|
5102
|
+
|
|
5062
5103
|
function readExtraFieldUnix(extraField, directory, isInfoZip) {
|
|
5063
5104
|
try {
|
|
5064
5105
|
const view = getDataView(extraField.data);
|
|
@@ -5137,7 +5178,7 @@
|
|
|
5137
5178
|
fileEntry,
|
|
5138
5179
|
index,
|
|
5139
5180
|
offset,
|
|
5140
|
-
|
|
5181
|
+
crc32,
|
|
5141
5182
|
compressedSize,
|
|
5142
5183
|
uncompressedSize,
|
|
5143
5184
|
dataOffset,
|
|
@@ -5158,7 +5199,7 @@
|
|
|
5158
5199
|
const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
|
|
5159
5200
|
getUint32(getDataView(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
|
|
5160
5201
|
if (dataDescriptorSignature) {
|
|
5161
|
-
const
|
|
5202
|
+
const readCrc32 = getUint32(getDataView(dataDescriptorArray), 4);
|
|
5162
5203
|
let readCompressedSize;
|
|
5163
5204
|
let readUncompressedSize;
|
|
5164
5205
|
if (extraFieldZip64) {
|
|
@@ -5168,8 +5209,8 @@
|
|
|
5168
5209
|
readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
|
|
5169
5210
|
readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
|
|
5170
5211
|
}
|
|
5171
|
-
const
|
|
5172
|
-
if (
|
|
5212
|
+
const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || readCrc32 == crc32;
|
|
5213
|
+
if (matchCrc32 &&
|
|
5173
5214
|
readCompressedSize == compressedSize &&
|
|
5174
5215
|
readUncompressedSize == uncompressedSize) {
|
|
5175
5216
|
dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
|
|
@@ -5338,11 +5379,11 @@
|
|
|
5338
5379
|
throwAmbiguousArchive("mismatched local file header (compression method)");
|
|
5339
5380
|
}
|
|
5340
5381
|
if (!localDirectory.bitFlag.dataDescriptor &&
|
|
5341
|
-
(localDirectory.
|
|
5342
|
-
(localDirectory.
|
|
5382
|
+
(localDirectory.crc32 || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
|
|
5383
|
+
(localDirectory.crc32 != zipEntry.crc32 ||
|
|
5343
5384
|
localDirectory.compressedSize != zipEntry.compressedSize ||
|
|
5344
5385
|
localDirectory.uncompressedSize != zipEntry.uncompressedSize)) {
|
|
5345
|
-
throwAmbiguousArchive("mismatched local file header (
|
|
5386
|
+
throwAmbiguousArchive("mismatched local file header (crc32 or sizes)");
|
|
5346
5387
|
}
|
|
5347
5388
|
}
|
|
5348
5389
|
|
|
@@ -5358,11 +5399,7 @@
|
|
|
5358
5399
|
|
|
5359
5400
|
function getDate(timeRaw) {
|
|
5360
5401
|
const date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & MAX_16_BITS;
|
|
5361
|
-
|
|
5362
|
-
return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
|
|
5363
|
-
} catch {
|
|
5364
|
-
// ignored
|
|
5365
|
-
}
|
|
5402
|
+
return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
|
|
5366
5403
|
}
|
|
5367
5404
|
|
|
5368
5405
|
function getDateNTFS(timeRaw) {
|
|
@@ -5395,7 +5432,9 @@
|
|
|
5395
5432
|
ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND: ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND,
|
|
5396
5433
|
ERR_EOCDR_NOT_FOUND: ERR_EOCDR_NOT_FOUND,
|
|
5397
5434
|
ERR_EXTRAFIELD_ZIP64_NOT_FOUND: ERR_EXTRAFIELD_ZIP64_NOT_FOUND,
|
|
5435
|
+
ERR_INVALID_AUTHENTICATION_CODE: ERR_INVALID_AUTHENTICATION_CODE,
|
|
5398
5436
|
ERR_INVALID_COMPRESSED_DATA: ERR_INVALID_COMPRESSED_DATA,
|
|
5437
|
+
ERR_INVALID_CRC32: ERR_INVALID_CRC32,
|
|
5399
5438
|
ERR_INVALID_PASSWORD: ERR_INVALID_PASSWORD,
|
|
5400
5439
|
ERR_INVALID_SIGNATURE: ERR_INVALID_SIGNATURE,
|
|
5401
5440
|
ERR_INVALID_UNCOMPRESSED_SIZE: ERR_INVALID_UNCOMPRESSED_SIZE,
|
|
@@ -5448,6 +5487,8 @@
|
|
|
5448
5487
|
const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
|
|
5449
5488
|
const MIN_UNIX_TIME = -2147483648;
|
|
5450
5489
|
const MAX_UNIX_TIME = 2147483647;
|
|
5490
|
+
const MIN_NTFS_TIME = BigInt(0);
|
|
5491
|
+
const MAX_NTFS_TIME = BigInt("0x7fffffffffffffff");
|
|
5451
5492
|
const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
|
|
5452
5493
|
const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
|
|
5453
5494
|
const ERR_UNDEFINED_READER = "Undefined reader";
|
|
@@ -5461,7 +5502,9 @@
|
|
|
5461
5502
|
const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
|
|
5462
5503
|
|
|
5463
5504
|
const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
|
|
5464
|
-
const
|
|
5505
|
+
const EXTRAFIELD_OFFSET_AES_VENDOR_VERSION = 4;
|
|
5506
|
+
const VENDOR_VERSION_AE_1 = 1;
|
|
5507
|
+
const INFOZIP_EXTRA_FIELD_TYPE$1 = "infozip";
|
|
5465
5508
|
const UNIX_EXTRA_FIELD_TYPE = "unix";
|
|
5466
5509
|
|
|
5467
5510
|
let workers = 0;
|
|
@@ -5555,9 +5598,9 @@
|
|
|
5555
5598
|
zip64UncompressedSize,
|
|
5556
5599
|
extraFieldLength
|
|
5557
5600
|
});
|
|
5558
|
-
const {
|
|
5559
|
-
if (
|
|
5560
|
-
setUint32(headerView, HEADER_OFFSET_SIGNATURE,
|
|
5601
|
+
const { crc32 } = entry;
|
|
5602
|
+
if (crc32 !== UNDEFINED_VALUE) {
|
|
5603
|
+
setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
|
|
5561
5604
|
}
|
|
5562
5605
|
Object.assign(entry, {
|
|
5563
5606
|
zip64UncompressedSize,
|
|
@@ -5680,6 +5723,7 @@
|
|
|
5680
5723
|
internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
|
|
5681
5724
|
externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
|
|
5682
5725
|
signature: options[PROPERTY_NAME_SIGNATURE],
|
|
5726
|
+
crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
|
|
5683
5727
|
offset: zipWriter.offset - diskOffset,
|
|
5684
5728
|
diskNumberStart: diskNumber
|
|
5685
5729
|
});
|
|
@@ -5716,7 +5760,7 @@
|
|
|
5716
5760
|
if (unixMode !== UNDEFINED_VALUE && (unixMode < 0 || unixMode > MAX_16_BITS)) {
|
|
5717
5761
|
throw new Error(ERR_INVALID_UNIX_MODE);
|
|
5718
5762
|
}
|
|
5719
|
-
if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
|
|
5763
|
+
if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE$1 && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
|
|
5720
5764
|
throw new Error(ERR_INVALID_UNIX_EXTRA_FIELD_TYPE);
|
|
5721
5765
|
}
|
|
5722
5766
|
if (unixExtraFieldType === UNIX_EXTRA_FIELD_TYPE &&
|
|
@@ -5724,7 +5768,7 @@
|
|
|
5724
5768
|
throw new Error(ERR_INVALID_UNIX_ID_SIZE);
|
|
5725
5769
|
}
|
|
5726
5770
|
if (unixExtraFieldType === UNDEFINED_VALUE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
|
|
5727
|
-
unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE;
|
|
5771
|
+
unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE$1;
|
|
5728
5772
|
}
|
|
5729
5773
|
let msdosAttributesRaw = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
|
|
5730
5774
|
let msdosAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES);
|
|
@@ -5896,27 +5940,8 @@
|
|
|
5896
5940
|
if (!zipCrypto && (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) && !(encryptionStrength >= 1 && encryptionStrength <= 3)) {
|
|
5897
5941
|
throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
|
|
5898
5942
|
}
|
|
5899
|
-
|
|
5900
|
-
const
|
|
5901
|
-
if (extraField) {
|
|
5902
|
-
let extraFieldSize = 0;
|
|
5903
|
-
let offset = 0;
|
|
5904
|
-
extraField.forEach(data => extraFieldSize += 4 + getLength(data));
|
|
5905
|
-
rawExtraField = new Uint8Array(extraFieldSize);
|
|
5906
|
-
const rawExtraFieldView = getDataView(rawExtraField);
|
|
5907
|
-
extraField.forEach((data, type) => {
|
|
5908
|
-
if (type > MAX_16_BITS) {
|
|
5909
|
-
throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
|
|
5910
|
-
}
|
|
5911
|
-
if (getLength(data) > MAX_16_BITS) {
|
|
5912
|
-
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
5913
|
-
}
|
|
5914
|
-
setUint16(rawExtraFieldView, offset, type);
|
|
5915
|
-
setUint16(rawExtraFieldView, offset + 2, getLength(data));
|
|
5916
|
-
arraySet(rawExtraField, data, offset + 4);
|
|
5917
|
-
offset += 4 + getLength(data);
|
|
5918
|
-
});
|
|
5919
|
-
}
|
|
5943
|
+
const rawExtraField = serializeExtraField(options[PROPERTY_NAME_EXTRA_FIELD]);
|
|
5944
|
+
const rawLocalExtraField = serializeExtraField(options[OPTION_LOCAL_EXTRA_FIELD]);
|
|
5920
5945
|
return {
|
|
5921
5946
|
comment,
|
|
5922
5947
|
resolvedOptions: {
|
|
@@ -5950,11 +5975,36 @@
|
|
|
5950
5975
|
useCompressionStream,
|
|
5951
5976
|
dataDescriptor,
|
|
5952
5977
|
zip64,
|
|
5953
|
-
rawExtraField
|
|
5978
|
+
rawExtraField,
|
|
5979
|
+
rawLocalExtraField
|
|
5954
5980
|
}
|
|
5955
5981
|
};
|
|
5956
5982
|
}
|
|
5957
5983
|
|
|
5984
|
+
function serializeExtraField(extraField) {
|
|
5985
|
+
if (!extraField) {
|
|
5986
|
+
return EMPTY_UINT8_ARRAY;
|
|
5987
|
+
}
|
|
5988
|
+
let extraFieldSize = 0;
|
|
5989
|
+
let offset = 0;
|
|
5990
|
+
extraField.forEach(data => extraFieldSize += 4 + getLength(data));
|
|
5991
|
+
const rawExtraField = new Uint8Array(extraFieldSize);
|
|
5992
|
+
const rawExtraFieldView = getDataView(rawExtraField);
|
|
5993
|
+
extraField.forEach((data, type) => {
|
|
5994
|
+
if (type > MAX_16_BITS) {
|
|
5995
|
+
throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
|
|
5996
|
+
}
|
|
5997
|
+
if (getLength(data) > MAX_16_BITS) {
|
|
5998
|
+
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
5999
|
+
}
|
|
6000
|
+
setUint16(rawExtraFieldView, offset, type);
|
|
6001
|
+
setUint16(rawExtraFieldView, offset + 2, getLength(data));
|
|
6002
|
+
arraySet(rawExtraField, data, offset + 4);
|
|
6003
|
+
offset += 4 + getLength(data);
|
|
6004
|
+
});
|
|
6005
|
+
return rawExtraField;
|
|
6006
|
+
}
|
|
6007
|
+
|
|
5958
6008
|
async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
|
|
5959
6009
|
const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
|
|
5960
6010
|
let { dataDescriptor, zip64, level, compressionMethod } = metadata;
|
|
@@ -6279,7 +6329,7 @@
|
|
|
6279
6329
|
msdosAttributes
|
|
6280
6330
|
};
|
|
6281
6331
|
let {
|
|
6282
|
-
|
|
6332
|
+
crc32,
|
|
6283
6333
|
uncompressedSize
|
|
6284
6334
|
} = options;
|
|
6285
6335
|
let compressedSize = 0;
|
|
@@ -6299,7 +6349,7 @@
|
|
|
6299
6349
|
encryptionStrength,
|
|
6300
6350
|
zipCrypto: encrypted && zipCrypto,
|
|
6301
6351
|
passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & MAX_8_BITS,
|
|
6302
|
-
|
|
6352
|
+
computeCrc32: !passThrough,
|
|
6303
6353
|
compressed: compressed && !passThrough,
|
|
6304
6354
|
encrypted: encrypted && !passThrough,
|
|
6305
6355
|
useWebWorkers,
|
|
@@ -6318,7 +6368,9 @@
|
|
|
6318
6368
|
writer.size += compressedSize;
|
|
6319
6369
|
if (!passThrough) {
|
|
6320
6370
|
uncompressedSize = result.inputSize;
|
|
6321
|
-
|
|
6371
|
+
if (!encrypted || zipCrypto) {
|
|
6372
|
+
crc32 = result.crc32;
|
|
6373
|
+
}
|
|
6322
6374
|
}
|
|
6323
6375
|
if ((!zip64CompressedSize && compressedSize >= MAX_32_BITS) ||
|
|
6324
6376
|
(!zip64UncompressedSize && uncompressedSize >= MAX_32_BITS)) {
|
|
@@ -6333,7 +6385,7 @@
|
|
|
6333
6385
|
|
|
6334
6386
|
}
|
|
6335
6387
|
setEntryInfo({
|
|
6336
|
-
|
|
6388
|
+
crc32,
|
|
6337
6389
|
compressedSize,
|
|
6338
6390
|
uncompressedSize,
|
|
6339
6391
|
headerInfo,
|
|
@@ -6356,7 +6408,8 @@
|
|
|
6356
6408
|
version,
|
|
6357
6409
|
headerArray,
|
|
6358
6410
|
headerView,
|
|
6359
|
-
signature,
|
|
6411
|
+
signature: crc32,
|
|
6412
|
+
crc32: encrypted && !zipCrypto && !passThrough ? UNDEFINED_VALUE : crc32,
|
|
6360
6413
|
extraFieldExtendedTimestampFlag,
|
|
6361
6414
|
zip64UncompressedSize,
|
|
6362
6415
|
zip64CompressedSize
|
|
@@ -6377,6 +6430,7 @@
|
|
|
6377
6430
|
dataDescriptor,
|
|
6378
6431
|
directory,
|
|
6379
6432
|
rawExtraField,
|
|
6433
|
+
rawLocalExtraField,
|
|
6380
6434
|
encryptionStrength,
|
|
6381
6435
|
extendedTimestamp,
|
|
6382
6436
|
ntfsTimestamp,
|
|
@@ -6384,7 +6438,8 @@
|
|
|
6384
6438
|
encrypted,
|
|
6385
6439
|
zip64UncompressedSize,
|
|
6386
6440
|
zip64CompressedSize,
|
|
6387
|
-
uncompressedSize
|
|
6441
|
+
uncompressedSize,
|
|
6442
|
+
crc32
|
|
6388
6443
|
} = options;
|
|
6389
6444
|
let { version, compressionMethod } = options;
|
|
6390
6445
|
const compressed = !directory && (compressionMethod === UNDEFINED_VALUE
|
|
@@ -6457,8 +6512,8 @@
|
|
|
6457
6512
|
extraFieldNTFS.uint16(EXTRAFIELD_TYPE_NTFS_TAG1);
|
|
6458
6513
|
extraFieldNTFS.uint16(24);
|
|
6459
6514
|
extraFieldNTFS.uint64(lastModTimeNTFS);
|
|
6460
|
-
extraFieldNTFS.uint64(getTimeNTFS(lastAccessDate)
|
|
6461
|
-
extraFieldNTFS.uint64(getTimeNTFS(creationDate)
|
|
6515
|
+
extraFieldNTFS.uint64(lastAccessDate ? getTimeNTFS(lastAccessDate) : lastModTimeNTFS);
|
|
6516
|
+
extraFieldNTFS.uint64(creationDate ? getTimeNTFS(creationDate) : lastModTimeNTFS);
|
|
6462
6517
|
rawExtraFieldNTFS = extraFieldNTFS.array;
|
|
6463
6518
|
} catch {
|
|
6464
6519
|
rawExtraFieldNTFS = EMPTY_UINT8_ARRAY;
|
|
@@ -6472,7 +6527,7 @@
|
|
|
6472
6527
|
let rawExtraFieldUnix;
|
|
6473
6528
|
try {
|
|
6474
6529
|
const { uid, gid, unixExtraFieldType } = options;
|
|
6475
|
-
if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
|
|
6530
|
+
if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE$1 && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
|
|
6476
6531
|
const uidBytes = packUnixId(uid);
|
|
6477
6532
|
const gidBytes = packUnixId(gid);
|
|
6478
6533
|
const payloadLength = 3 + uidBytes.length + gidBytes.length;
|
|
@@ -6510,15 +6565,18 @@
|
|
|
6510
6565
|
}
|
|
6511
6566
|
if (encrypted && !zipCrypto) {
|
|
6512
6567
|
version = version > VERSION_AES ? version : VERSION_AES;
|
|
6568
|
+
if (passThrough && crc32 !== UNDEFINED_VALUE) {
|
|
6569
|
+
rawExtraFieldAES[EXTRAFIELD_OFFSET_AES_VENDOR_VERSION] = VENDOR_VERSION_AE_1;
|
|
6570
|
+
}
|
|
6513
6571
|
rawExtraFieldAES[9] = compressionMethod;
|
|
6514
6572
|
compressionMethod = COMPRESSION_METHOD_AES;
|
|
6515
6573
|
}
|
|
6516
6574
|
const localExtraFieldZip64Length = writeLocalExtraFieldZip64 ? getLength(rawLocalExtraFieldZip64) : 0;
|
|
6517
|
-
const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
|
|
6575
|
+
const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField, rawLocalExtraField);
|
|
6518
6576
|
if (extraFieldLength > MAX_16_BITS) {
|
|
6519
6577
|
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
6520
6578
|
}
|
|
6521
|
-
const dosLastModDate = new Date(Math.ceil(lastModDate.getTime() /
|
|
6579
|
+
const dosLastModDate = new Date(Math.ceil(Math.floor(lastModDate.getTime() / 1000) / 2) * 2000);
|
|
6522
6580
|
const {
|
|
6523
6581
|
headerArray,
|
|
6524
6582
|
headerView,
|
|
@@ -6548,6 +6606,7 @@
|
|
|
6548
6606
|
localHeader.bytes(rawExtraFieldNTFS);
|
|
6549
6607
|
localHeader.bytes(rawExtraFieldUnix);
|
|
6550
6608
|
localHeader.bytes(rawExtraField);
|
|
6609
|
+
localHeader.bytes(rawLocalExtraField);
|
|
6551
6610
|
if (dataDescriptor) {
|
|
6552
6611
|
if (!zip64CompressedSize) {
|
|
6553
6612
|
setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
|
|
@@ -6666,7 +6725,7 @@
|
|
|
6666
6725
|
}
|
|
6667
6726
|
|
|
6668
6727
|
function setEntryInfo({
|
|
6669
|
-
|
|
6728
|
+
crc32,
|
|
6670
6729
|
compressedSize,
|
|
6671
6730
|
uncompressedSize,
|
|
6672
6731
|
headerInfo,
|
|
@@ -6674,6 +6733,7 @@
|
|
|
6674
6733
|
}, {
|
|
6675
6734
|
zip64,
|
|
6676
6735
|
zipCrypto,
|
|
6736
|
+
passThrough,
|
|
6677
6737
|
dataDescriptor
|
|
6678
6738
|
}) {
|
|
6679
6739
|
const {
|
|
@@ -6684,10 +6744,10 @@
|
|
|
6684
6744
|
dataDescriptorView,
|
|
6685
6745
|
dataDescriptorOffset
|
|
6686
6746
|
} = dataDescriptorInfo;
|
|
6687
|
-
if ((!encrypted || zipCrypto) &&
|
|
6688
|
-
setUint32(headerView, HEADER_OFFSET_SIGNATURE,
|
|
6747
|
+
if ((!encrypted || zipCrypto || passThrough) && crc32 !== UNDEFINED_VALUE) {
|
|
6748
|
+
setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
|
|
6689
6749
|
if (dataDescriptor) {
|
|
6690
|
-
setUint32(dataDescriptorView, dataDescriptorOffset,
|
|
6750
|
+
setUint32(dataDescriptorView, dataDescriptorOffset, crc32);
|
|
6691
6751
|
}
|
|
6692
6752
|
}
|
|
6693
6753
|
if (zip64) {
|
|
@@ -6710,15 +6770,15 @@
|
|
|
6710
6770
|
encrypted,
|
|
6711
6771
|
zip64,
|
|
6712
6772
|
localExtraFieldZip64Length,
|
|
6713
|
-
|
|
6773
|
+
crc32,
|
|
6714
6774
|
compressedSize,
|
|
6715
6775
|
uncompressedSize,
|
|
6716
6776
|
zip64UncompressedSize,
|
|
6717
6777
|
zip64CompressedSize
|
|
6718
|
-
}, localHeaderView, { dataDescriptor }) {
|
|
6778
|
+
}, localHeaderView, { dataDescriptor, passThrough }) {
|
|
6719
6779
|
if (!dataDescriptor) {
|
|
6720
|
-
if (!encrypted) {
|
|
6721
|
-
setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET,
|
|
6780
|
+
if (!encrypted || (passThrough && crc32 !== UNDEFINED_VALUE)) {
|
|
6781
|
+
setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, crc32);
|
|
6722
6782
|
}
|
|
6723
6783
|
if (!zip64CompressedSize) {
|
|
6724
6784
|
setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, compressedSize);
|
|
@@ -7027,7 +7087,8 @@
|
|
|
7027
7087
|
|
|
7028
7088
|
function getTimeNTFS(date) {
|
|
7029
7089
|
if (date) {
|
|
7030
|
-
|
|
7090
|
+
const timeNTFS = ((BigInt(date.getTime()) + BigInt(11644473600000)) * BigInt(10000));
|
|
7091
|
+
return timeNTFS < MIN_NTFS_TIME ? MIN_NTFS_TIME : timeNTFS > MAX_NTFS_TIME ? MAX_NTFS_TIME : timeNTFS;
|
|
7031
7092
|
}
|
|
7032
7093
|
}
|
|
7033
7094
|
|
|
@@ -7182,6 +7243,20 @@
|
|
|
7182
7243
|
|
|
7183
7244
|
const ERR_ENTRY_EXISTS = "Entry filename already exists";
|
|
7184
7245
|
const ERR_READABLE_CONSUMED = "Readable stream already consumed";
|
|
7246
|
+
const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
|
|
7247
|
+
const INTERPRETED_EXTRA_FIELD_TYPES = new Set([
|
|
7248
|
+
EXTRAFIELD_TYPE_ZIP64,
|
|
7249
|
+
EXTRAFIELD_TYPE_AES,
|
|
7250
|
+
EXTRAFIELD_TYPE_NTFS,
|
|
7251
|
+
EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP,
|
|
7252
|
+
EXTRAFIELD_TYPE_UNICODE_PATH,
|
|
7253
|
+
EXTRAFIELD_TYPE_UNICODE_COMMENT,
|
|
7254
|
+
EXTRAFIELD_TYPE_USDZ,
|
|
7255
|
+
EXTRAFIELD_TYPE_INFOZIP,
|
|
7256
|
+
EXTRAFIELD_TYPE_UNIX,
|
|
7257
|
+
EXTRAFIELD_TYPE_UNIX_TYPE1,
|
|
7258
|
+
EXTRAFIELD_TYPE_PKWARE_UNIX
|
|
7259
|
+
]);
|
|
7185
7260
|
|
|
7186
7261
|
class ZipEntry {
|
|
7187
7262
|
|
|
@@ -7919,6 +7994,20 @@
|
|
|
7919
7994
|
}
|
|
7920
7995
|
}
|
|
7921
7996
|
|
|
7997
|
+
function getUserExtraField(extraField) {
|
|
7998
|
+
if (extraField) {
|
|
7999
|
+
const userExtraField = new Map();
|
|
8000
|
+
extraField.forEach((field, type) => {
|
|
8001
|
+
if (!INTERPRETED_EXTRA_FIELD_TYPES.has(type)) {
|
|
8002
|
+
userExtraField.set(type, field.data);
|
|
8003
|
+
}
|
|
8004
|
+
});
|
|
8005
|
+
if (userExtraField.size) {
|
|
8006
|
+
return userExtraField;
|
|
8007
|
+
}
|
|
8008
|
+
}
|
|
8009
|
+
}
|
|
8010
|
+
|
|
7922
8011
|
async function exportZip(zipWriter, entry, totalSize, options, readers) {
|
|
7923
8012
|
const selectedEntry = entry;
|
|
7924
8013
|
const entryOffsets = new Map();
|
|
@@ -7956,9 +8045,13 @@
|
|
|
7956
8045
|
uncompressedSize,
|
|
7957
8046
|
encrypted,
|
|
7958
8047
|
zipCrypto,
|
|
7959
|
-
|
|
8048
|
+
crc32,
|
|
7960
8049
|
compressionMethod,
|
|
7961
|
-
extraFieldAES
|
|
8050
|
+
extraFieldAES,
|
|
8051
|
+
internalFileAttributes,
|
|
8052
|
+
extraField,
|
|
8053
|
+
uid,
|
|
8054
|
+
gid
|
|
7962
8055
|
} = child.data;
|
|
7963
8056
|
zipEntryOptions = {
|
|
7964
8057
|
externalFileAttributes,
|
|
@@ -7966,8 +8059,20 @@
|
|
|
7966
8059
|
comment,
|
|
7967
8060
|
lastModDate,
|
|
7968
8061
|
creationDate,
|
|
7969
|
-
lastAccessDate
|
|
8062
|
+
lastAccessDate,
|
|
8063
|
+
internalFileAttributes
|
|
7970
8064
|
};
|
|
8065
|
+
const userExtraField = getUserExtraField(extraField);
|
|
8066
|
+
if (userExtraField) {
|
|
8067
|
+
zipEntryOptions.extraField = userExtraField;
|
|
8068
|
+
}
|
|
8069
|
+
if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
|
|
8070
|
+
Object.assign(zipEntryOptions, {
|
|
8071
|
+
uid,
|
|
8072
|
+
gid,
|
|
8073
|
+
unixExtraFieldType: options.unixExtraFieldType || INFOZIP_EXTRA_FIELD_TYPE
|
|
8074
|
+
});
|
|
8075
|
+
}
|
|
7971
8076
|
if (child.passThrough) {
|
|
7972
8077
|
let level, encryptionStrength;
|
|
7973
8078
|
if (compressionMethod === 0) {
|
|
@@ -7980,7 +8085,7 @@
|
|
|
7980
8085
|
passThrough: true,
|
|
7981
8086
|
encrypted,
|
|
7982
8087
|
zipCrypto,
|
|
7983
|
-
|
|
8088
|
+
crc32,
|
|
7984
8089
|
uncompressedSize,
|
|
7985
8090
|
level,
|
|
7986
8091
|
encryptionStrength,
|