@zip.js/zip.js 2.8.51 → 2.8.53
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 +8 -3
- package/deno.json +1 -1
- package/dist/zip-core-external.js +241 -95
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +243 -94
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +564 -199
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +551 -194
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +564 -199
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +567 -198
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +567 -198
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +243 -94
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +243 -94
- package/dist/zip-native.min.js +1 -1
- package/dist/zip.js +243 -94
- package/dist/zip.min.js +1 -1
- package/eslint.config.mjs +1 -1
- package/index-native.cjs +567 -198
- package/index-native.min.js +1 -1
- package/index.cjs +567 -198
- package/index.d.cts +551 -45
- package/index.d.ts +551 -45
- package/index.min.js +1 -1
- package/lib/core/codec-worker-web.js +13 -4
- package/lib/core/codec-worker.js +2 -0
- package/lib/core/constants.js +9 -0
- package/lib/core/io.js +43 -4
- package/lib/core/options.js +2 -0
- package/lib/core/util/compatible-streams.js +3 -8
- package/lib/core/zip-entry.js +16 -0
- package/lib/core/zip-fs.js +236 -107
- package/lib/core/zip-reader.js +106 -40
- package/lib/core/zip-writer.js +171 -41
- package/lib/zip-core-writer.js +3 -0
- package/package.json +9 -7
package/lib/core/zip-reader.js
CHANGED
|
@@ -76,6 +76,7 @@ import {
|
|
|
76
76
|
FILE_ATTR_MSDOS_ARCHIVE_MASK,
|
|
77
77
|
FILE_ATTR_UNIX_TYPE_MASK,
|
|
78
78
|
FILE_ATTR_UNIX_TYPE_DIR,
|
|
79
|
+
FILE_ATTR_UNIX_TYPE_SYMLINK,
|
|
79
80
|
FILE_ATTR_UNIX_EXECUTABLE_MASK,
|
|
80
81
|
FILE_ATTR_UNIX_DEFAULT_MASK,
|
|
81
82
|
DIRECTORY_SIGNATURE,
|
|
@@ -111,7 +112,8 @@ import {
|
|
|
111
112
|
readUint8Array,
|
|
112
113
|
BlobReader,
|
|
113
114
|
GenericReader,
|
|
114
|
-
GenericWriter
|
|
115
|
+
GenericWriter,
|
|
116
|
+
ownsWritable
|
|
115
117
|
} from "./io.js";
|
|
116
118
|
import { decodeText } from "./util/decode-text.js";
|
|
117
119
|
import { getDataView } from "./util/array.js";
|
|
@@ -148,6 +150,7 @@ import {
|
|
|
148
150
|
OPTION_CHECK_OVERLAPPING_ENTRY_ONLY,
|
|
149
151
|
OPTION_CHECK_OVERLAPPING_ENTRY,
|
|
150
152
|
OPTION_CHECK_AMBIGUITY,
|
|
153
|
+
OPTION_CHECK_LOCAL_DIRECTORY,
|
|
151
154
|
OPTION_CHECK_SIGNATURE,
|
|
152
155
|
OPTION_CHECK_CRC32,
|
|
153
156
|
OPTION_CHECK_AUTHENTICATION_CODE,
|
|
@@ -234,7 +237,7 @@ class ZipReader {
|
|
|
234
237
|
if (reader.size < END_OF_CENTRAL_DIR_LENGTH) {
|
|
235
238
|
throw new Error(ERR_BAD_FORMAT);
|
|
236
239
|
}
|
|
237
|
-
const strictness = getStrictness(
|
|
240
|
+
const strictness = getStrictness(options, zipReader.options);
|
|
238
241
|
const checkAmbiguity = strictness == STRICTNESS_STRICT;
|
|
239
242
|
const rejectAmbiguousEndOfDirectory = strictness != STRICTNESS_TOLERANT;
|
|
240
243
|
const maxAppendedDataSize = getMaxAppendedDataSize(getOptionValue(zipReader, options, OPTION_MAX_APPENDED_DATA_SIZE), strictness);
|
|
@@ -456,6 +459,7 @@ class ZipReader {
|
|
|
456
459
|
index: indexFile,
|
|
457
460
|
versionMadeBy,
|
|
458
461
|
msDosCompatible,
|
|
462
|
+
zip64: false,
|
|
459
463
|
compressedSize: 0,
|
|
460
464
|
uncompressedSize: 0,
|
|
461
465
|
commentLength,
|
|
@@ -489,15 +493,18 @@ class ZipReader {
|
|
|
489
493
|
const setuid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETUID_MASK);
|
|
490
494
|
const setgid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETGID_MASK);
|
|
491
495
|
const sticky = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_STICKY_MASK);
|
|
492
|
-
const
|
|
496
|
+
const unixType = fileEntry.unixMode === UNDEFINED_VALUE ? unixExternalUpper : fileEntry.unixMode;
|
|
497
|
+
const symlink = (unixType & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_SYMLINK;
|
|
498
|
+
const executable = !symlink && ((fileEntry.unixMode !== UNDEFINED_VALUE)
|
|
493
499
|
? ((fileEntry.unixMode & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)
|
|
494
|
-
: (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0));
|
|
500
|
+
: (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)));
|
|
495
501
|
const modeIsDir = fileEntry.unixMode !== UNDEFINED_VALUE && ((fileEntry.unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
|
|
496
502
|
const upperIsDir = ((unixExternalUpper & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
|
|
497
503
|
Object.assign(fileEntry, {
|
|
498
504
|
setuid,
|
|
499
505
|
setgid,
|
|
500
506
|
sticky,
|
|
507
|
+
symlink,
|
|
501
508
|
unixExternalUpper,
|
|
502
509
|
internalFileAttribute: fileEntry.internalFileAttributes,
|
|
503
510
|
externalFileAttribute: fileEntry.externalFileAttributes,
|
|
@@ -563,6 +570,10 @@ class ZipReader {
|
|
|
563
570
|
}
|
|
564
571
|
|
|
565
572
|
async close() {
|
|
573
|
+
const { reader } = this;
|
|
574
|
+
if (!reader.readUint8Array && reader.readable && !reader.readable.locked) {
|
|
575
|
+
await reader.readable.cancel();
|
|
576
|
+
}
|
|
566
577
|
}
|
|
567
578
|
}
|
|
568
579
|
|
|
@@ -688,9 +699,12 @@ class ZipEntry {
|
|
|
688
699
|
extraFieldLength,
|
|
689
700
|
filenameLength
|
|
690
701
|
} = localDirectory;
|
|
691
|
-
const
|
|
702
|
+
const checkLocalDirectoryOption = getOptionValue(zipEntry, options, OPTION_CHECK_LOCAL_DIRECTORY);
|
|
703
|
+
const entryStrictness = getStrictness(options, zipEntry.options);
|
|
704
|
+
const checkLocalDirectory = getCheckLocalDirectory(checkLocalDirectoryOption, entryStrictness);
|
|
705
|
+
const checkLocalFilename = getCheckLocalFilename(checkLocalDirectoryOption, entryStrictness);
|
|
692
706
|
let rawLocalFilename = EMPTY_UINT8_ARRAY;
|
|
693
|
-
if (
|
|
707
|
+
if (checkLocalFilename && (filenameLength || extraFieldLength)) {
|
|
694
708
|
const trailingDataArray = await readUint8Array(reader, localHeaderOffset + HEADER_SIZE, filenameLength + extraFieldLength);
|
|
695
709
|
rawLocalFilename = trailingDataArray.subarray(0, filenameLength);
|
|
696
710
|
localDirectory.rawExtraField = trailingDataArray.subarray(filenameLength);
|
|
@@ -699,17 +713,26 @@ class ZipEntry {
|
|
|
699
713
|
await readUint8Array(reader, localHeaderOffset + HEADER_SIZE + filenameLength, extraFieldLength) :
|
|
700
714
|
EMPTY_UINT8_ARRAY;
|
|
701
715
|
}
|
|
716
|
+
if (checkLocalFilename) {
|
|
717
|
+
localDirectory.rawFilename = rawLocalFilename;
|
|
718
|
+
}
|
|
702
719
|
readCommonFooter(zipEntry, localDirectory, dataView, 4, true);
|
|
703
|
-
if (
|
|
704
|
-
|
|
720
|
+
if (checkLocalDirectory) {
|
|
721
|
+
validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename);
|
|
705
722
|
}
|
|
706
|
-
const { lastAccessDate, creationDate } = localDirectory;
|
|
723
|
+
const { lastAccessDate, creationDate, uid, gid } = localDirectory;
|
|
707
724
|
if (lastAccessDate) {
|
|
708
725
|
fileEntry.lastAccessDate = lastAccessDate;
|
|
709
726
|
}
|
|
710
727
|
if (creationDate) {
|
|
711
728
|
fileEntry.creationDate = creationDate;
|
|
712
729
|
}
|
|
730
|
+
if (uid !== UNDEFINED_VALUE && fileEntry.uid === UNDEFINED_VALUE) {
|
|
731
|
+
fileEntry.uid = uid;
|
|
732
|
+
}
|
|
733
|
+
if (gid !== UNDEFINED_VALUE && fileEntry.gid === UNDEFINED_VALUE) {
|
|
734
|
+
fileEntry.gid = gid;
|
|
735
|
+
}
|
|
713
736
|
const encrypted = zipEntry.encrypted && localDirectory.encrypted && !passThrough;
|
|
714
737
|
const zipCrypto = encrypted && !extraFieldAES;
|
|
715
738
|
if (!passThrough) {
|
|
@@ -816,7 +839,7 @@ class ZipEntry {
|
|
|
816
839
|
throw error;
|
|
817
840
|
}
|
|
818
841
|
} finally {
|
|
819
|
-
const preventClose = getOptionValue(zipEntry, options, OPTION_PREVENT_CLOSE);
|
|
842
|
+
const preventClose = !ownsWritable(writer) && getOptionValue(zipEntry, options, OPTION_PREVENT_CLOSE);
|
|
820
843
|
if (!preventClose && writable && !writable.locked) {
|
|
821
844
|
const writableWriter = writable.getWriter();
|
|
822
845
|
if (abortError) {
|
|
@@ -945,10 +968,12 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
|
|
|
945
968
|
directory.extraFieldNTFS = extraFieldNTFS;
|
|
946
969
|
}
|
|
947
970
|
const extraFieldUnix = extraField.get(EXTRAFIELD_TYPE_UNIX);
|
|
971
|
+
let unixIdsRead;
|
|
948
972
|
if (extraFieldUnix) {
|
|
949
|
-
readExtraFieldUnix(extraFieldUnix, directory, false);
|
|
973
|
+
unixIdsRead = readExtraFieldUnix(extraFieldUnix, directory, false);
|
|
950
974
|
directory.extraFieldUnix = extraFieldUnix;
|
|
951
|
-
}
|
|
975
|
+
}
|
|
976
|
+
if (!unixIdsRead) {
|
|
952
977
|
const extraFieldInfoZip = extraField.get(EXTRAFIELD_TYPE_INFOZIP);
|
|
953
978
|
if (extraFieldInfoZip) {
|
|
954
979
|
readExtraFieldUnix(extraFieldInfoZip, directory, true);
|
|
@@ -1051,7 +1076,7 @@ function readExtraFieldNTFS(extraFieldNTFS, directory) {
|
|
|
1051
1076
|
const creationDate = getDateNTFS(rawCreationDate);
|
|
1052
1077
|
const extraFieldData = { lastModDate, lastAccessDate, creationDate };
|
|
1053
1078
|
Object.assign(extraFieldNTFS, extraFieldData);
|
|
1054
|
-
Object.assign(directory, extraFieldData);
|
|
1079
|
+
Object.assign(directory, extraFieldData, { rawLastAccessDate, rawCreationDate });
|
|
1055
1080
|
}
|
|
1056
1081
|
}
|
|
1057
1082
|
|
|
@@ -1060,8 +1085,8 @@ function readExtraFieldUnixDates(extraField, directory) {
|
|
|
1060
1085
|
return;
|
|
1061
1086
|
}
|
|
1062
1087
|
const extraFieldView = getDataView(extraField.data);
|
|
1063
|
-
const lastAccessDate = new Date(getUint32(extraFieldView, 0) * 1000);
|
|
1064
|
-
const lastModDate = new Date(getUint32(extraFieldView, 4) * 1000);
|
|
1088
|
+
const lastAccessDate = new Date((getUint32(extraFieldView, 0) | 0) * 1000);
|
|
1089
|
+
const lastModDate = new Date((getUint32(extraFieldView, 4) | 0) * 1000);
|
|
1065
1090
|
const extraFieldData = { lastAccessDate, lastModDate };
|
|
1066
1091
|
if (extraField.data.length >= 12) {
|
|
1067
1092
|
extraFieldData.uid = getUint16(extraFieldView, 8);
|
|
@@ -1095,6 +1120,7 @@ function readExtraFieldUnix(extraField, directory, isInfoZip) {
|
|
|
1095
1120
|
if (gid !== UNDEFINED_VALUE) {
|
|
1096
1121
|
directory.gid = gid;
|
|
1097
1122
|
}
|
|
1123
|
+
return uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE;
|
|
1098
1124
|
} catch {
|
|
1099
1125
|
// ignored
|
|
1100
1126
|
}
|
|
@@ -1167,26 +1193,25 @@ async function detectOverlappingEntry({
|
|
|
1167
1193
|
}
|
|
1168
1194
|
if (dataDescriptorLength) {
|
|
1169
1195
|
const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH);
|
|
1170
|
-
const
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
if (extraFieldZip64) {
|
|
1177
|
-
readCompressedSize = getBigUint64(getDataView(dataDescriptorArray), 8);
|
|
1178
|
-
readUncompressedSize = getBigUint64(getDataView(dataDescriptorArray), 16);
|
|
1179
|
-
} else {
|
|
1180
|
-
readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
|
|
1181
|
-
readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
|
|
1182
|
-
}
|
|
1183
|
-
const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || readCrc32 == crc32;
|
|
1196
|
+
const dataDescriptorView = getDataView(dataDescriptorArray);
|
|
1197
|
+
let signature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
|
|
1198
|
+
getUint32(dataDescriptorView, 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
|
|
1199
|
+
if (signature) {
|
|
1200
|
+
const signedDataDescriptor = readDataDescriptor(dataDescriptorView, DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH, extraFieldZip64);
|
|
1201
|
+
const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || signedDataDescriptor.crc32 == crc32;
|
|
1184
1202
|
if (matchCrc32 &&
|
|
1185
|
-
|
|
1186
|
-
|
|
1203
|
+
signedDataDescriptor.compressedSize == compressedSize &&
|
|
1204
|
+
signedDataDescriptor.uncompressedSize == uncompressedSize) {
|
|
1187
1205
|
dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
|
|
1206
|
+
} else {
|
|
1207
|
+
signature = false;
|
|
1188
1208
|
}
|
|
1189
1209
|
}
|
|
1210
|
+
if (dataDescriptorArray.length >= dataDescriptorLength) {
|
|
1211
|
+
const localDataDescriptor = readDataDescriptor(dataDescriptorView, signature ? DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH : 0, extraFieldZip64);
|
|
1212
|
+
localDataDescriptor.signature = signature;
|
|
1213
|
+
fileEntry.localDirectory.dataDescriptor = localDataDescriptor;
|
|
1214
|
+
}
|
|
1190
1215
|
}
|
|
1191
1216
|
const range = {
|
|
1192
1217
|
start: offset,
|
|
@@ -1203,6 +1228,20 @@ async function detectOverlappingEntry({
|
|
|
1203
1228
|
readRanges.set(index, range);
|
|
1204
1229
|
}
|
|
1205
1230
|
|
|
1231
|
+
function readDataDescriptor(dataDescriptorView, offset, extraFieldZip64) {
|
|
1232
|
+
const crc32 = getUint32(dataDescriptorView, offset);
|
|
1233
|
+
let compressedSize;
|
|
1234
|
+
let uncompressedSize;
|
|
1235
|
+
if (extraFieldZip64) {
|
|
1236
|
+
compressedSize = getBigUint64(dataDescriptorView, offset + 4);
|
|
1237
|
+
uncompressedSize = getBigUint64(dataDescriptorView, offset + 12);
|
|
1238
|
+
} else {
|
|
1239
|
+
compressedSize = getUint32(dataDescriptorView, offset + 4);
|
|
1240
|
+
uncompressedSize = getUint32(dataDescriptorView, offset + 8);
|
|
1241
|
+
}
|
|
1242
|
+
return { crc32, compressedSize, uncompressedSize };
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1206
1245
|
function getDiskOffset(reader, diskNumber) {
|
|
1207
1246
|
return reader.getDiskOffset ? reader.getDiskOffset(diskNumber) : 0;
|
|
1208
1247
|
}
|
|
@@ -1211,14 +1250,40 @@ function isStrictnessValue(value) {
|
|
|
1211
1250
|
return value === STRICTNESS_STRICT || value === STRICTNESS_BALANCED || value === STRICTNESS_TOLERANT;
|
|
1212
1251
|
}
|
|
1213
1252
|
|
|
1214
|
-
function getStrictness(
|
|
1215
|
-
|
|
1216
|
-
|
|
1253
|
+
function getStrictness(options, inheritedOptions) {
|
|
1254
|
+
return resolveStrictness(options, resolveStrictness(inheritedOptions, STRICTNESS_BALANCED));
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
function resolveStrictness(options, inheritedStrictness) {
|
|
1258
|
+
const strictness = options[OPTION_STRICTNESS];
|
|
1259
|
+
if (strictness !== UNDEFINED_VALUE) {
|
|
1260
|
+
if (!isStrictnessValue(strictness)) {
|
|
1261
|
+
throw new Error(ERR_INVALID_STRICTNESS);
|
|
1262
|
+
}
|
|
1263
|
+
return strictness;
|
|
1264
|
+
}
|
|
1265
|
+
const checkAmbiguity = options[OPTION_CHECK_AMBIGUITY];
|
|
1266
|
+
if (checkAmbiguity === UNDEFINED_VALUE) {
|
|
1267
|
+
return inheritedStrictness;
|
|
1217
1268
|
}
|
|
1218
|
-
if (
|
|
1219
|
-
|
|
1269
|
+
if (checkAmbiguity) {
|
|
1270
|
+
return STRICTNESS_STRICT;
|
|
1271
|
+
}
|
|
1272
|
+
return inheritedStrictness == STRICTNESS_TOLERANT ? STRICTNESS_TOLERANT : STRICTNESS_BALANCED;
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
function getCheckLocalDirectory(checkLocalDirectory, strictness) {
|
|
1276
|
+
if (checkLocalDirectory === UNDEFINED_VALUE) {
|
|
1277
|
+
return strictness != STRICTNESS_TOLERANT;
|
|
1278
|
+
}
|
|
1279
|
+
return Boolean(checkLocalDirectory);
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
function getCheckLocalFilename(checkLocalFilename, strictness) {
|
|
1283
|
+
if (checkLocalFilename === UNDEFINED_VALUE) {
|
|
1284
|
+
return strictness == STRICTNESS_STRICT;
|
|
1220
1285
|
}
|
|
1221
|
-
return
|
|
1286
|
+
return Boolean(checkLocalFilename);
|
|
1222
1287
|
}
|
|
1223
1288
|
|
|
1224
1289
|
function getFilenameValidation(filenameValidation, strictness) {
|
|
@@ -1366,10 +1431,11 @@ async function readSignature(reader, view, anchoredOffset, signatureOffset, size
|
|
|
1366
1431
|
return UNDEFINED_VALUE;
|
|
1367
1432
|
}
|
|
1368
1433
|
|
|
1369
|
-
function
|
|
1434
|
+
function validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename) {
|
|
1370
1435
|
const { rawFilename } = zipEntry;
|
|
1371
|
-
if (
|
|
1372
|
-
rawLocalFilename.
|
|
1436
|
+
if (checkLocalFilename &&
|
|
1437
|
+
(rawLocalFilename.length != rawFilename.length ||
|
|
1438
|
+
rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte]))) {
|
|
1373
1439
|
throwAmbiguousArchive("mismatched local file header (filename)");
|
|
1374
1440
|
}
|
|
1375
1441
|
if ((localDirectory.rawBitFlag & BITFLAG_AMBIGUITY_MASK) != (zipEntry.rawBitFlag & BITFLAG_AMBIGUITY_MASK)) {
|