styled-map-package 4.0.1 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/smp-download.js +1 -1
- package/bin/smp-view.js +32 -23
- package/dist/download.d.cts +1 -1
- package/dist/download.d.ts +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/reader-watch.d.cts +1 -1
- package/dist/reader-watch.d.ts +1 -1
- package/dist/reader.cjs +2 -1
- package/dist/reader.d.cts +1 -1
- package/dist/reader.d.ts +1 -1
- package/dist/reader.js +2 -1
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/style-downloader.cjs +2 -2
- package/dist/style-downloader.d.cts +1 -1
- package/dist/style-downloader.d.ts +1 -1
- package/dist/style-downloader.js +2 -2
- package/dist/tile-downloader.cjs +2 -2
- package/dist/tile-downloader.d.cts +1 -1
- package/dist/tile-downloader.d.ts +1 -1
- package/dist/tile-downloader.js +2 -2
- package/dist/{types-B4Xn1F9K.d.cts → types-yLQy3AKR.d.cts} +6 -3
- package/dist/{types-B4Xn1F9K.d.ts → types-yLQy3AKR.d.ts} +6 -3
- package/dist/utils/file-formats.d.cts +1 -1
- package/dist/utils/file-formats.d.ts +1 -1
- package/dist/utils/style.cjs +2 -2
- package/dist/utils/style.d.cts +1 -1
- package/dist/utils/style.d.ts +1 -1
- package/dist/utils/style.js +2 -2
- package/dist/utils/templates.cjs +4 -0
- package/dist/utils/templates.d.cts +4 -2
- package/dist/utils/templates.d.ts +4 -2
- package/dist/utils/templates.js +2 -0
- package/dist/writer.cjs +51 -3
- package/dist/writer.d.cts +1 -1
- package/dist/writer.d.ts +1 -1
- package/dist/writer.js +53 -3
- package/node_modules/@node-rs/crc32/LICENSE +21 -0
- package/node_modules/@node-rs/crc32/README.md +61 -0
- package/node_modules/@node-rs/crc32/browser.js +1 -0
- package/node_modules/@node-rs/crc32/index.d.ts +5 -0
- package/node_modules/@node-rs/crc32/index.js +368 -0
- package/node_modules/@node-rs/crc32/package.json +97 -0
- package/node_modules/@node-rs/crc32-linux-x64-gnu/README.md +3 -0
- package/node_modules/@node-rs/crc32-linux-x64-gnu/crc32.linux-x64-gnu.node +0 -0
- package/node_modules/@node-rs/crc32-linux-x64-gnu/package.json +43 -0
- package/node_modules/@node-rs/crc32-linux-x64-musl/README.md +3 -0
- package/node_modules/@node-rs/crc32-linux-x64-musl/crc32.linux-x64-musl.node +0 -0
- package/node_modules/@node-rs/crc32-linux-x64-musl/package.json +43 -0
- package/node_modules/define-data-property/.eslintrc +24 -0
- package/node_modules/define-data-property/.github/FUNDING.yml +12 -0
- package/node_modules/define-data-property/.nycrc +13 -0
- package/node_modules/define-data-property/CHANGELOG.md +70 -0
- package/node_modules/define-data-property/LICENSE +21 -0
- package/node_modules/define-data-property/README.md +67 -0
- package/node_modules/define-data-property/index.d.ts +12 -0
- package/node_modules/define-data-property/index.js +56 -0
- package/node_modules/define-data-property/package.json +106 -0
- package/node_modules/define-data-property/test/index.js +392 -0
- package/node_modules/define-data-property/tsconfig.json +59 -0
- package/node_modules/define-properties/.editorconfig +13 -0
- package/node_modules/define-properties/.eslintrc +19 -0
- package/node_modules/define-properties/.github/FUNDING.yml +12 -0
- package/node_modules/define-properties/.nycrc +9 -0
- package/node_modules/define-properties/CHANGELOG.md +91 -0
- package/node_modules/define-properties/LICENSE +21 -0
- package/node_modules/define-properties/README.md +84 -0
- package/node_modules/define-properties/index.js +47 -0
- package/node_modules/define-properties/package.json +88 -0
- package/node_modules/es-define-property/.eslintrc +13 -0
- package/node_modules/es-define-property/.github/FUNDING.yml +12 -0
- package/node_modules/es-define-property/.nycrc +9 -0
- package/node_modules/es-define-property/CHANGELOG.md +29 -0
- package/node_modules/es-define-property/LICENSE +21 -0
- package/node_modules/es-define-property/README.md +49 -0
- package/node_modules/es-define-property/index.d.ts +3 -0
- package/node_modules/es-define-property/index.js +14 -0
- package/node_modules/es-define-property/package.json +81 -0
- package/node_modules/es-define-property/test/index.js +56 -0
- package/node_modules/es-define-property/tsconfig.json +10 -0
- package/node_modules/es-errors/.eslintrc +5 -0
- package/node_modules/es-errors/.github/FUNDING.yml +12 -0
- package/node_modules/es-errors/CHANGELOG.md +40 -0
- package/node_modules/es-errors/LICENSE +21 -0
- package/node_modules/es-errors/README.md +55 -0
- package/node_modules/es-errors/eval.d.ts +3 -0
- package/node_modules/es-errors/eval.js +4 -0
- package/node_modules/es-errors/index.d.ts +3 -0
- package/node_modules/es-errors/index.js +4 -0
- package/node_modules/es-errors/package.json +80 -0
- package/node_modules/es-errors/range.d.ts +3 -0
- package/node_modules/es-errors/range.js +4 -0
- package/node_modules/es-errors/ref.d.ts +3 -0
- package/node_modules/es-errors/ref.js +4 -0
- package/node_modules/es-errors/syntax.d.ts +3 -0
- package/node_modules/es-errors/syntax.js +4 -0
- package/node_modules/es-errors/test/index.js +19 -0
- package/node_modules/es-errors/tsconfig.json +49 -0
- package/node_modules/es-errors/type.d.ts +3 -0
- package/node_modules/es-errors/type.js +4 -0
- package/node_modules/es-errors/uri.d.ts +3 -0
- package/node_modules/es-errors/uri.js +4 -0
- package/node_modules/globalthis/.eslintrc +18 -0
- package/node_modules/globalthis/.nycrc +10 -0
- package/node_modules/globalthis/CHANGELOG.md +109 -0
- package/node_modules/globalthis/LICENSE +21 -0
- package/node_modules/globalthis/README.md +70 -0
- package/node_modules/globalthis/auto.js +3 -0
- package/node_modules/globalthis/implementation.browser.js +11 -0
- package/node_modules/globalthis/implementation.js +3 -0
- package/node_modules/globalthis/index.js +19 -0
- package/node_modules/globalthis/package.json +99 -0
- package/node_modules/globalthis/polyfill.js +10 -0
- package/node_modules/globalthis/shim.js +29 -0
- package/node_modules/globalthis/test/implementation.js +11 -0
- package/node_modules/globalthis/test/index.js +11 -0
- package/node_modules/globalthis/test/native.js +26 -0
- package/node_modules/globalthis/test/shimmed.js +29 -0
- package/node_modules/globalthis/test/tests.js +36 -0
- package/node_modules/gopd/.eslintrc +16 -0
- package/node_modules/gopd/.github/FUNDING.yml +12 -0
- package/node_modules/gopd/CHANGELOG.md +45 -0
- package/node_modules/gopd/LICENSE +21 -0
- package/node_modules/gopd/README.md +40 -0
- package/node_modules/gopd/gOPD.d.ts +1 -0
- package/node_modules/gopd/gOPD.js +4 -0
- package/node_modules/gopd/index.d.ts +5 -0
- package/node_modules/gopd/index.js +15 -0
- package/node_modules/gopd/package.json +77 -0
- package/node_modules/gopd/test/index.js +36 -0
- package/node_modules/gopd/tsconfig.json +9 -0
- package/node_modules/has-property-descriptors/.eslintrc +13 -0
- package/node_modules/has-property-descriptors/.github/FUNDING.yml +12 -0
- package/node_modules/has-property-descriptors/.nycrc +9 -0
- package/node_modules/has-property-descriptors/CHANGELOG.md +35 -0
- package/node_modules/has-property-descriptors/LICENSE +21 -0
- package/node_modules/has-property-descriptors/README.md +43 -0
- package/node_modules/has-property-descriptors/index.js +22 -0
- package/node_modules/has-property-descriptors/package.json +77 -0
- package/node_modules/has-property-descriptors/test/index.js +57 -0
- package/node_modules/is-it-type/License +19 -0
- package/node_modules/is-it-type/README.md +102 -0
- package/node_modules/is-it-type/changelog.md +239 -0
- package/node_modules/is-it-type/dist/cjs/is-it-type.js +173 -0
- package/node_modules/is-it-type/dist/cjs/is-it-type.js.map +1 -0
- package/node_modules/is-it-type/dist/cjs/is-it-type.min.js +2 -0
- package/node_modules/is-it-type/dist/cjs/is-it-type.min.js.map +1 -0
- package/node_modules/is-it-type/dist/esm/is-it-type.js +143 -0
- package/node_modules/is-it-type/dist/esm/is-it-type.js.map +1 -0
- package/node_modules/is-it-type/dist/esm/is-it-type.min.js +2 -0
- package/node_modules/is-it-type/dist/esm/is-it-type.min.js.map +1 -0
- package/node_modules/is-it-type/dist/esm/package.json +3 -0
- package/node_modules/is-it-type/dist/umd/is-it-type.js +450 -0
- package/node_modules/is-it-type/dist/umd/is-it-type.js.map +1 -0
- package/node_modules/is-it-type/dist/umd/is-it-type.min.js +2 -0
- package/node_modules/is-it-type/dist/umd/is-it-type.min.js.map +1 -0
- package/node_modules/is-it-type/es/index.js +8 -0
- package/node_modules/is-it-type/es/package.json +3 -0
- package/node_modules/is-it-type/index.js +10 -0
- package/node_modules/is-it-type/package.json +87 -0
- package/node_modules/is-it-type/src/index.js +169 -0
- package/node_modules/object-keys/.editorconfig +13 -0
- package/node_modules/object-keys/.eslintrc +17 -0
- package/node_modules/object-keys/.travis.yml +277 -0
- package/node_modules/object-keys/CHANGELOG.md +232 -0
- package/node_modules/object-keys/LICENSE +21 -0
- package/node_modules/object-keys/README.md +76 -0
- package/node_modules/object-keys/implementation.js +122 -0
- package/node_modules/object-keys/index.js +32 -0
- package/node_modules/object-keys/isArguments.js +17 -0
- package/node_modules/object-keys/package.json +88 -0
- package/node_modules/object-keys/test/index.js +5 -0
- package/node_modules/simple-invariant/License +19 -0
- package/node_modules/simple-invariant/README.md +64 -0
- package/node_modules/simple-invariant/changelog.md +31 -0
- package/node_modules/simple-invariant/index.js +19 -0
- package/node_modules/simple-invariant/package.json +50 -0
- package/node_modules/yauzl-promise/License +19 -0
- package/node_modules/yauzl-promise/README.md +440 -0
- package/node_modules/yauzl-promise/index.js +10 -0
- package/node_modules/yauzl-promise/lib/entry.js +312 -0
- package/node_modules/yauzl-promise/lib/index.js +160 -0
- package/node_modules/yauzl-promise/lib/reader.js +289 -0
- package/node_modules/yauzl-promise/lib/shared.js +20 -0
- package/node_modules/yauzl-promise/lib/utils.js +105 -0
- package/node_modules/yauzl-promise/lib/zip.js +1224 -0
- package/node_modules/yauzl-promise/package.json +56 -0
- package/package.json +9 -11
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/* --------------------
|
|
2
|
+
* yauzl-promise module
|
|
3
|
+
* `Entry` class
|
|
4
|
+
* ------------------*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
// Modules
|
|
9
|
+
const {createInflateRaw} = require('zlib'),
|
|
10
|
+
{Transform: TransformStream, pipeline} = require('stream'),
|
|
11
|
+
calculateCrc32 = require('@node-rs/crc32').crc32,
|
|
12
|
+
{isObject, isBoolean, isPositiveInteger, isPositiveIntegerOrZero} = require('is-it-type'),
|
|
13
|
+
assert = require('simple-invariant');
|
|
14
|
+
|
|
15
|
+
// Imports
|
|
16
|
+
const {INTERNAL_SYMBOL, uncertainUncompressedSizeEntriesRegistry} = require('./shared.js'),
|
|
17
|
+
{dosDateTimeToDate} = require('./utils.js');
|
|
18
|
+
|
|
19
|
+
// Exports
|
|
20
|
+
|
|
21
|
+
const MAC_LFH_EXTRA_FIELDS_LENGTH = 16,
|
|
22
|
+
FOUR_GIB = 0x100000000; // Math.pow(2, 32)
|
|
23
|
+
|
|
24
|
+
class Entry {
|
|
25
|
+
/**
|
|
26
|
+
* Class representing ZIP file entry.
|
|
27
|
+
* Class is exported in public interface, for purpose of `instanceof` checks, but constructor cannot
|
|
28
|
+
* be called by user. This is enforced by use of private symbol `INTERNAL_SYMBOL`.
|
|
29
|
+
* @class
|
|
30
|
+
* @param {Object} testSymbol - Must be `INTERNAL_SYMBOL`
|
|
31
|
+
* @param {Object} props - Entry properties (see `Zip` class's `_readEntryAt()` method)
|
|
32
|
+
*/
|
|
33
|
+
constructor(testSymbol, props) {
|
|
34
|
+
assert(testSymbol === INTERNAL_SYMBOL, 'Entry class cannot be instantiated directly');
|
|
35
|
+
Object.assign(this, props);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get last modified date as JS `Date` object.
|
|
40
|
+
* @returns {Date} - Date
|
|
41
|
+
*/
|
|
42
|
+
getLastMod() {
|
|
43
|
+
return dosDateTimeToDate(this.lastModDate, this.lastModTime);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get if entry is encrypted.
|
|
48
|
+
* @returns {boolean} - `true` if is encrypted
|
|
49
|
+
*/
|
|
50
|
+
isEncrypted() {
|
|
51
|
+
return (this.generalPurposeBitFlag & 0x1) !== 0; // eslint-disable-line no-bitwise
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Get if file data is compressed.
|
|
56
|
+
* Differs slightly from Yauzl's implementation, which only returns `true` if compression method
|
|
57
|
+
* is deflate. This returns `true` if it's compressed with *any* compression method.
|
|
58
|
+
* @returns {boolean} - `true` if file data is compressed
|
|
59
|
+
*/
|
|
60
|
+
isCompressed() {
|
|
61
|
+
return this.compressionMethod !== 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get readable stream for file data.
|
|
66
|
+
* @async
|
|
67
|
+
* @param {Object} [options] - Options
|
|
68
|
+
* @param {boolean} [options.decompress=true] - `false` to output raw data without decompression
|
|
69
|
+
* @param {boolean} [options.decrypt=true] - `false` to disable decryption if is encrypted
|
|
70
|
+
* and output raw encrypted data
|
|
71
|
+
* @param {boolean} [options.validateCrc32=true] - `false` to skip CRC32 validation
|
|
72
|
+
* @param {number} [options.start] - Start offset (only valid if not decompressing)
|
|
73
|
+
* @param {number} [options.end] - End offset (only valid if not decompressing)
|
|
74
|
+
* @returns {Object} - Readable stream
|
|
75
|
+
*/
|
|
76
|
+
async openReadStream(options) {
|
|
77
|
+
// Validate options
|
|
78
|
+
let decompress, decrypt, validateCrc32, start, end;
|
|
79
|
+
if (options != null) {
|
|
80
|
+
assert(isObject(options), '`options` must be an object if provided');
|
|
81
|
+
const unknownKey = Object.keys(options).find(
|
|
82
|
+
key => !['decompress', 'decrypt', 'validateCrc32', 'start', 'end'].includes(key)
|
|
83
|
+
);
|
|
84
|
+
assert(unknownKey === undefined, `Unknown option '${unknownKey}'`);
|
|
85
|
+
|
|
86
|
+
({decompress, decrypt, validateCrc32, start, end} = options);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (decrypt == null) {
|
|
90
|
+
decrypt = this.isEncrypted();
|
|
91
|
+
} else {
|
|
92
|
+
assert(isBoolean(decrypt), '`options.decrypt` must be a boolean if provided');
|
|
93
|
+
if (!this.isEncrypted()) decrypt = false;
|
|
94
|
+
}
|
|
95
|
+
assert(!decrypt, 'Decryption is not supported');
|
|
96
|
+
|
|
97
|
+
if (decompress == null) {
|
|
98
|
+
decompress = this.isCompressed();
|
|
99
|
+
} else {
|
|
100
|
+
assert(isBoolean(decompress), '`options.decompress` must be a boolean if provided');
|
|
101
|
+
if (!this.isCompressed()) decompress = false;
|
|
102
|
+
}
|
|
103
|
+
assert(
|
|
104
|
+
!decompress || this.compressionMethod === 8,
|
|
105
|
+
`Unsupported compression method ${this.compressionMethod}`
|
|
106
|
+
);
|
|
107
|
+
assert(!decompress || !this.isEncrypted(), 'Cannot decompress encrypted data');
|
|
108
|
+
|
|
109
|
+
if (validateCrc32 == null) {
|
|
110
|
+
validateCrc32 = decompress || !this.isCompressed();
|
|
111
|
+
} else if (validateCrc32 === true) {
|
|
112
|
+
assert(!decompress || !this.isCompressed(), 'Cannot validate CRC32 for uncompressed data');
|
|
113
|
+
} else {
|
|
114
|
+
assert(validateCrc32 === false, '`options.validateCrc32` must be a boolean if provided');
|
|
115
|
+
}
|
|
116
|
+
assert(!validateCrc32 || !this.isEncrypted(), 'Cannot validate CRC32 of encrypted data');
|
|
117
|
+
|
|
118
|
+
if (start == null) {
|
|
119
|
+
start = 0;
|
|
120
|
+
} else if (start !== 0) {
|
|
121
|
+
assert(isPositiveInteger(start), '`options.start` must be a positive integer if provided');
|
|
122
|
+
assert(!decompress, 'Cannot stream a section of file if decompressing');
|
|
123
|
+
assert(!validateCrc32, 'Cannot validate CRC32 for a section of file');
|
|
124
|
+
assert(start <= this.compressedSize, '`start` is after end of file data');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (end == null) {
|
|
128
|
+
end = this.compressedSize;
|
|
129
|
+
} else {
|
|
130
|
+
assert(isPositiveIntegerOrZero(end), '`options.end` must be a positive integer if provided');
|
|
131
|
+
assert(!decompress, 'Cannot stream a section of file if decompressing');
|
|
132
|
+
assert(!validateCrc32, 'Cannot validate CRC32 for a section of file');
|
|
133
|
+
assert(end <= this.compressedSize, '`end` is after end of file data');
|
|
134
|
+
assert(end >= start, '`end` is before `start`');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Read Local File Header.
|
|
138
|
+
// Have already checked this read is in bounds in `readEntry()`.
|
|
139
|
+
const buffer = await this.zip.reader.read(this.fileHeaderOffset, 30);
|
|
140
|
+
// Bytes 0-3: Local File Header signature = 0x04034b50
|
|
141
|
+
assert(buffer.readUInt32LE(0) === 0x04034b50, 'Invalid Local File Header signature');
|
|
142
|
+
// All this should be redundant
|
|
143
|
+
// Bytes 4-5: Version needed to extract (minimum)
|
|
144
|
+
// Bytes 6-7: General Purpose Bit Flag
|
|
145
|
+
// Bytes 8-9: Compression method
|
|
146
|
+
// Bytes 10-11: File last modification time
|
|
147
|
+
// Bytes 12-13: File last modification date
|
|
148
|
+
// Bytes 14-17: CRC32
|
|
149
|
+
const localCrc32 = buffer.readUInt32LE(14);
|
|
150
|
+
// Bytes 18-21: Compressed size
|
|
151
|
+
const localCompressedSize = buffer.readUInt32LE(18);
|
|
152
|
+
// Bytes 22-23: Uncompressed size
|
|
153
|
+
const localUncompressedSize = buffer.readUInt32LE(22);
|
|
154
|
+
// Bytes 26-27: Filename length
|
|
155
|
+
const filenameLength = buffer.readUInt16LE(26);
|
|
156
|
+
// Bytes 28-29: Extra Fields length
|
|
157
|
+
const extraFieldsLength = buffer.readUInt16LE(28);
|
|
158
|
+
// Bytes 30-... - Filename + Extra Fields
|
|
159
|
+
|
|
160
|
+
const fileDataOffset = this.fileHeaderOffset + 30 + filenameLength + extraFieldsLength;
|
|
161
|
+
this.fileDataOffset = fileDataOffset;
|
|
162
|
+
|
|
163
|
+
if (this.zip.isMacArchive || this.zip.isMaybeMacArchive) {
|
|
164
|
+
// Check properties match Mac ZIP signature
|
|
165
|
+
const matchesMacSignature = localCrc32 === 0
|
|
166
|
+
&& localCompressedSize === 0
|
|
167
|
+
&& localUncompressedSize === 0
|
|
168
|
+
&& filenameLength === this.filenameLength
|
|
169
|
+
&& extraFieldsLength === this.extraFields.length * MAC_LFH_EXTRA_FIELDS_LENGTH;
|
|
170
|
+
if (this.zip.isMacArchive) {
|
|
171
|
+
assert(matchesMacSignature, 'Misidentified Mac OS Archive Utility ZIP');
|
|
172
|
+
} else if (!matchesMacSignature) {
|
|
173
|
+
// Doesn't fit signature of Mac OS Archive Utility ZIP, so can't be one
|
|
174
|
+
this.zip._setAsNotMacArchive();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (this.compressedSize !== 0) {
|
|
179
|
+
assert(
|
|
180
|
+
fileDataOffset + this.compressedSize <= this.zip.footerOffset,
|
|
181
|
+
'File data overflows file bounds: '
|
|
182
|
+
+ `${fileDataOffset} + ${this.compressedSize} > ${this.zip.footerOffset}`
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Get stream
|
|
187
|
+
let stream = this.zip.reader.createReadStream(fileDataOffset + start, end - start);
|
|
188
|
+
|
|
189
|
+
// Pipe stream through decompress, CRC32 validation, and/or uncompressed size check transform streams
|
|
190
|
+
const streams = [stream];
|
|
191
|
+
if (decompress) {
|
|
192
|
+
streams.push(createInflateRaw());
|
|
193
|
+
// eslint-disable-next-line no-use-before-define
|
|
194
|
+
if (this.zip.validateEntrySizes) streams.push(new ValidateUncompressedSizeStream(this));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// eslint-disable-next-line no-use-before-define
|
|
198
|
+
if (validateCrc32) streams.push(new ValidateCrc32Stream(this.crc32));
|
|
199
|
+
|
|
200
|
+
if (streams.length > 1) {
|
|
201
|
+
pipeline(streams, () => {});
|
|
202
|
+
stream = streams[streams.length - 1];
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Return stream
|
|
206
|
+
return stream;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
module.exports = Entry;
|
|
211
|
+
|
|
212
|
+
class ValidateUncompressedSizeStream extends TransformStream {
|
|
213
|
+
/**
|
|
214
|
+
* Transform stream to compare size of uncompressed stream to expected.
|
|
215
|
+
* If `entry.uncompressedSizeIsCertain === false`, only checks actual byte count is accurate
|
|
216
|
+
* in lower 32 bits. `entry.uncompressedSize` can be inaccurate in faulty Mac OS ZIPs where
|
|
217
|
+
* uncompressed size reported by ZIP is truncated to lower 32 bits.
|
|
218
|
+
* If it proves inaccurate, `entry.uncompressedSize` is updated,
|
|
219
|
+
* and ZIP is flagged as being Mac OS ZIP if it isn't already.
|
|
220
|
+
* @class
|
|
221
|
+
* @param {Object} entry - Entry object
|
|
222
|
+
*/
|
|
223
|
+
constructor(entry) {
|
|
224
|
+
super();
|
|
225
|
+
this.byteCount = 0;
|
|
226
|
+
this.expectedByteCount = entry.uncompressedSize;
|
|
227
|
+
this.entry = entry;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
_transform(chunk, encoding, cb) {
|
|
231
|
+
this.byteCount += chunk.length;
|
|
232
|
+
if (this.byteCount > this.expectedByteCount) {
|
|
233
|
+
if (this.entry.uncompressedSizeIsCertain) {
|
|
234
|
+
cb(new Error(
|
|
235
|
+
`Too many bytes in the stream. Expected ${this.expectedByteCount}, `
|
|
236
|
+
+ `got at least ${this.byteCount}.`
|
|
237
|
+
));
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Entry must be at least 4 GiB larger. ZIP must be faulty Mac OS ZIP.
|
|
242
|
+
if (this.entry.uncompressedSize === this.expectedByteCount) {
|
|
243
|
+
this.expectedByteCount += FOUR_GIB;
|
|
244
|
+
this.entry.uncompressedSize = this.expectedByteCount;
|
|
245
|
+
const {zip} = this.entry;
|
|
246
|
+
if (!zip.isMacArchive) {
|
|
247
|
+
if (!zip.isMaybeMacArchive) {
|
|
248
|
+
// It shouldn't be possible for `isMaybeMacArchive` to be `false`.
|
|
249
|
+
// But check here as failsafe, as the logic around handling maybe-Mac ZIPs is complex.
|
|
250
|
+
// If there's a mistake in logic which does cause us to get here, `_setAsMacArchive()`
|
|
251
|
+
// below could throw an error which would crash the whole process. Contain the damage.
|
|
252
|
+
cb(new Error('Logic failure. Please raise an issue.'));
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
zip._setAsMacArchive(zip.numEntriesRead, zip._entryCursor);
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
// Same entry must be being streamed simultaneously on another "thread",
|
|
259
|
+
// and other stream overtook this one, and already increased size
|
|
260
|
+
this.expectedByteCount = this.entry.uncompressedSize;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
cb(null, chunk);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
_flush(cb) {
|
|
268
|
+
if (this.byteCount < this.expectedByteCount) {
|
|
269
|
+
cb(new Error(
|
|
270
|
+
`Not enough bytes in the stream. Expected ${this.expectedByteCount}, got only ${this.byteCount}.`
|
|
271
|
+
));
|
|
272
|
+
} else {
|
|
273
|
+
if (!this.entry.uncompressedSizeIsCertain) {
|
|
274
|
+
// Uncompressed size was uncertain, but is now known.
|
|
275
|
+
// Record size as certain, and remove from list of uncertain-sized entries.
|
|
276
|
+
this.entry.uncompressedSizeIsCertain = true;
|
|
277
|
+
const ref = this.entry._ref;
|
|
278
|
+
if (ref) {
|
|
279
|
+
this.entry._ref = null;
|
|
280
|
+
this.entry.zip._uncertainUncompressedSizeEntryRefs.delete(ref);
|
|
281
|
+
uncertainUncompressedSizeEntriesRegistry.unregister(ref);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
cb();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Transform stream to calculate CRC32 of data and compare to expected.
|
|
291
|
+
* @class
|
|
292
|
+
*/
|
|
293
|
+
class ValidateCrc32Stream extends TransformStream {
|
|
294
|
+
constructor(crc32) {
|
|
295
|
+
super();
|
|
296
|
+
this.crc32 = 0;
|
|
297
|
+
this.expectedCrc32 = crc32;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
_transform(chunk, encoding, cb) {
|
|
301
|
+
this.crc32 = calculateCrc32(chunk, this.crc32);
|
|
302
|
+
cb(null, chunk);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
_flush(cb) {
|
|
306
|
+
if (this.crc32 !== this.expectedCrc32) {
|
|
307
|
+
cb(new Error(`CRC32 validation failed. Expected ${this.expectedCrc32}, received ${this.crc32}.`));
|
|
308
|
+
} else {
|
|
309
|
+
cb();
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/* --------------------
|
|
2
|
+
* yauzl-promise module
|
|
3
|
+
* Entry point
|
|
4
|
+
* ------------------*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
// Modules
|
|
9
|
+
const {fstat} = require('fs'),
|
|
10
|
+
{promisify} = require('util'),
|
|
11
|
+
{isObject, isString, isBoolean, isInteger, isPositiveInteger} = require('is-it-type'),
|
|
12
|
+
assert = require('simple-invariant');
|
|
13
|
+
|
|
14
|
+
const fstatAsync = promisify(fstat);
|
|
15
|
+
|
|
16
|
+
// Imports
|
|
17
|
+
const Zip = require('./zip.js'),
|
|
18
|
+
Entry = require('./entry.js'),
|
|
19
|
+
{Reader, FileReader, FdReader, BufferReader} = require('./reader.js'),
|
|
20
|
+
{dosDateTimeToDate, validateFilename} = require('./utils.js'),
|
|
21
|
+
{INTERNAL_SYMBOL} = require('./shared.js');
|
|
22
|
+
|
|
23
|
+
// Exports
|
|
24
|
+
|
|
25
|
+
module.exports = {
|
|
26
|
+
Zip,
|
|
27
|
+
Entry,
|
|
28
|
+
open,
|
|
29
|
+
fromFd,
|
|
30
|
+
fromBuffer,
|
|
31
|
+
fromReader,
|
|
32
|
+
Reader,
|
|
33
|
+
dosDateTimeToDate,
|
|
34
|
+
validateFilename
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Create `Zip` from file.
|
|
39
|
+
* @param {string} path - ZIP file path
|
|
40
|
+
* @param {Object} [options] - Options
|
|
41
|
+
* @param {boolean} [options.decodeStrings=true] - Decode filenames and comments to strings
|
|
42
|
+
* @param {boolean} [options.validateEntrySizes=true] - Validate entry sizes
|
|
43
|
+
* @param {boolean} [options.validateFilenames=true] - Validate filenames
|
|
44
|
+
* @param {boolean} [options.strictFilenames=false] - Don't allow backslashes (`\`) in filenames
|
|
45
|
+
* @param {boolean} [options.supportMacArchive=true] - Support Mac OS Archive Utility faulty ZIP files
|
|
46
|
+
* @returns {Zip} - `Zip` class instance
|
|
47
|
+
*/
|
|
48
|
+
async function open(path, options) {
|
|
49
|
+
assert(isString(path), '`path` must be a string');
|
|
50
|
+
options = validateOptions(options);
|
|
51
|
+
|
|
52
|
+
const reader = new FileReader(path);
|
|
53
|
+
await reader.open();
|
|
54
|
+
const {size} = await fstatAsync(reader.fd);
|
|
55
|
+
|
|
56
|
+
const zip = new Zip(INTERNAL_SYMBOL, reader, size, options);
|
|
57
|
+
try {
|
|
58
|
+
await zip._init();
|
|
59
|
+
} catch (err) {
|
|
60
|
+
await reader.close();
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
63
|
+
return zip;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Create `Zip` from file descriptor.
|
|
68
|
+
* @param {number} fd - ZIP file descriptor
|
|
69
|
+
* @param {Object} [options] - Options
|
|
70
|
+
* @param {boolean} [options.decodeStrings=true] - Decode filenames and comments to strings
|
|
71
|
+
* @param {boolean} [options.validateEntrySizes=true] - Validate entry sizes
|
|
72
|
+
* @param {boolean} [options.validateFilenames=true] - Validate filenames
|
|
73
|
+
* @param {boolean} [options.strictFilenames=false] - Don't allow backslashes (`\`) in filenames
|
|
74
|
+
* @param {boolean} [options.supportMacArchive=true] - Support Mac OS Archive Utility faulty ZIP files
|
|
75
|
+
* @returns {Zip} - `Zip` class instance
|
|
76
|
+
*/
|
|
77
|
+
async function fromFd(fd, options) {
|
|
78
|
+
assert(isInteger(fd), '`fd` must be an integer');
|
|
79
|
+
options = validateOptions(options);
|
|
80
|
+
|
|
81
|
+
const reader = new FdReader(fd);
|
|
82
|
+
await reader.open();
|
|
83
|
+
const {size} = await fstatAsync(fd);
|
|
84
|
+
|
|
85
|
+
const zip = new Zip(INTERNAL_SYMBOL, reader, size, options);
|
|
86
|
+
await zip._init();
|
|
87
|
+
return zip;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Create `Zip` from `Buffer`.
|
|
92
|
+
* @param {Buffer} buffer - Buffer containing ZIP file
|
|
93
|
+
* @param {Object} [options] - Options
|
|
94
|
+
* @param {boolean} [options.decodeStrings=true] - Decode filenames and comments to strings
|
|
95
|
+
* @param {boolean} [options.validateEntrySizes=true] - Validate entry sizes
|
|
96
|
+
* @param {boolean} [options.validateFilenames=true] - Validate filenames
|
|
97
|
+
* @param {boolean} [options.strictFilenames=false] - Don't allow backslashes (`\`) in filenames
|
|
98
|
+
* @param {boolean} [options.supportMacArchive=true] - Support Mac OS Archive Utility faulty ZIP files
|
|
99
|
+
* @returns {Zip} - `Zip` class instance
|
|
100
|
+
*/
|
|
101
|
+
async function fromBuffer(buffer, options) {
|
|
102
|
+
assert(buffer instanceof Buffer, '`buffer` must be a Buffer');
|
|
103
|
+
options = validateOptions(options);
|
|
104
|
+
|
|
105
|
+
const reader = new BufferReader(buffer);
|
|
106
|
+
await reader.open();
|
|
107
|
+
const zip = new Zip(INTERNAL_SYMBOL, reader, buffer.length, options);
|
|
108
|
+
await zip._init();
|
|
109
|
+
return zip;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Create `Zip` from `Reader`.
|
|
114
|
+
* @param {Object} reader - `Reader` object
|
|
115
|
+
* @param {number} size - Size of ZIP file
|
|
116
|
+
* @param {Object} [options] - Options
|
|
117
|
+
* @param {boolean} [options.decodeStrings=true] - Decode filenames and comments to strings
|
|
118
|
+
* @param {boolean} [options.validateEntrySizes=true] - Validate entry sizes
|
|
119
|
+
* @param {boolean} [options.validateFilenames=true] - Validate filenames
|
|
120
|
+
* @param {boolean} [options.strictFilenames=false] - Don't allow backslashes (`\`) in filenames
|
|
121
|
+
* @param {boolean} [options.supportMacArchive=true] - Support Mac OS Archive Utility faulty ZIP files
|
|
122
|
+
* @returns {Zip} - `Zip` class instance
|
|
123
|
+
*/
|
|
124
|
+
async function fromReader(reader, size, options) {
|
|
125
|
+
assert(reader instanceof Reader, '`reader` must be an instance of `Reader` class');
|
|
126
|
+
assert(isPositiveInteger(size), '`size` must be a positive integer');
|
|
127
|
+
options = validateOptions(options);
|
|
128
|
+
|
|
129
|
+
await reader.open();
|
|
130
|
+
const zip = new Zip(INTERNAL_SYMBOL, reader, size, options);
|
|
131
|
+
await zip._init();
|
|
132
|
+
return zip;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Validate and conform `Zip` creation options.
|
|
137
|
+
* @param {Object} [inputOptions] - Input options object
|
|
138
|
+
* @returns {Object} - Conformed options object
|
|
139
|
+
*/
|
|
140
|
+
function validateOptions(inputOptions) {
|
|
141
|
+
const options = {
|
|
142
|
+
decodeStrings: true,
|
|
143
|
+
validateEntrySizes: true,
|
|
144
|
+
validateFilenames: true,
|
|
145
|
+
strictFilenames: false,
|
|
146
|
+
supportMacArchive: true
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
if (inputOptions != null) {
|
|
150
|
+
assert(isObject(inputOptions), '`options` must be an object if provided');
|
|
151
|
+
|
|
152
|
+
for (const [key, value] of Object.entries(inputOptions)) {
|
|
153
|
+
assert(Object.hasOwn(options, key), `Unknown option '${key}'`);
|
|
154
|
+
assert(isBoolean(value), `\`options.${key}\` must be a boolean if provided`);
|
|
155
|
+
options[key] = value;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return options;
|
|
160
|
+
}
|