neozip-cli 0.70.0-alpha
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/CHANGELOG.md +72 -0
- package/DOCUMENTATION.md +194 -0
- package/LICENSE +22 -0
- package/README.md +504 -0
- package/WHY_NEOZIP.md +212 -0
- package/bin/neolist +16 -0
- package/bin/neounzip +16 -0
- package/bin/neozip +15 -0
- package/dist/neozipkit-bundles/blockchain.js +13091 -0
- package/dist/neozipkit-bundles/browser.js +5733 -0
- package/dist/neozipkit-bundles/core.js +3766 -0
- package/dist/neozipkit-bundles/server.js +14996 -0
- package/dist/neozipkit-wrappers/blockchain/core/contracts.js +16 -0
- package/dist/neozipkit-wrappers/blockchain/index.js +2 -0
- package/dist/neozipkit-wrappers/core/ZipDecompress.js +2 -0
- package/dist/neozipkit-wrappers/core/components/HashCalculator.js +2 -0
- package/dist/neozipkit-wrappers/core/components/Logger.js +2 -0
- package/dist/neozipkit-wrappers/core/constants/Errors.js +2 -0
- package/dist/neozipkit-wrappers/core/constants/Headers.js +2 -0
- package/dist/neozipkit-wrappers/core/encryption/ZipCrypto.js +7 -0
- package/dist/neozipkit-wrappers/core/index.js +3 -0
- package/dist/neozipkit-wrappers/index.js +13 -0
- package/dist/neozipkit-wrappers/server/index.js +2 -0
- package/dist/src/config/ConfigSetup.js +455 -0
- package/dist/src/config/ConfigStore.js +373 -0
- package/dist/src/config/ConfigWizard.js +453 -0
- package/dist/src/config/WalletConfig.js +372 -0
- package/dist/src/exit-codes.js +210 -0
- package/dist/src/index.js +141 -0
- package/dist/src/neolist.js +1194 -0
- package/dist/src/neounzip.js +2177 -0
- package/dist/src/neozip/CommentManager.js +240 -0
- package/dist/src/neozip/blockchain.js +383 -0
- package/dist/src/neozip/createZip.js +2273 -0
- package/dist/src/neozip/file-operations.js +920 -0
- package/dist/src/neozip/types.js +6 -0
- package/dist/src/neozip/user-interaction.js +256 -0
- package/dist/src/neozip/utils.js +96 -0
- package/dist/src/neozip.js +785 -0
- package/dist/src/server/CommentManager.js +240 -0
- package/dist/src/version.js +59 -0
- package/env.example +101 -0
- package/package.json +175 -0
|
@@ -0,0 +1,3766 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
6
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
// neozipkit/dist/core/constants/Errors.js
|
|
10
|
+
var require_Errors = __commonJS({
|
|
11
|
+
"neozipkit/dist/core/constants/Errors.js"(exports2) {
|
|
12
|
+
"use strict";
|
|
13
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
14
|
+
exports2.default = {
|
|
15
|
+
/* Header error messages */
|
|
16
|
+
INVALID_LOC: "Invalid LOC header (bad signature)",
|
|
17
|
+
INVALID_CEN: "Invalid CEN header (bad signature)",
|
|
18
|
+
INVALID_END: "Invalid END header (bad signature)",
|
|
19
|
+
/* ZipEntry error messages*/
|
|
20
|
+
NO_DATA: "Nothing to decompress",
|
|
21
|
+
FILE_IN_THE_WAY: "There is a file in the way: %s",
|
|
22
|
+
UNKNOWN_METHOD: "Invalid/unsupported compression method",
|
|
23
|
+
/* Encryption Errors */
|
|
24
|
+
STRONG_ENCRYPT_UNSUPPORTED: "Strong Encryption is not supported",
|
|
25
|
+
/* Timestamp error messages */
|
|
26
|
+
INVALID_TIMESTAMP: "Invalid timestamp",
|
|
27
|
+
TIMESTAMP_FAILED: "Failed to create the timestamp",
|
|
28
|
+
/* Inflater error messages */
|
|
29
|
+
AVAIL_DATA: "inflate::Available inflate data did not terminate",
|
|
30
|
+
INVALID_DISTANCE: "inflate::Invalid literal/length or distance code in fixed or dynamic block",
|
|
31
|
+
TO_MANY_CODES: "inflate::Dynamic block code description: too many length or distance codes",
|
|
32
|
+
INVALID_REPEAT_LEN: "inflate::Dynamic block code description: repeat more than specified lengths",
|
|
33
|
+
INVALID_REPEAT_FIRST: "inflate::Dynamic block code description: repeat lengths with no first length",
|
|
34
|
+
INCOMPLETE_CODES: "inflate::Dynamic block code description: code lengths codes incomplete",
|
|
35
|
+
INVALID_DYN_DISTANCE: "inflate::Dynamic block code description: invalid distance code lengths",
|
|
36
|
+
INVALID_CODES_LEN: "inflate::Dynamic block code description: invalid literal/length code lengths",
|
|
37
|
+
INVALID_STORE_BLOCK: "inflate::Stored block length did not match one's complement",
|
|
38
|
+
INVALID_BLOCK_TYPE: "inflate::Invalid block type (type == 3)",
|
|
39
|
+
/* Extract error messages */
|
|
40
|
+
INVALID_CMP_DATA_LENGTH: "Compressed data length does not match the expected length",
|
|
41
|
+
EXTRACT_FAILED: "Failed to extract file",
|
|
42
|
+
INVALID_CRC: "CRC32 checksum does not match the expected value",
|
|
43
|
+
UNKNOWN_SHA256: "The SHA-256 hash has not been saved",
|
|
44
|
+
INVALID_SHA256: "The SHA-256 hash does not match the expected value",
|
|
45
|
+
/* NEO-ZIP error messages */
|
|
46
|
+
CANT_EXTRACT_FILE: "Could not extract the file",
|
|
47
|
+
CANT_OVERRIDE: "Target file already exists",
|
|
48
|
+
NO_ZIP: "No zip file was loaded",
|
|
49
|
+
NO_ENTRY: "Entry doesn't exist",
|
|
50
|
+
DIRECTORY_CONTENT_ERROR: "A directory cannot have content",
|
|
51
|
+
FILE_NOT_FOUND: "File not found: %s",
|
|
52
|
+
NOT_IMPLEMENTED: "Not implemented",
|
|
53
|
+
INVALID_FILENAME: "Invalid filename",
|
|
54
|
+
INVALID_FORMAT: "Invalid or unsupported zip format. No END header found",
|
|
55
|
+
// NeoZipKit error messages
|
|
56
|
+
NO_STREAM_SUPPORT: "Streams are not supported in this environment",
|
|
57
|
+
NO_BLOB_SUPPORT: "Blobs are not supported in this environment",
|
|
58
|
+
NO_FILE_READER_SUPPORT: "FileReader is not supported in this environment",
|
|
59
|
+
// Create Zip error messages
|
|
60
|
+
NO_FILES: "No files added, Zip file not created",
|
|
61
|
+
DATATYPE_STRING_UNSUPPORTED: "The String type is not supported by this platform.",
|
|
62
|
+
DATATYPE_ARRAY_UNSUPPORTED: "The Array type is not supported by this platform.",
|
|
63
|
+
DATATYPE_BUFFER_UNSUPPORTED: "The Buffer type is not supported by this platform.",
|
|
64
|
+
DATATYPE_BLOB_UNSUPPORTED: "The Blob type is not supported by this platform.",
|
|
65
|
+
DATATYPE_U8ARRAY_UNSUPPORTED: "The uint8Array type is not supported by this platform.",
|
|
66
|
+
DATATYPE_ARRAYBUFFER_UNSUPPORTED: "The ArrayBuffer type is not supported by this platform.",
|
|
67
|
+
DATATYPE_UNSUPPORTED: "Unsupported input type.",
|
|
68
|
+
COMPRESS_FAILED: "Failed to compress data",
|
|
69
|
+
COMPRESSION_ERROR: "Error occurred during compression",
|
|
70
|
+
DECOMPRESSION_ERROR: "Error occurred during decompression",
|
|
71
|
+
ENCRYPT_FAILED: "Encryption failed"
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// neozipkit/dist/core/constants/Headers.js
|
|
77
|
+
var require_Headers = __commonJS({
|
|
78
|
+
"neozipkit/dist/core/constants/Headers.js"(exports2) {
|
|
79
|
+
"use strict";
|
|
80
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
81
|
+
exports2.DOS_FILE_ATTR = exports2.FILE_SYSTEM = exports2.HDR_ID = exports2.EXTENSIBLE_DATA_FIELDS = exports2.GP_FLAG = exports2.CMP_METHOD = exports2.ZIP64_CENTRAL_END = exports2.ZIP64_CENTRAL_DIR = exports2.CENTRAL_END = exports2.CENTRAL_DIR = exports2.DATA_DESC = exports2.ENCRYPT_HDR_SIZE = exports2.LOCAL_HDR = exports2.TOKENIZED_METADATA = exports2.TIMESTAMP_METADATA = exports2.TIMESTAMP_SUBMITTED = exports2.DATA_DESCRIPTOR = exports2.ZIP64_CENTRAL_DIRECTORY_END = exports2.ZIP64_CENTRAL_DIRECTORY_LOCATOR = exports2.CENTRAL_DIRECTORY_END = exports2.CENTRAL_FILE_HEADER = exports2.LOCAL_FILE_HEADER = void 0;
|
|
82
|
+
exports2.LOCAL_FILE_HEADER = "PK";
|
|
83
|
+
exports2.CENTRAL_FILE_HEADER = "PK";
|
|
84
|
+
exports2.CENTRAL_DIRECTORY_END = "PK";
|
|
85
|
+
exports2.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x07";
|
|
86
|
+
exports2.ZIP64_CENTRAL_DIRECTORY_END = "PK";
|
|
87
|
+
exports2.DATA_DESCRIPTOR = "PK\x07\b";
|
|
88
|
+
exports2.TIMESTAMP_SUBMITTED = "META-INF/TS-SUBMIT.OTS";
|
|
89
|
+
exports2.TIMESTAMP_METADATA = "META-INF/TIMESTAMP.OTS";
|
|
90
|
+
exports2.TOKENIZED_METADATA = "META-INF/NZIP.TOKEN";
|
|
91
|
+
exports2.LOCAL_HDR = {
|
|
92
|
+
SIZE: 30,
|
|
93
|
+
// LOC header size in bytes
|
|
94
|
+
SIGNATURE: 67324752,
|
|
95
|
+
// "PK\003\004"
|
|
96
|
+
VER_EXTRACT: 4,
|
|
97
|
+
// version needed to extract
|
|
98
|
+
FLAGS: 6,
|
|
99
|
+
// general purpose bit flag
|
|
100
|
+
COMPRESSION: 8,
|
|
101
|
+
// compression method
|
|
102
|
+
TIMEDATE_DOS: 10,
|
|
103
|
+
// modification time (2 bytes time, 2 bytes date)
|
|
104
|
+
CRC: 14,
|
|
105
|
+
// uncompressed file crc-32 value
|
|
106
|
+
CMP_SIZE: 18,
|
|
107
|
+
// compressed size
|
|
108
|
+
UNCMP_SIZE: 22,
|
|
109
|
+
// uncompressed size
|
|
110
|
+
FNAME_LEN: 26,
|
|
111
|
+
// filename length
|
|
112
|
+
EXTRA_LEN: 28
|
|
113
|
+
// extra field length
|
|
114
|
+
};
|
|
115
|
+
exports2.ENCRYPT_HDR_SIZE = 12;
|
|
116
|
+
exports2.DATA_DESC = {
|
|
117
|
+
SIGNATURE: 134695760,
|
|
118
|
+
// "PK\007\008"
|
|
119
|
+
SIZE: 16,
|
|
120
|
+
// EXT header size in bytes
|
|
121
|
+
CRC: 4,
|
|
122
|
+
// uncompressed file crc-32 value (offset)
|
|
123
|
+
CMP_SIZE: 8,
|
|
124
|
+
// compressed size (offset)
|
|
125
|
+
UNCMP_SIZE: 12
|
|
126
|
+
// uncompressed size
|
|
127
|
+
};
|
|
128
|
+
exports2.CENTRAL_DIR = {
|
|
129
|
+
SIZE: 46,
|
|
130
|
+
// Central directory header size
|
|
131
|
+
SIGNATURE: 33639248,
|
|
132
|
+
// "PK\001\002"
|
|
133
|
+
VER_MADE: 4,
|
|
134
|
+
// version made by
|
|
135
|
+
VER_EXT: 6,
|
|
136
|
+
// version needed to extract
|
|
137
|
+
FLAGS: 8,
|
|
138
|
+
// encrypt, decrypt flags
|
|
139
|
+
CMP_METHOD: 10,
|
|
140
|
+
// compression method
|
|
141
|
+
TIMEDATE_DOS: 12,
|
|
142
|
+
// DOS modification time (2 bytes time, 2 bytes date)
|
|
143
|
+
CRC: 16,
|
|
144
|
+
// uncompressed file crc-32 value
|
|
145
|
+
CMP_SIZE: 20,
|
|
146
|
+
// compressed size
|
|
147
|
+
UNCMP_SIZE: 24,
|
|
148
|
+
// uncompressed size
|
|
149
|
+
FNAME_LEN: 28,
|
|
150
|
+
// filename length
|
|
151
|
+
EXTRA_LEN: 30,
|
|
152
|
+
// extra field length
|
|
153
|
+
COMMENT_LEN: 32,
|
|
154
|
+
// file comment length
|
|
155
|
+
DISK_NUM: 34,
|
|
156
|
+
// volume number start
|
|
157
|
+
INT_FILE_ATTR: 36,
|
|
158
|
+
// internal file attributes
|
|
159
|
+
EXT_FILE_ATTR: 38,
|
|
160
|
+
// external file attributes (host system dependent)
|
|
161
|
+
LOCAL_HDR_OFFSET: 42
|
|
162
|
+
// LOC header offset
|
|
163
|
+
};
|
|
164
|
+
exports2.CENTRAL_END = {
|
|
165
|
+
SIZE: 22,
|
|
166
|
+
// END header size
|
|
167
|
+
SIGNATURE: 101010256,
|
|
168
|
+
// "PK\005\006"
|
|
169
|
+
VOL_NUM: 4,
|
|
170
|
+
// number of this disk
|
|
171
|
+
VOLDIR_START: 6,
|
|
172
|
+
// number of the volume/disk with start of the Central Directory
|
|
173
|
+
VOL_ENTRIES: 8,
|
|
174
|
+
// number of entries on this volume/disk
|
|
175
|
+
TOTAL_ENTRIES: 10,
|
|
176
|
+
// total number of entries on this disk
|
|
177
|
+
CENTRAL_DIR_SIZE: 12,
|
|
178
|
+
// central directory size in bytes
|
|
179
|
+
CENTRAL_DIR_OFFSET: 16,
|
|
180
|
+
// offset of first CEN header
|
|
181
|
+
ZIP_COMMENT_LEN: 20
|
|
182
|
+
// zip file comment length
|
|
183
|
+
};
|
|
184
|
+
exports2.ZIP64_CENTRAL_DIR = {
|
|
185
|
+
SIGNATURE: 101075792,
|
|
186
|
+
// zip64 signature, "PK\006\006"
|
|
187
|
+
SIZE: 56,
|
|
188
|
+
// zip64 record minimum size
|
|
189
|
+
LEAD: 12,
|
|
190
|
+
// leading bytes at the start of the record, not counted by the value stored in ZIP64SIZE
|
|
191
|
+
SIZE_FIELD: 4,
|
|
192
|
+
// zip64 size of the central directory record
|
|
193
|
+
VER_MADEBY: 12,
|
|
194
|
+
// zip64 version made by
|
|
195
|
+
VER_NEEDED: 14,
|
|
196
|
+
// zip64 version needed to extract
|
|
197
|
+
VOL_NUM: 16,
|
|
198
|
+
// zip64 number of this disk
|
|
199
|
+
VOLDIR_START: 20,
|
|
200
|
+
// number of the disk with the start of the record directory
|
|
201
|
+
VOL_ENTRIES: 24,
|
|
202
|
+
// number of entries on this disk
|
|
203
|
+
TOTAL_ENTRIES: 32,
|
|
204
|
+
// total number of entries
|
|
205
|
+
CENTRAL_DIR_SIZE: 40,
|
|
206
|
+
// zip64 central directory size in bytes
|
|
207
|
+
CENTRAL_DIR_OFFSET: 48,
|
|
208
|
+
// offset of start of central directory with respect to the starting disk number
|
|
209
|
+
EXTRA_FIELD: 56
|
|
210
|
+
// extensible data sector
|
|
211
|
+
};
|
|
212
|
+
exports2.ZIP64_CENTRAL_END = {
|
|
213
|
+
SIZE: 20,
|
|
214
|
+
// zip64 END header size
|
|
215
|
+
SIGNATURE: 117853008,
|
|
216
|
+
// zip64 Locator signature, "PK\006\007"
|
|
217
|
+
VOL_NUM: 4,
|
|
218
|
+
// number of the disk with the start of the zip64
|
|
219
|
+
CENTRAL_DIR_OFFSET: 8,
|
|
220
|
+
// relative offset of the zip64 end of central directory
|
|
221
|
+
TOTAL_DISKS: 16
|
|
222
|
+
// total number of disks
|
|
223
|
+
};
|
|
224
|
+
exports2.CMP_METHOD = {
|
|
225
|
+
STORED: 0,
|
|
226
|
+
// no compression
|
|
227
|
+
SHRUNK: 1,
|
|
228
|
+
// shrunk
|
|
229
|
+
REDUCED1: 2,
|
|
230
|
+
// reduced with compression factor 1
|
|
231
|
+
REDUCED2: 3,
|
|
232
|
+
// reduced with compression factor 2
|
|
233
|
+
REDUCED3: 4,
|
|
234
|
+
// reduced with compression factor 3
|
|
235
|
+
REDUCED4: 5,
|
|
236
|
+
// reduced with compression factor 4
|
|
237
|
+
IMPLODED: 6,
|
|
238
|
+
// imploded
|
|
239
|
+
DEFLATED: 8,
|
|
240
|
+
// deflated
|
|
241
|
+
ENHANCED_DEFLATE: 9,
|
|
242
|
+
// enhanced deflated
|
|
243
|
+
BZIP2: 12,
|
|
244
|
+
// compressed using BZIP2
|
|
245
|
+
LZMA: 14,
|
|
246
|
+
// LZMA
|
|
247
|
+
IBM_TERSE: 18,
|
|
248
|
+
// compressed using IBM TERSE
|
|
249
|
+
IBM_LZ77: 19,
|
|
250
|
+
// IBM LZ77
|
|
251
|
+
ZSTD: 93,
|
|
252
|
+
// Zstandard compression
|
|
253
|
+
AES_ENCRYPT: 99
|
|
254
|
+
// WinZIP AES encryption method
|
|
255
|
+
};
|
|
256
|
+
exports2.GP_FLAG = {
|
|
257
|
+
ENCRYPTED: 1,
|
|
258
|
+
// Bit 0: encrypted file
|
|
259
|
+
COMPRESSION1: 2,
|
|
260
|
+
// Bit 1, compression option
|
|
261
|
+
COMPRESSION2: 4,
|
|
262
|
+
// Bit 2, compression option
|
|
263
|
+
DATA_DESC: 8,
|
|
264
|
+
// Bit 3, data descriptor
|
|
265
|
+
ENHANCED_DEFLATE: 16,
|
|
266
|
+
// Bit 4, enhanced deflating
|
|
267
|
+
PATCHED: 32,
|
|
268
|
+
// Bit 5, indicates that the file is compressed patched data.
|
|
269
|
+
STRONG_ENCRYPT: 64,
|
|
270
|
+
// Bit 6, strong encryption (patented)
|
|
271
|
+
// Bits 7-10: Currently unused.
|
|
272
|
+
EFS: 2048,
|
|
273
|
+
// Bit 11: Language encoding flag (EFS)
|
|
274
|
+
// Bit 12: Reserved by PKWARE for enhanced compression.
|
|
275
|
+
// Bit 13: encrypted the Central Directory (patented).
|
|
276
|
+
// Bits 14-15: Reserved by PKWARE.
|
|
277
|
+
MASK: 4096
|
|
278
|
+
// mask header values
|
|
279
|
+
};
|
|
280
|
+
exports2.EXTENSIBLE_DATA_FIELDS = {
|
|
281
|
+
ID: 0,
|
|
282
|
+
SIZE: 2
|
|
283
|
+
};
|
|
284
|
+
exports2.HDR_ID = {
|
|
285
|
+
ZIP64: 1,
|
|
286
|
+
// ZIP64 Extended Information Extra Field
|
|
287
|
+
AVINFO: 7,
|
|
288
|
+
// AV Info
|
|
289
|
+
PFS: 8,
|
|
290
|
+
// PFS Extra Field
|
|
291
|
+
OS2: 9,
|
|
292
|
+
// OS/2 Extra Field
|
|
293
|
+
NTFS: 10,
|
|
294
|
+
// NTFS Extra Field
|
|
295
|
+
OPENVMS: 12,
|
|
296
|
+
// OpenVMS Extra Field
|
|
297
|
+
UNIX: 13,
|
|
298
|
+
// Unix Extra Field
|
|
299
|
+
FORK: 14,
|
|
300
|
+
// Fork Data Extra Field
|
|
301
|
+
PATCH: 15,
|
|
302
|
+
// Patch Descriptor Extra Field
|
|
303
|
+
x509PKCS7: 20,
|
|
304
|
+
// X.509 Certificate Store (PKCS#7)
|
|
305
|
+
x509CERT_IDF: 21,
|
|
306
|
+
// X.509 Certificate ID and Fingerprint
|
|
307
|
+
x509CERT_IDC: 22,
|
|
308
|
+
// X.509 Certificate ID and Certificate
|
|
309
|
+
STRONG_ENC: 23,
|
|
310
|
+
// Strong Encryption Header
|
|
311
|
+
RECORD_MGT: 24,
|
|
312
|
+
// Record Management Controls
|
|
313
|
+
x509PKCS7RL: 25,
|
|
314
|
+
// X.509 Certificate Revocation List (PKCS#7)
|
|
315
|
+
IBM1: 101,
|
|
316
|
+
// IBM S/390 (Z390) - Attribute
|
|
317
|
+
IBM2: 102,
|
|
318
|
+
// IBM S/390 (Z390) - Attribute
|
|
319
|
+
SHA256: 334,
|
|
320
|
+
// SHA256 "N\01" with 64 bytes (256 bit) of SHA256 hash data
|
|
321
|
+
POSZIP: 18064,
|
|
322
|
+
// POSZIP 4690
|
|
323
|
+
UNV_TIME: 21589,
|
|
324
|
+
// Universal Time (UT) (32-bit) 5 data bytes
|
|
325
|
+
UID_GID: 30837,
|
|
326
|
+
// Unix UID/GID (any size)
|
|
327
|
+
UNICODE_PATH: 28789,
|
|
328
|
+
// Info-ZIP Unicode Path Extra Field
|
|
329
|
+
SYMLINK: 30805,
|
|
330
|
+
// Unix Symbolic Link Extra Field
|
|
331
|
+
HARDLINK: 30821
|
|
332
|
+
// Unix Hard Link Extra Field
|
|
333
|
+
};
|
|
334
|
+
exports2.FILE_SYSTEM = {
|
|
335
|
+
MSDOS: 0,
|
|
336
|
+
// MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems)
|
|
337
|
+
AMIGA: 1,
|
|
338
|
+
// Amiga
|
|
339
|
+
OPENVMS: 2,
|
|
340
|
+
// OpenVMS
|
|
341
|
+
UNIX: 3,
|
|
342
|
+
// UNIX
|
|
343
|
+
VM_CMS: 4,
|
|
344
|
+
// VM/CMS
|
|
345
|
+
ATARI: 5,
|
|
346
|
+
// Atari ST
|
|
347
|
+
OS2: 6,
|
|
348
|
+
// OS/2 H.P.F.S.
|
|
349
|
+
MAC: 7,
|
|
350
|
+
// Macintosh
|
|
351
|
+
CP_M: 9,
|
|
352
|
+
// CP/M
|
|
353
|
+
NTFS: 10,
|
|
354
|
+
// Windows NTFS
|
|
355
|
+
MVS: 11,
|
|
356
|
+
// MVS (OS/390 - Z/OS)
|
|
357
|
+
VSE: 12,
|
|
358
|
+
// VSE
|
|
359
|
+
ACORN: 13,
|
|
360
|
+
// Acorn Risc
|
|
361
|
+
VFAT: 14,
|
|
362
|
+
// VFAT
|
|
363
|
+
ALTMVS: 15,
|
|
364
|
+
// Alternate MVS
|
|
365
|
+
BEOS: 16,
|
|
366
|
+
// BeOS
|
|
367
|
+
TANDEM: 17,
|
|
368
|
+
// Tandem
|
|
369
|
+
OS400: 18,
|
|
370
|
+
// OS/400
|
|
371
|
+
DARWIN: 19
|
|
372
|
+
// Apple OS/X (Darwin)
|
|
373
|
+
};
|
|
374
|
+
exports2.DOS_FILE_ATTR = {
|
|
375
|
+
READONLY: 1,
|
|
376
|
+
HIDDEN: 2,
|
|
377
|
+
SYSTEM: 4,
|
|
378
|
+
VOLUME: 8,
|
|
379
|
+
DIRECTORY: 16,
|
|
380
|
+
ARCHIVE: 32
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
// neozipkit/dist/core/components/Logger.js
|
|
386
|
+
var require_Logger = __commonJS({
|
|
387
|
+
"neozipkit/dist/core/components/Logger.js"(exports2) {
|
|
388
|
+
"use strict";
|
|
389
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
390
|
+
exports2.Logger = void 0;
|
|
391
|
+
exports2.configureLoggerFromEnvironment = configureLoggerFromEnvironment;
|
|
392
|
+
var Logger = class {
|
|
393
|
+
static {
|
|
394
|
+
__name(this, "Logger");
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Configure the logger
|
|
398
|
+
*/
|
|
399
|
+
static configure(config) {
|
|
400
|
+
this.config = { ...this.config, ...config };
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Get current logger configuration
|
|
404
|
+
*/
|
|
405
|
+
static getConfig() {
|
|
406
|
+
return { ...this.config };
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Enable logging
|
|
410
|
+
*/
|
|
411
|
+
static enable() {
|
|
412
|
+
this.config.enabled = true;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Disable all logging
|
|
416
|
+
*/
|
|
417
|
+
static disable() {
|
|
418
|
+
this.config.enabled = false;
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Set log level
|
|
422
|
+
*/
|
|
423
|
+
static setLevel(level) {
|
|
424
|
+
this.config.level = level;
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Check if a log level should be output
|
|
428
|
+
*/
|
|
429
|
+
static shouldLog(level) {
|
|
430
|
+
if (!this.config.enabled)
|
|
431
|
+
return false;
|
|
432
|
+
const levels = ["debug", "info", "warn", "error", "silent"];
|
|
433
|
+
const currentLevelIndex = levels.indexOf(this.config.level);
|
|
434
|
+
const requestedLevelIndex = levels.indexOf(level);
|
|
435
|
+
return requestedLevelIndex >= currentLevelIndex;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Log a message
|
|
439
|
+
*/
|
|
440
|
+
static log(...args) {
|
|
441
|
+
if (this.shouldLog("info")) {
|
|
442
|
+
this.originalConsole.log(...args);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Log an error message
|
|
447
|
+
*/
|
|
448
|
+
static error(...args) {
|
|
449
|
+
if (this.shouldLog("error")) {
|
|
450
|
+
this.originalConsole.error(...args);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Log a warning message
|
|
455
|
+
*/
|
|
456
|
+
static warn(...args) {
|
|
457
|
+
if (this.shouldLog("warn")) {
|
|
458
|
+
this.originalConsole.warn(...args);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Log a debug message
|
|
463
|
+
*/
|
|
464
|
+
static debug(...args) {
|
|
465
|
+
if (this.shouldLog("debug")) {
|
|
466
|
+
this.originalConsole.log(...args);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Log an info message
|
|
471
|
+
*/
|
|
472
|
+
static info(...args) {
|
|
473
|
+
if (this.shouldLog("info")) {
|
|
474
|
+
this.originalConsole.info(...args);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Override console methods globally (use with caution)
|
|
479
|
+
*/
|
|
480
|
+
static overrideConsole() {
|
|
481
|
+
console.log = (...args) => this.log(...args);
|
|
482
|
+
console.error = (...args) => this.error(...args);
|
|
483
|
+
console.warn = (...args) => this.warn(...args);
|
|
484
|
+
console.debug = (...args) => this.debug(...args);
|
|
485
|
+
console.info = (...args) => this.info(...args);
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Restore original console methods
|
|
489
|
+
*/
|
|
490
|
+
static restoreConsole() {
|
|
491
|
+
console.log = this.originalConsole.log;
|
|
492
|
+
console.error = this.originalConsole.error;
|
|
493
|
+
console.warn = this.originalConsole.warn;
|
|
494
|
+
console.debug = this.originalConsole.debug;
|
|
495
|
+
console.info = this.originalConsole.info;
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
exports2.Logger = Logger;
|
|
499
|
+
Logger.config = {
|
|
500
|
+
enabled: true,
|
|
501
|
+
level: "info"
|
|
502
|
+
};
|
|
503
|
+
Logger.originalConsole = {
|
|
504
|
+
log: console.log,
|
|
505
|
+
error: console.error,
|
|
506
|
+
warn: console.warn,
|
|
507
|
+
debug: console.debug,
|
|
508
|
+
info: console.info
|
|
509
|
+
};
|
|
510
|
+
function configureLoggerFromEnvironment() {
|
|
511
|
+
const env = typeof process !== "undefined" ? process.env : {};
|
|
512
|
+
if (env.NEOZIP_DEBUG === "false") {
|
|
513
|
+
Logger.disable();
|
|
514
|
+
} else if (env.NEOZIP_DEBUG === "true") {
|
|
515
|
+
Logger.enable();
|
|
516
|
+
Logger.setLevel("debug");
|
|
517
|
+
}
|
|
518
|
+
if (env.NEOZIP_LOG_LEVEL) {
|
|
519
|
+
const level = env.NEOZIP_LOG_LEVEL;
|
|
520
|
+
if (["debug", "info", "warn", "error", "silent"].includes(level)) {
|
|
521
|
+
Logger.setLevel(level);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
if (env.NODE_ENV === "production") {
|
|
525
|
+
Logger.setLevel("error");
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
__name(configureLoggerFromEnvironment, "configureLoggerFromEnvironment");
|
|
529
|
+
configureLoggerFromEnvironment();
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
// neozipkit/dist/core/encryption/types.js
|
|
534
|
+
var require_types = __commonJS({
|
|
535
|
+
"neozipkit/dist/core/encryption/types.js"(exports2) {
|
|
536
|
+
"use strict";
|
|
537
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
538
|
+
exports2.EncryptionMethod = void 0;
|
|
539
|
+
var EncryptionMethod;
|
|
540
|
+
(function(EncryptionMethod2) {
|
|
541
|
+
EncryptionMethod2[EncryptionMethod2["NONE"] = 0] = "NONE";
|
|
542
|
+
EncryptionMethod2[EncryptionMethod2["ZIP_CRYPTO"] = 1] = "ZIP_CRYPTO";
|
|
543
|
+
})(EncryptionMethod || (exports2.EncryptionMethod = EncryptionMethod = {}));
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
// neozipkit/dist/core/encryption/ZipCrypto.js
|
|
548
|
+
var require_ZipCrypto = __commonJS({
|
|
549
|
+
"neozipkit/dist/core/encryption/ZipCrypto.js"(exports2) {
|
|
550
|
+
"use strict";
|
|
551
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
552
|
+
exports2.DecryptionStream = exports2.ZipCrypto = void 0;
|
|
553
|
+
exports2.crc32 = crc32;
|
|
554
|
+
exports2.crc32update = crc32update;
|
|
555
|
+
exports2.sha256 = sha256;
|
|
556
|
+
var types_1 = require_types();
|
|
557
|
+
var Logger_12 = require_Logger();
|
|
558
|
+
var Headers_1 = require_Headers();
|
|
559
|
+
var crypto_1 = require("crypto");
|
|
560
|
+
var ZipCrypto = class _ZipCrypto {
|
|
561
|
+
static {
|
|
562
|
+
__name(this, "ZipCrypto");
|
|
563
|
+
}
|
|
564
|
+
canHandle(method) {
|
|
565
|
+
return method === types_1.EncryptionMethod.ZIP_CRYPTO;
|
|
566
|
+
}
|
|
567
|
+
getMethodName() {
|
|
568
|
+
return "ZIP-Crypto";
|
|
569
|
+
}
|
|
570
|
+
getKeyLength() {
|
|
571
|
+
return _ZipCrypto.KEY_LENGTH;
|
|
572
|
+
}
|
|
573
|
+
async encrypt(data, options) {
|
|
574
|
+
try {
|
|
575
|
+
if (options.method !== types_1.EncryptionMethod.ZIP_CRYPTO) {
|
|
576
|
+
return {
|
|
577
|
+
success: false,
|
|
578
|
+
error: "ZIP-Crypto encryption method required"
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
const keys = this.initKeys(options.password);
|
|
582
|
+
const encryptedData = Buffer.alloc(data.length);
|
|
583
|
+
for (let i = 0; i < data.length; i++) {
|
|
584
|
+
const byte = data[i];
|
|
585
|
+
const encryptedByte = this.encryptByte(keys, byte);
|
|
586
|
+
encryptedData[i] = encryptedByte;
|
|
587
|
+
this.updateKeys(keys, byte);
|
|
588
|
+
}
|
|
589
|
+
return {
|
|
590
|
+
success: true,
|
|
591
|
+
encryptedData
|
|
592
|
+
};
|
|
593
|
+
} catch (error) {
|
|
594
|
+
return {
|
|
595
|
+
success: false,
|
|
596
|
+
error: error instanceof Error ? error.message : "Unknown encryption error"
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
async decrypt(data, options) {
|
|
601
|
+
try {
|
|
602
|
+
if (options.method !== types_1.EncryptionMethod.ZIP_CRYPTO) {
|
|
603
|
+
return {
|
|
604
|
+
success: false,
|
|
605
|
+
error: "ZIP-Crypto decryption method required"
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
const keys = this.initKeys(options.password);
|
|
609
|
+
const decryptedData = Buffer.alloc(data.length);
|
|
610
|
+
for (let i = 0; i < data.length; i++) {
|
|
611
|
+
const encryptedByte = data[i];
|
|
612
|
+
const decryptedByte = this.decryptByte(keys, encryptedByte);
|
|
613
|
+
decryptedData[i] = decryptedByte;
|
|
614
|
+
this.updateKeys(keys, decryptedByte);
|
|
615
|
+
}
|
|
616
|
+
return {
|
|
617
|
+
success: true,
|
|
618
|
+
decryptedData
|
|
619
|
+
};
|
|
620
|
+
} catch (error) {
|
|
621
|
+
return {
|
|
622
|
+
success: false,
|
|
623
|
+
error: error instanceof Error ? error.message : "Unknown decryption error"
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Verify password using check byte from decrypted header
|
|
629
|
+
* @param decryptedHeader - 12-byte decrypted encryption header
|
|
630
|
+
* @param checkByte - Expected check byte value
|
|
631
|
+
* @throws Error if password verification fails
|
|
632
|
+
*/
|
|
633
|
+
verifyPassword(decryptedHeader, checkByte) {
|
|
634
|
+
if (decryptedHeader.length < 12) {
|
|
635
|
+
throw new Error("Decrypted header must be at least 12 bytes");
|
|
636
|
+
}
|
|
637
|
+
if (decryptedHeader[11] !== checkByte) {
|
|
638
|
+
throw new Error("Password verification FAILED");
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Parse local header to extract information needed for decryption
|
|
643
|
+
* @param localHeaderBuffer - 30-byte local header buffer
|
|
644
|
+
* @param entry - ZIP entry to update with extracted information
|
|
645
|
+
* @returns Object with bitFlags, lastModTimeDate, localCrc, and checkByte
|
|
646
|
+
*/
|
|
647
|
+
parseLocalHeaderForDecryption(localHeaderBuffer, entry) {
|
|
648
|
+
if (localHeaderBuffer.readUInt32LE(0) !== 67324752) {
|
|
649
|
+
throw new Error("Invalid local header signature");
|
|
650
|
+
}
|
|
651
|
+
const bitFlags = localHeaderBuffer.readUInt16LE(6);
|
|
652
|
+
const lastModTimeDate = localHeaderBuffer.readUInt32LE(10);
|
|
653
|
+
const localCrc = localHeaderBuffer.readUInt32LE(14);
|
|
654
|
+
if (bitFlags & Headers_1.GP_FLAG.DATA_DESC && (!entry.lastModTimeDate || entry.lastModTimeDate === 0)) {
|
|
655
|
+
entry.lastModTimeDate = lastModTimeDate;
|
|
656
|
+
}
|
|
657
|
+
entry.localCrc = localCrc;
|
|
658
|
+
let checkByte;
|
|
659
|
+
if (bitFlags & Headers_1.GP_FLAG.DATA_DESC) {
|
|
660
|
+
const timeDate = entry.lastModTimeDate || entry.timeDateDOS || 0;
|
|
661
|
+
checkByte = timeDate >> 8 & 255;
|
|
662
|
+
} else {
|
|
663
|
+
const crc = localCrc && localCrc !== 0 ? localCrc : entry.crc;
|
|
664
|
+
checkByte = crc >> 24 & 255;
|
|
665
|
+
}
|
|
666
|
+
return { bitFlags, lastModTimeDate, localCrc, checkByte };
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Create encryption header (12 bytes) for PKZIP encryption
|
|
670
|
+
* Generates 11 random bytes + 1 check byte
|
|
671
|
+
* @param entry - ZIP entry to create header for
|
|
672
|
+
* @param password - Password for encryption (used to calculate check byte)
|
|
673
|
+
* @returns 12-byte encryption header buffer
|
|
674
|
+
*/
|
|
675
|
+
createEncryptionHeader(entry, password) {
|
|
676
|
+
const header = Buffer.alloc(Headers_1.ENCRYPT_HDR_SIZE);
|
|
677
|
+
const random = (0, crypto_1.randomBytes)(11);
|
|
678
|
+
random.copy(header, 0);
|
|
679
|
+
let checkByte;
|
|
680
|
+
if ((entry.bitFlags & Headers_1.GP_FLAG.DATA_DESC) !== 0) {
|
|
681
|
+
const timeDate = entry.lastModTimeDate || entry.timeDateDOS || 0;
|
|
682
|
+
checkByte = timeDate >> 8 & 255;
|
|
683
|
+
} else {
|
|
684
|
+
checkByte = entry.crc >> 24 & 255;
|
|
685
|
+
}
|
|
686
|
+
header[11] = checkByte;
|
|
687
|
+
Logger_12.Logger.debug(`[ZipCrypto] Created encryption header: checkByte=0x${checkByte.toString(16).padStart(2, "0")}, DATA_DESC=${(entry.bitFlags & Headers_1.GP_FLAG.DATA_DESC) !== 0}`);
|
|
688
|
+
return header;
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Encrypt buffer (header + compressed data) for PKZIP encryption
|
|
692
|
+
* Creates encryption header, concatenates with compressed data, and encrypts everything
|
|
693
|
+
* @param entry - ZIP entry to encrypt
|
|
694
|
+
* @param compressedData - Compressed data to encrypt
|
|
695
|
+
* @param password - Password for encryption
|
|
696
|
+
* @returns Encrypted buffer (encrypted header + encrypted compressed data)
|
|
697
|
+
*/
|
|
698
|
+
encryptBuffer(entry, compressedData, password) {
|
|
699
|
+
const header = this.createEncryptionHeader(entry, password);
|
|
700
|
+
const dataToEncrypt = Buffer.concat([header, compressedData]);
|
|
701
|
+
const keys = this.initKeys(password);
|
|
702
|
+
const encryptedData = Buffer.alloc(dataToEncrypt.length);
|
|
703
|
+
for (let i = 0; i < dataToEncrypt.length; i++) {
|
|
704
|
+
const byte = dataToEncrypt[i];
|
|
705
|
+
const encryptedByte = this.encryptByte(keys, byte);
|
|
706
|
+
encryptedData[i] = encryptedByte;
|
|
707
|
+
this.updateKeys(keys, byte);
|
|
708
|
+
}
|
|
709
|
+
Logger_12.Logger.debug(`[ZipCrypto] Encrypted buffer: ${compressedData.length} bytes compressed data + ${Headers_1.ENCRYPT_HDR_SIZE} bytes header = ${encryptedData.length} bytes total`);
|
|
710
|
+
return encryptedData;
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Decrypt buffer-based encrypted data (for in-memory extraction)
|
|
714
|
+
* Handles local header parsing, encryption header extraction, and decryption
|
|
715
|
+
* @param entry - ZIP entry with encryption information
|
|
716
|
+
* @param buffer - Full ZIP file buffer
|
|
717
|
+
* @param encryptedData - Encrypted data without header (from parseLocalHeader)
|
|
718
|
+
* @param password - Password for decryption
|
|
719
|
+
* @returns Decrypted compressed data (without header)
|
|
720
|
+
*/
|
|
721
|
+
decryptBuffer(entry, buffer, encryptedData, password) {
|
|
722
|
+
const localData = buffer.subarray(entry.localHdrOffset);
|
|
723
|
+
const localHeaderBuffer = localData.subarray(0, 30);
|
|
724
|
+
const { bitFlags, localCrc, checkByte } = this.parseLocalHeaderForDecryption(localHeaderBuffer, entry);
|
|
725
|
+
const fnameLen = localHeaderBuffer.readUInt16LE(26);
|
|
726
|
+
const extraLen = localHeaderBuffer.readUInt16LE(28);
|
|
727
|
+
const localSize = 30 + fnameLen + extraLen;
|
|
728
|
+
const ENCRYPT_HDR_SIZE = 12;
|
|
729
|
+
const encryptHeader = localData.subarray(localSize, localSize + ENCRYPT_HDR_SIZE);
|
|
730
|
+
const encryptedDataWithHeader = Buffer.concat([encryptHeader, encryptedData]);
|
|
731
|
+
const keys = this.initKeys(password);
|
|
732
|
+
for (let i = 0; i < encryptedDataWithHeader.length; i++) {
|
|
733
|
+
const encryptedByte = encryptedDataWithHeader[i];
|
|
734
|
+
const decryptedByte = this.decryptByte(keys, encryptedByte);
|
|
735
|
+
encryptedDataWithHeader[i] = decryptedByte;
|
|
736
|
+
this.updateKeys(keys, decryptedByte);
|
|
737
|
+
}
|
|
738
|
+
const decryptedHeader = encryptedDataWithHeader.subarray(0, ENCRYPT_HDR_SIZE);
|
|
739
|
+
this.verifyPassword(decryptedHeader, checkByte);
|
|
740
|
+
return encryptedDataWithHeader.subarray(ENCRYPT_HDR_SIZE);
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Create a streaming decryptor for chunked data processing
|
|
744
|
+
* Handles 12-byte header decryption and verification, then yields decrypted chunks
|
|
745
|
+
*
|
|
746
|
+
* MEMORY EFFICIENCY: This method processes encrypted data one block at a time.
|
|
747
|
+
* - Decryption state (keys) is maintained across blocks via updateKeys()
|
|
748
|
+
* - Only the minimum 12-byte header is accumulated before password verification
|
|
749
|
+
* - Each decrypted block is yielded immediately without accumulation
|
|
750
|
+
*
|
|
751
|
+
* @param password - Password for decryption
|
|
752
|
+
* @param checkByte - Expected check byte value for password verification
|
|
753
|
+
* @param encryptedStream - Async generator of encrypted data chunks (one block at a time)
|
|
754
|
+
* @returns Async generator of decrypted data chunks (one block at a time)
|
|
755
|
+
*/
|
|
756
|
+
async *createStreamDecryptor(password, checkByte, encryptedStream) {
|
|
757
|
+
const keys = this.initKeys(password);
|
|
758
|
+
const ENCRYPT_HDR_SIZE = 12;
|
|
759
|
+
const headerBuffer = Buffer.alloc(ENCRYPT_HDR_SIZE);
|
|
760
|
+
let headerBytesCollected = 0;
|
|
761
|
+
let currentChunk = null;
|
|
762
|
+
let currentChunkOffset = 0;
|
|
763
|
+
while (headerBytesCollected < ENCRYPT_HDR_SIZE) {
|
|
764
|
+
if (!currentChunk || currentChunkOffset >= currentChunk.length) {
|
|
765
|
+
const result = await encryptedStream.next();
|
|
766
|
+
if (result.done || !result.value) {
|
|
767
|
+
throw new Error("ZIP-Crypto: insufficient encrypted data (missing encryption header)");
|
|
768
|
+
}
|
|
769
|
+
currentChunk = result.value;
|
|
770
|
+
currentChunkOffset = 0;
|
|
771
|
+
}
|
|
772
|
+
const bytesNeeded = ENCRYPT_HDR_SIZE - headerBytesCollected;
|
|
773
|
+
const bytesToCopy = Math.min(bytesNeeded, currentChunk.length - currentChunkOffset);
|
|
774
|
+
currentChunk.copy(headerBuffer, headerBytesCollected, currentChunkOffset, currentChunkOffset + bytesToCopy);
|
|
775
|
+
headerBytesCollected += bytesToCopy;
|
|
776
|
+
currentChunkOffset += bytesToCopy;
|
|
777
|
+
}
|
|
778
|
+
for (let i = 0; i < ENCRYPT_HDR_SIZE; i++) {
|
|
779
|
+
const encryptedByte = headerBuffer[i];
|
|
780
|
+
const decryptedByte = this.decryptByte(keys, encryptedByte) & 255;
|
|
781
|
+
headerBuffer[i] = decryptedByte;
|
|
782
|
+
this.updateKeys(keys, decryptedByte);
|
|
783
|
+
}
|
|
784
|
+
this.verifyPassword(headerBuffer, checkByte);
|
|
785
|
+
if (currentChunk && currentChunkOffset < currentChunk.length) {
|
|
786
|
+
const remainingInChunk = currentChunk.length - currentChunkOffset;
|
|
787
|
+
for (let i = 0; i < remainingInChunk; i++) {
|
|
788
|
+
const pos = currentChunkOffset + i;
|
|
789
|
+
const encryptedByte = currentChunk[pos];
|
|
790
|
+
const decryptedByte = this.decryptByte(keys, encryptedByte);
|
|
791
|
+
currentChunk[pos] = decryptedByte;
|
|
792
|
+
this.updateKeys(keys, decryptedByte);
|
|
793
|
+
}
|
|
794
|
+
yield currentChunk.subarray(currentChunkOffset);
|
|
795
|
+
}
|
|
796
|
+
for await (const encryptedChunk of encryptedStream) {
|
|
797
|
+
for (let i = 0; i < encryptedChunk.length; i++) {
|
|
798
|
+
const encryptedByte = encryptedChunk[i];
|
|
799
|
+
const decryptedByte = this.decryptByte(keys, encryptedByte);
|
|
800
|
+
encryptedChunk[i] = decryptedByte;
|
|
801
|
+
this.updateKeys(keys, decryptedByte);
|
|
802
|
+
}
|
|
803
|
+
yield encryptedChunk;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Initialize encryption keys from password
|
|
808
|
+
*/
|
|
809
|
+
initKeys(password) {
|
|
810
|
+
const keys = [305419896, 591751049, 878082192];
|
|
811
|
+
for (let i = 0; i < password.length; i++) {
|
|
812
|
+
this.updateKeys(keys, password.charCodeAt(i));
|
|
813
|
+
}
|
|
814
|
+
return keys;
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* Update encryption keys with a byte
|
|
818
|
+
* Based on zip.js implementation - uses Math.imul for 32-bit integer multiplication
|
|
819
|
+
*/
|
|
820
|
+
updateKeys(keys, byte) {
|
|
821
|
+
keys[0] = (keys[0] >>> 8 ^ _ZipCrypto.CRC_TABLE[(keys[0] ^ byte) & 255]) >>> 0;
|
|
822
|
+
keys[1] = (Math.imul(keys[1] + (keys[0] & 255), 134775813) + 1 & 4294967295) >>> 0;
|
|
823
|
+
keys[2] = (keys[2] >>> 8 ^ _ZipCrypto.CRC_TABLE[(keys[2] ^ keys[1] >>> 24) & 255]) >>> 0;
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* Encrypt a single byte
|
|
827
|
+
* Based on zip.js implementation - uses Math.imul for 32-bit integer multiplication
|
|
828
|
+
*/
|
|
829
|
+
encryptByte(keys, byte) {
|
|
830
|
+
const temp = keys[2] | 2;
|
|
831
|
+
return (byte ^ Math.imul(temp, temp ^ 1) >>> 8) & 255;
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Decrypt a single byte
|
|
835
|
+
* Based on zip.js implementation - uses Math.imul for 32-bit integer multiplication
|
|
836
|
+
*/
|
|
837
|
+
decryptByte(keys, encryptedByte) {
|
|
838
|
+
const temp = keys[2] | 2;
|
|
839
|
+
return (encryptedByte ^ Math.imul(temp, temp ^ 1) >>> 8) & 255;
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* CRC32 implementation for ZIP crypto (single byte update)
|
|
843
|
+
* Used internally for key updates during encryption/decryption
|
|
844
|
+
*/
|
|
845
|
+
crc32(crc, byte) {
|
|
846
|
+
return (crc >>> 8 ^ _ZipCrypto.CRC_TABLE[(crc ^ byte) & 255]) >>> 0;
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* Static CRC32 calculation for a full buffer
|
|
850
|
+
* Delegates to exported crc32() function
|
|
851
|
+
* @param buf - Buffer or string to calculate CRC32 for
|
|
852
|
+
* @returns CRC32 checksum as unsigned 32-bit integer
|
|
853
|
+
*/
|
|
854
|
+
static crc32(buf) {
|
|
855
|
+
return crc32Impl(buf);
|
|
856
|
+
}
|
|
857
|
+
/**
|
|
858
|
+
* Static CRC32 incremental update (single byte)
|
|
859
|
+
* Delegates to exported crc32update() function
|
|
860
|
+
* @param crc - Current CRC32 value
|
|
861
|
+
* @param byte - Byte to update with
|
|
862
|
+
* @returns Updated CRC32 value
|
|
863
|
+
*/
|
|
864
|
+
static crc32update(crc, byte) {
|
|
865
|
+
return crc32updateImpl(crc, byte);
|
|
866
|
+
}
|
|
867
|
+
};
|
|
868
|
+
exports2.ZipCrypto = ZipCrypto;
|
|
869
|
+
ZipCrypto.KEY_LENGTH = 3;
|
|
870
|
+
ZipCrypto.CRC_TABLE = [
|
|
871
|
+
0,
|
|
872
|
+
1996959894,
|
|
873
|
+
3993919788,
|
|
874
|
+
2567524794,
|
|
875
|
+
124634137,
|
|
876
|
+
1886057615,
|
|
877
|
+
3915621685,
|
|
878
|
+
2657392035,
|
|
879
|
+
249268274,
|
|
880
|
+
2044508324,
|
|
881
|
+
3772115230,
|
|
882
|
+
2547177864,
|
|
883
|
+
162941995,
|
|
884
|
+
2125561021,
|
|
885
|
+
3887607047,
|
|
886
|
+
2428444049,
|
|
887
|
+
498536548,
|
|
888
|
+
1789927666,
|
|
889
|
+
4089016648,
|
|
890
|
+
2227061214,
|
|
891
|
+
450548861,
|
|
892
|
+
1843258603,
|
|
893
|
+
4107580753,
|
|
894
|
+
2211677639,
|
|
895
|
+
325883990,
|
|
896
|
+
1684777152,
|
|
897
|
+
4251122042,
|
|
898
|
+
2321926636,
|
|
899
|
+
335633487,
|
|
900
|
+
1661365465,
|
|
901
|
+
4195302755,
|
|
902
|
+
2366115317,
|
|
903
|
+
997073096,
|
|
904
|
+
1281953886,
|
|
905
|
+
3579855332,
|
|
906
|
+
2724688242,
|
|
907
|
+
1006888145,
|
|
908
|
+
1258607687,
|
|
909
|
+
3524101629,
|
|
910
|
+
2768942443,
|
|
911
|
+
901097722,
|
|
912
|
+
1119000684,
|
|
913
|
+
3686517206,
|
|
914
|
+
2898065728,
|
|
915
|
+
853044451,
|
|
916
|
+
1172266101,
|
|
917
|
+
3705015759,
|
|
918
|
+
2882616665,
|
|
919
|
+
651767980,
|
|
920
|
+
1373503546,
|
|
921
|
+
3369554304,
|
|
922
|
+
3218104598,
|
|
923
|
+
565507253,
|
|
924
|
+
1454621731,
|
|
925
|
+
3485111705,
|
|
926
|
+
3099436303,
|
|
927
|
+
671266974,
|
|
928
|
+
1594198024,
|
|
929
|
+
3322730930,
|
|
930
|
+
2970347812,
|
|
931
|
+
795835527,
|
|
932
|
+
1483230225,
|
|
933
|
+
3244367275,
|
|
934
|
+
3060149565,
|
|
935
|
+
1994146192,
|
|
936
|
+
31158534,
|
|
937
|
+
2563907772,
|
|
938
|
+
4023717930,
|
|
939
|
+
1907459465,
|
|
940
|
+
112637215,
|
|
941
|
+
2680153253,
|
|
942
|
+
3904427059,
|
|
943
|
+
2013776290,
|
|
944
|
+
251722036,
|
|
945
|
+
2517215374,
|
|
946
|
+
3775830040,
|
|
947
|
+
2137656763,
|
|
948
|
+
141376813,
|
|
949
|
+
2439277719,
|
|
950
|
+
3865271297,
|
|
951
|
+
1802195444,
|
|
952
|
+
476864866,
|
|
953
|
+
2238001368,
|
|
954
|
+
4066508878,
|
|
955
|
+
1812370925,
|
|
956
|
+
453092731,
|
|
957
|
+
2181625025,
|
|
958
|
+
4111451223,
|
|
959
|
+
1706088902,
|
|
960
|
+
314042704,
|
|
961
|
+
2344532202,
|
|
962
|
+
4240017532,
|
|
963
|
+
1658658271,
|
|
964
|
+
366619977,
|
|
965
|
+
2362670323,
|
|
966
|
+
4224994405,
|
|
967
|
+
1303535960,
|
|
968
|
+
984961486,
|
|
969
|
+
2747007092,
|
|
970
|
+
3569037538,
|
|
971
|
+
1256170817,
|
|
972
|
+
1037604311,
|
|
973
|
+
2765210733,
|
|
974
|
+
3554079995,
|
|
975
|
+
1131014506,
|
|
976
|
+
879679996,
|
|
977
|
+
2909243462,
|
|
978
|
+
3663771856,
|
|
979
|
+
1141124467,
|
|
980
|
+
855842277,
|
|
981
|
+
2852801631,
|
|
982
|
+
3708648649,
|
|
983
|
+
1342533948,
|
|
984
|
+
654459306,
|
|
985
|
+
3188396048,
|
|
986
|
+
3373015174,
|
|
987
|
+
1466479909,
|
|
988
|
+
544179635,
|
|
989
|
+
3110523913,
|
|
990
|
+
3462522015,
|
|
991
|
+
1591671054,
|
|
992
|
+
702138776,
|
|
993
|
+
2966460450,
|
|
994
|
+
3352799412,
|
|
995
|
+
1504918807,
|
|
996
|
+
783551873,
|
|
997
|
+
3082640443,
|
|
998
|
+
3233442989,
|
|
999
|
+
3988292384,
|
|
1000
|
+
2596254646,
|
|
1001
|
+
62317068,
|
|
1002
|
+
1957810842,
|
|
1003
|
+
3939845945,
|
|
1004
|
+
2647816111,
|
|
1005
|
+
81470997,
|
|
1006
|
+
1943803523,
|
|
1007
|
+
3814918930,
|
|
1008
|
+
2489596804,
|
|
1009
|
+
225274430,
|
|
1010
|
+
2053790376,
|
|
1011
|
+
3826175755,
|
|
1012
|
+
2466906013,
|
|
1013
|
+
167816743,
|
|
1014
|
+
2097651377,
|
|
1015
|
+
4027552580,
|
|
1016
|
+
2265490386,
|
|
1017
|
+
503444072,
|
|
1018
|
+
1762050814,
|
|
1019
|
+
4150417245,
|
|
1020
|
+
2154129355,
|
|
1021
|
+
426522225,
|
|
1022
|
+
1852507879,
|
|
1023
|
+
4275313526,
|
|
1024
|
+
2312317920,
|
|
1025
|
+
282753626,
|
|
1026
|
+
1742555852,
|
|
1027
|
+
4189708143,
|
|
1028
|
+
2394877945,
|
|
1029
|
+
397917763,
|
|
1030
|
+
1622183637,
|
|
1031
|
+
3604390888,
|
|
1032
|
+
2714866558,
|
|
1033
|
+
953729732,
|
|
1034
|
+
1340076626,
|
|
1035
|
+
3518719985,
|
|
1036
|
+
2797360999,
|
|
1037
|
+
1068828381,
|
|
1038
|
+
1219638859,
|
|
1039
|
+
3624741850,
|
|
1040
|
+
2936675148,
|
|
1041
|
+
906185462,
|
|
1042
|
+
1090812512,
|
|
1043
|
+
3747672003,
|
|
1044
|
+
2825379669,
|
|
1045
|
+
829329135,
|
|
1046
|
+
1181335161,
|
|
1047
|
+
3412177804,
|
|
1048
|
+
3160834842,
|
|
1049
|
+
628085408,
|
|
1050
|
+
1382605366,
|
|
1051
|
+
3423369109,
|
|
1052
|
+
3138078467,
|
|
1053
|
+
570562233,
|
|
1054
|
+
1426400815,
|
|
1055
|
+
3317316542,
|
|
1056
|
+
2998733608,
|
|
1057
|
+
733239954,
|
|
1058
|
+
1555261956,
|
|
1059
|
+
3268935591,
|
|
1060
|
+
3050360625,
|
|
1061
|
+
752459403,
|
|
1062
|
+
1541320221,
|
|
1063
|
+
2607071920,
|
|
1064
|
+
3965973030,
|
|
1065
|
+
1969922972,
|
|
1066
|
+
40735498,
|
|
1067
|
+
2617837225,
|
|
1068
|
+
3943577151,
|
|
1069
|
+
1913087877,
|
|
1070
|
+
83908371,
|
|
1071
|
+
2512341634,
|
|
1072
|
+
3803740692,
|
|
1073
|
+
2075208622,
|
|
1074
|
+
213261112,
|
|
1075
|
+
2463272603,
|
|
1076
|
+
3855990285,
|
|
1077
|
+
2094854071,
|
|
1078
|
+
198958881,
|
|
1079
|
+
2262029012,
|
|
1080
|
+
4057260610,
|
|
1081
|
+
1759359992,
|
|
1082
|
+
534414190,
|
|
1083
|
+
2176718541,
|
|
1084
|
+
4139329115,
|
|
1085
|
+
1873836001,
|
|
1086
|
+
414664567,
|
|
1087
|
+
2282248934,
|
|
1088
|
+
4279200368,
|
|
1089
|
+
1711684554,
|
|
1090
|
+
285281116,
|
|
1091
|
+
2405801727,
|
|
1092
|
+
4167216745,
|
|
1093
|
+
1634467795,
|
|
1094
|
+
376229701,
|
|
1095
|
+
2685067896,
|
|
1096
|
+
3608007406,
|
|
1097
|
+
1308918612,
|
|
1098
|
+
956543938,
|
|
1099
|
+
2808555105,
|
|
1100
|
+
3495958263,
|
|
1101
|
+
1231636301,
|
|
1102
|
+
1047427035,
|
|
1103
|
+
2932959818,
|
|
1104
|
+
3654703836,
|
|
1105
|
+
1088359270,
|
|
1106
|
+
936918e3,
|
|
1107
|
+
2847714899,
|
|
1108
|
+
3736837829,
|
|
1109
|
+
1202900863,
|
|
1110
|
+
817233897,
|
|
1111
|
+
3183342108,
|
|
1112
|
+
3401237130,
|
|
1113
|
+
1404277552,
|
|
1114
|
+
615818150,
|
|
1115
|
+
3134207493,
|
|
1116
|
+
3453421203,
|
|
1117
|
+
1423857449,
|
|
1118
|
+
601450431,
|
|
1119
|
+
3009837614,
|
|
1120
|
+
3294710456,
|
|
1121
|
+
1567103746,
|
|
1122
|
+
711928724,
|
|
1123
|
+
3020668471,
|
|
1124
|
+
3272380065,
|
|
1125
|
+
1510334235,
|
|
1126
|
+
755167117
|
|
1127
|
+
];
|
|
1128
|
+
function crc32Impl(buf) {
|
|
1129
|
+
if (typeof buf === "string") {
|
|
1130
|
+
buf = Buffer.from(buf, "utf8");
|
|
1131
|
+
}
|
|
1132
|
+
let len = buf.length;
|
|
1133
|
+
let crc = ~0;
|
|
1134
|
+
for (let off = 0; off < len; ) {
|
|
1135
|
+
crc = ZipCrypto.CRC_TABLE[(crc ^ buf[off++]) & 255] ^ crc >>> 8;
|
|
1136
|
+
}
|
|
1137
|
+
return ~crc >>> 0;
|
|
1138
|
+
}
|
|
1139
|
+
__name(crc32Impl, "crc32Impl");
|
|
1140
|
+
function crc32updateImpl(crc, byte) {
|
|
1141
|
+
return ZipCrypto.CRC_TABLE[(crc ^ byte) & 255] ^ crc >>> 8;
|
|
1142
|
+
}
|
|
1143
|
+
__name(crc32updateImpl, "crc32updateImpl");
|
|
1144
|
+
function crc32(buf) {
|
|
1145
|
+
return crc32Impl(buf);
|
|
1146
|
+
}
|
|
1147
|
+
__name(crc32, "crc32");
|
|
1148
|
+
function crc32update(crc, byte) {
|
|
1149
|
+
return crc32updateImpl(crc, byte);
|
|
1150
|
+
}
|
|
1151
|
+
__name(crc32update, "crc32update");
|
|
1152
|
+
var crypto_2 = require("crypto");
|
|
1153
|
+
function sha256(data) {
|
|
1154
|
+
const hash = (0, crypto_2.createHash)("sha256");
|
|
1155
|
+
return hash.update(data).digest("hex");
|
|
1156
|
+
}
|
|
1157
|
+
__name(sha256, "sha256");
|
|
1158
|
+
var DecryptionStream = class {
|
|
1159
|
+
static {
|
|
1160
|
+
__name(this, "DecryptionStream");
|
|
1161
|
+
}
|
|
1162
|
+
constructor(options) {
|
|
1163
|
+
this.password = options.password;
|
|
1164
|
+
this.method = options.method;
|
|
1165
|
+
this.entry = options.entry;
|
|
1166
|
+
this.zipCrypto = new ZipCrypto();
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Decrypt compressed data stream chunk by chunk
|
|
1170
|
+
*/
|
|
1171
|
+
async *decrypt(encryptedStream) {
|
|
1172
|
+
if (this.method !== types_1.EncryptionMethod.ZIP_CRYPTO) {
|
|
1173
|
+
throw new Error(`Unsupported encryption method: ${this.method}`);
|
|
1174
|
+
}
|
|
1175
|
+
const checkByte = this.calculateCheckByte();
|
|
1176
|
+
yield* this.zipCrypto.createStreamDecryptor(this.password, checkByte, encryptedStream);
|
|
1177
|
+
}
|
|
1178
|
+
/**
|
|
1179
|
+
* Calculate check byte for password verification
|
|
1180
|
+
* For DATA_DESC files: lastModTimeDate >> 8
|
|
1181
|
+
* For non-DATA_DESC files: CRC >> 24
|
|
1182
|
+
*/
|
|
1183
|
+
calculateCheckByte() {
|
|
1184
|
+
if (this.entry.bitFlags & Headers_1.GP_FLAG.DATA_DESC) {
|
|
1185
|
+
let lastModTimeDate = this.entry.lastModTimeDate;
|
|
1186
|
+
if (!lastModTimeDate || lastModTimeDate === 0) {
|
|
1187
|
+
lastModTimeDate = this.entry.timeDateDOS || 0;
|
|
1188
|
+
}
|
|
1189
|
+
const checkByte = lastModTimeDate >> 8 & 255;
|
|
1190
|
+
return checkByte;
|
|
1191
|
+
} else {
|
|
1192
|
+
const crc = this.entry.localCrc && this.entry.localCrc !== 0 ? this.entry.localCrc : this.entry.crc;
|
|
1193
|
+
const checkByte = crc >> 24 & 255;
|
|
1194
|
+
return checkByte;
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
/**
|
|
1198
|
+
* Prepare entry for decryption by parsing local header from file handle
|
|
1199
|
+
* This extracts the information needed for check byte calculation
|
|
1200
|
+
* @param fileHandle - File handle to read from
|
|
1201
|
+
* @param entry - ZIP entry to update
|
|
1202
|
+
* @returns Check byte value for password verification
|
|
1203
|
+
*/
|
|
1204
|
+
static async prepareEntryForDecryption(fileHandle, entry) {
|
|
1205
|
+
const localHeaderBuffer = Buffer.alloc(30);
|
|
1206
|
+
await fileHandle.read(localHeaderBuffer, 0, 30, entry.localHdrOffset);
|
|
1207
|
+
const zipCrypto = new ZipCrypto();
|
|
1208
|
+
const { checkByte } = zipCrypto.parseLocalHeaderForDecryption(localHeaderBuffer, entry);
|
|
1209
|
+
return checkByte;
|
|
1210
|
+
}
|
|
1211
|
+
};
|
|
1212
|
+
exports2.DecryptionStream = DecryptionStream;
|
|
1213
|
+
}
|
|
1214
|
+
});
|
|
1215
|
+
|
|
1216
|
+
// neozipkit/dist/core/ZipEntry.js
|
|
1217
|
+
var require_ZipEntry = __commonJS({
|
|
1218
|
+
"neozipkit/dist/core/ZipEntry.js"(exports2) {
|
|
1219
|
+
"use strict";
|
|
1220
|
+
var __importDefault2 = exports2 && exports2.__importDefault || function(mod) {
|
|
1221
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
1222
|
+
};
|
|
1223
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
1224
|
+
exports2.ZipEntry = void 0;
|
|
1225
|
+
var Errors_1 = __importDefault2(require_Errors());
|
|
1226
|
+
var Headers_1 = require_Headers();
|
|
1227
|
+
var Logger_12 = require_Logger();
|
|
1228
|
+
var ZipCrypto_12 = require_ZipCrypto();
|
|
1229
|
+
var VER_ENCODING = 30;
|
|
1230
|
+
var VER_EXTRACT = 10;
|
|
1231
|
+
var ZipEntry = class {
|
|
1232
|
+
static {
|
|
1233
|
+
__name(this, "ZipEntry");
|
|
1234
|
+
}
|
|
1235
|
+
/**
|
|
1236
|
+
* Creates a new ZIP entry
|
|
1237
|
+
* @param fname - Name of the file within the ZIP
|
|
1238
|
+
* @param comment - Optional comment for this entry
|
|
1239
|
+
* @param debug - Enable debug logging
|
|
1240
|
+
*/
|
|
1241
|
+
constructor(fname, comment, debug) {
|
|
1242
|
+
this.debug = true;
|
|
1243
|
+
this.verMadeBy = 0;
|
|
1244
|
+
this.verExtract = 0;
|
|
1245
|
+
this.bitFlags = 0;
|
|
1246
|
+
this.cmpMethod = 0;
|
|
1247
|
+
this.timeDateDOS = 0;
|
|
1248
|
+
this.crc = 0;
|
|
1249
|
+
this.compressedSize = 0;
|
|
1250
|
+
this.uncompressedSize = 0;
|
|
1251
|
+
this.volNumber = 0;
|
|
1252
|
+
this.intFileAttr = 0;
|
|
1253
|
+
this.extFileAttr = 0;
|
|
1254
|
+
this.localHdrOffset = 0;
|
|
1255
|
+
this.filename = "";
|
|
1256
|
+
this.extraField = null;
|
|
1257
|
+
this.comment = null;
|
|
1258
|
+
this.fileBuffer = null;
|
|
1259
|
+
this.cmpData = null;
|
|
1260
|
+
this.isEncrypted = false;
|
|
1261
|
+
this.isStrongEncrypt = false;
|
|
1262
|
+
this.encryptHdr = null;
|
|
1263
|
+
this.lastModTimeDate = 0;
|
|
1264
|
+
this.decrypt = null;
|
|
1265
|
+
this.isUpdated = true;
|
|
1266
|
+
this.isDirectory = false;
|
|
1267
|
+
this.isMetaData = false;
|
|
1268
|
+
this.platform = null;
|
|
1269
|
+
this.universalTime = null;
|
|
1270
|
+
this.uid = null;
|
|
1271
|
+
this.gid = null;
|
|
1272
|
+
this.sha256 = null;
|
|
1273
|
+
this.isSymlink = false;
|
|
1274
|
+
this.linkTarget = null;
|
|
1275
|
+
this.isHardLink = false;
|
|
1276
|
+
this.originalEntry = null;
|
|
1277
|
+
this.inode = null;
|
|
1278
|
+
this.isMSDOS = this.platform === null;
|
|
1279
|
+
this.isUnixLike = this.platform != null && this.platform !== "win32";
|
|
1280
|
+
this.isMacOS = this.platform != null && this.platform === "darwin";
|
|
1281
|
+
this.isLinux = this.platform != null && this.platform === "linux";
|
|
1282
|
+
this.VER_MADE_BY = (() => {
|
|
1283
|
+
switch (this.platform) {
|
|
1284
|
+
case "darwin":
|
|
1285
|
+
return Headers_1.FILE_SYSTEM.DARWIN << 8 | VER_ENCODING;
|
|
1286
|
+
case "win32":
|
|
1287
|
+
return Headers_1.FILE_SYSTEM.NTFS << 8 | VER_ENCODING;
|
|
1288
|
+
default:
|
|
1289
|
+
return Headers_1.FILE_SYSTEM.UNIX << 8 | VER_ENCODING;
|
|
1290
|
+
}
|
|
1291
|
+
})();
|
|
1292
|
+
this.filename = fname || "";
|
|
1293
|
+
this.comment = comment || null;
|
|
1294
|
+
this.debug = debug || false;
|
|
1295
|
+
this.bitFlags |= Headers_1.GP_FLAG.EFS;
|
|
1296
|
+
}
|
|
1297
|
+
/**
|
|
1298
|
+
* Reads ZIP entry data from a central directory buffer
|
|
1299
|
+
* @param data - Buffer containing central directory entry data
|
|
1300
|
+
* @returns Buffer positioned at start of next entry
|
|
1301
|
+
* @throws Error if central directory entry is invalid
|
|
1302
|
+
*/
|
|
1303
|
+
readZipEntry(data) {
|
|
1304
|
+
if (data.length < Headers_1.CENTRAL_DIR.SIZE) {
|
|
1305
|
+
throw new Error("Zip entry data is too small or corrupt");
|
|
1306
|
+
}
|
|
1307
|
+
if (data.readUInt32LE(0) !== Headers_1.CENTRAL_DIR.SIGNATURE) {
|
|
1308
|
+
throw new Error(Errors_1.default.INVALID_CEN);
|
|
1309
|
+
}
|
|
1310
|
+
this.verMadeBy = data.readUInt16LE(Headers_1.CENTRAL_DIR.VER_MADE);
|
|
1311
|
+
this.verExtract = data.readUInt16LE(Headers_1.CENTRAL_DIR.VER_EXT);
|
|
1312
|
+
this.bitFlags = data.readUInt16LE(Headers_1.CENTRAL_DIR.FLAGS);
|
|
1313
|
+
if ((this.bitFlags & Headers_1.GP_FLAG.ENCRYPTED) != 0) {
|
|
1314
|
+
this.isEncrypted = true;
|
|
1315
|
+
if ((this.bitFlags & Headers_1.GP_FLAG.STRONG_ENCRYPT) != 0)
|
|
1316
|
+
this.isStrongEncrypt = true;
|
|
1317
|
+
}
|
|
1318
|
+
this.cmpMethod = data.readUInt16LE(Headers_1.CENTRAL_DIR.CMP_METHOD);
|
|
1319
|
+
this.timeDateDOS = data.readUInt32LE(Headers_1.CENTRAL_DIR.TIMEDATE_DOS);
|
|
1320
|
+
this.crc = data.readUInt32LE(Headers_1.CENTRAL_DIR.CRC);
|
|
1321
|
+
this.compressedSize = data.readUInt32LE(Headers_1.CENTRAL_DIR.CMP_SIZE);
|
|
1322
|
+
this.uncompressedSize = data.readUInt32LE(Headers_1.CENTRAL_DIR.UNCMP_SIZE);
|
|
1323
|
+
this.volNumber = data.readUInt16LE(Headers_1.CENTRAL_DIR.DISK_NUM);
|
|
1324
|
+
this.intFileAttr = data.readUInt16LE(Headers_1.CENTRAL_DIR.INT_FILE_ATTR);
|
|
1325
|
+
this.extFileAttr = data.readUInt32LE(Headers_1.CENTRAL_DIR.EXT_FILE_ATTR);
|
|
1326
|
+
if (this.extFileAttr & Headers_1.DOS_FILE_ATTR.DIRECTORY)
|
|
1327
|
+
this.isDirectory = true;
|
|
1328
|
+
this.localHdrOffset = data.readUInt32LE(Headers_1.CENTRAL_DIR.LOCAL_HDR_OFFSET);
|
|
1329
|
+
let fnameLen = data.readUInt16LE(Headers_1.CENTRAL_DIR.FNAME_LEN);
|
|
1330
|
+
const filename = data.toString("utf8", Headers_1.CENTRAL_DIR.SIZE, Headers_1.CENTRAL_DIR.SIZE + fnameLen);
|
|
1331
|
+
this.filename = filename;
|
|
1332
|
+
if (this.filename.endsWith("/"))
|
|
1333
|
+
this.isDirectory = true;
|
|
1334
|
+
let extraLen = data.readUInt16LE(Headers_1.CENTRAL_DIR.EXTRA_LEN);
|
|
1335
|
+
if (extraLen > 0) {
|
|
1336
|
+
this.extraField = data.subarray(Headers_1.CENTRAL_DIR.SIZE + fnameLen, Headers_1.CENTRAL_DIR.SIZE + fnameLen + extraLen);
|
|
1337
|
+
for (let i = 0; i < extraLen; ) {
|
|
1338
|
+
let _id = this.extraField.readUInt16LE(i);
|
|
1339
|
+
let _len = this.extraField.readUInt16LE(i + 2);
|
|
1340
|
+
let _data = this.extraField.subarray(i + 4, i + 4 + _len);
|
|
1341
|
+
if (_id === Headers_1.HDR_ID.UNICODE_PATH && _len >= 5) {
|
|
1342
|
+
const version = _data.readUInt8(0);
|
|
1343
|
+
const nameCrc32 = _data.readUInt32LE(1);
|
|
1344
|
+
const fnameBuf = Buffer.from(this.filename);
|
|
1345
|
+
const calculatedCrc = (0, ZipCrypto_12.crc32)(fnameBuf);
|
|
1346
|
+
if (calculatedCrc === nameCrc32) {
|
|
1347
|
+
const unicodeName = _data.subarray(5).toString("utf8");
|
|
1348
|
+
this.filename = unicodeName;
|
|
1349
|
+
if (this.debug) {
|
|
1350
|
+
Logger_12.Logger.log(`Using Unicode Path: ${this.filename}`);
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
i += 4 + _len;
|
|
1355
|
+
}
|
|
1356
|
+
for (let i = 0; i < extraLen; ) {
|
|
1357
|
+
let _id = this.extraField.readUInt16LE(i);
|
|
1358
|
+
let _len = this.extraField.readUInt16LE(i + 2);
|
|
1359
|
+
let _data = this.extraField.subarray(i + 4, i + 4 + _len);
|
|
1360
|
+
if (_id === Headers_1.HDR_ID.SHA256) {
|
|
1361
|
+
if (_len === 64)
|
|
1362
|
+
this.sha256 = _data.toString("utf8");
|
|
1363
|
+
else
|
|
1364
|
+
this.sha256 = _data.toString("hex");
|
|
1365
|
+
} else if (_id === Headers_1.HDR_ID.UNV_TIME) {
|
|
1366
|
+
if (_len >= 5) {
|
|
1367
|
+
const flags = _data.readUInt8(0);
|
|
1368
|
+
if (flags & 1) {
|
|
1369
|
+
this.universalTime = _data.readUInt32LE(1);
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
} else if (_id === Headers_1.HDR_ID.UID_GID) {
|
|
1373
|
+
if (_len >= 5) {
|
|
1374
|
+
const version = _data.readUInt8(0);
|
|
1375
|
+
const uidSize = _data.readUInt8(1);
|
|
1376
|
+
if (uidSize <= 4 && _len >= 2 + uidSize) {
|
|
1377
|
+
this.uid = _data.readUIntLE(2, uidSize);
|
|
1378
|
+
if (_len >= 2 + uidSize + 1) {
|
|
1379
|
+
const gidSize = _data.readUInt8(2 + uidSize);
|
|
1380
|
+
if (gidSize <= 4 && _len >= 2 + uidSize + 1 + gidSize) {
|
|
1381
|
+
this.gid = _data.readUIntLE(2 + uidSize + 1, gidSize);
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
} else if (_id === Headers_1.HDR_ID.SYMLINK) {
|
|
1387
|
+
if (_len >= 3) {
|
|
1388
|
+
const version = _data.readUInt8(0);
|
|
1389
|
+
const targetLength = _data.readUInt16LE(1);
|
|
1390
|
+
if (targetLength > 0 && _len >= 3 + targetLength) {
|
|
1391
|
+
this.isSymlink = true;
|
|
1392
|
+
this.linkTarget = _data.subarray(3, 3 + targetLength).toString("utf8");
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
} else if (_id === Headers_1.HDR_ID.HARDLINK) {
|
|
1396
|
+
if (_len >= 11) {
|
|
1397
|
+
const version = _data.readUInt8(0);
|
|
1398
|
+
this.inode = _data.readUInt32LE(1);
|
|
1399
|
+
const originalLength = _data.readUInt16LE(5);
|
|
1400
|
+
if (originalLength > 0 && _len >= 7 + originalLength) {
|
|
1401
|
+
this.isHardLink = true;
|
|
1402
|
+
this.originalEntry = _data.subarray(7, 7 + originalLength).toString("utf8");
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
i += 4 + _len;
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
let comLen = data.readUInt16LE(Headers_1.CENTRAL_DIR.COMMENT_LEN);
|
|
1410
|
+
if (comLen > 0)
|
|
1411
|
+
this.comment = data.toString("utf8", Headers_1.CENTRAL_DIR.SIZE + fnameLen, Headers_1.CENTRAL_DIR.SIZE + fnameLen + comLen);
|
|
1412
|
+
if (this.debug)
|
|
1413
|
+
this.showVerboseInfo();
|
|
1414
|
+
let rawSize = Headers_1.CENTRAL_DIR.SIZE + fnameLen + extraLen + comLen;
|
|
1415
|
+
return data.subarray(rawSize);
|
|
1416
|
+
}
|
|
1417
|
+
/**
|
|
1418
|
+
* Checks if the filename contains characters that require Unicode handling
|
|
1419
|
+
* @returns true if the filename contains non-ASCII characters or special characters
|
|
1420
|
+
*/
|
|
1421
|
+
needsUnicodeHandling() {
|
|
1422
|
+
return /[^\x00-\x7E]|['"]/.test(this.filename);
|
|
1423
|
+
}
|
|
1424
|
+
/**
|
|
1425
|
+
* Adds UTF-8 Unicode Path field to a buffer
|
|
1426
|
+
* @param buffer - The buffer to write to
|
|
1427
|
+
* @param offset - The offset in the buffer to start writing
|
|
1428
|
+
* @returns The new offset after writing
|
|
1429
|
+
*/
|
|
1430
|
+
addUnicodePathField(buffer, offset) {
|
|
1431
|
+
const unicodePathBuf = Buffer.from(this.filename, "utf8");
|
|
1432
|
+
const asciiName = this.filename.replace(/[^\x00-\x7E]/g, "?");
|
|
1433
|
+
const asciiNameBuf = Buffer.from(asciiName, "ascii");
|
|
1434
|
+
const nameCrc32 = (0, ZipCrypto_12.crc32)(asciiNameBuf);
|
|
1435
|
+
const unicodePathLen = 5 + unicodePathBuf.length;
|
|
1436
|
+
buffer.writeUInt16LE(Headers_1.HDR_ID.UNICODE_PATH, offset);
|
|
1437
|
+
buffer.writeUInt16LE(unicodePathLen, offset + 2);
|
|
1438
|
+
buffer.writeUInt8(1, offset + 4);
|
|
1439
|
+
buffer.writeUInt32LE(nameCrc32, offset + 5);
|
|
1440
|
+
unicodePathBuf.copy(buffer, offset + 9);
|
|
1441
|
+
return offset + 4 + unicodePathLen;
|
|
1442
|
+
}
|
|
1443
|
+
/**
|
|
1444
|
+
* Creates a local header for this ZIP entry
|
|
1445
|
+
* @returns Buffer containing the local header data
|
|
1446
|
+
*/
|
|
1447
|
+
createLocalHdr() {
|
|
1448
|
+
let extraFieldLen = 0;
|
|
1449
|
+
const needsUnicode = this.needsUnicodeHandling();
|
|
1450
|
+
if (needsUnicode) {
|
|
1451
|
+
const unicodeNameLen = Buffer.from(this.filename, "utf8").length;
|
|
1452
|
+
extraFieldLen = 5 + unicodeNameLen + 4;
|
|
1453
|
+
}
|
|
1454
|
+
const data = Buffer.alloc(Headers_1.LOCAL_HDR.SIZE + this.filename.length + extraFieldLen);
|
|
1455
|
+
data.writeUInt32LE(Headers_1.LOCAL_HDR.SIGNATURE, 0);
|
|
1456
|
+
data.writeUInt16LE(VER_EXTRACT, Headers_1.LOCAL_HDR.VER_EXTRACT);
|
|
1457
|
+
data.writeUInt16LE(this.bitFlags >>> 0, Headers_1.LOCAL_HDR.FLAGS);
|
|
1458
|
+
data.writeUInt16LE(this.cmpMethod, Headers_1.LOCAL_HDR.COMPRESSION);
|
|
1459
|
+
data.writeUInt32LE(this.timeDateDOS >>> 0, Headers_1.LOCAL_HDR.TIMEDATE_DOS);
|
|
1460
|
+
data.writeUInt32LE(this.crc, Headers_1.LOCAL_HDR.CRC);
|
|
1461
|
+
data.writeUInt32LE(this.compressedSize, Headers_1.LOCAL_HDR.CMP_SIZE);
|
|
1462
|
+
data.writeUInt32LE(this.uncompressedSize, Headers_1.LOCAL_HDR.UNCMP_SIZE);
|
|
1463
|
+
data.writeUInt16LE(this.filename.length, Headers_1.LOCAL_HDR.FNAME_LEN);
|
|
1464
|
+
data.writeUInt16LE(extraFieldLen, Headers_1.LOCAL_HDR.EXTRA_LEN);
|
|
1465
|
+
const asciiName = this.filename.replace(/[^\x00-\x7E]/g, "?");
|
|
1466
|
+
const fnameBuf = Buffer.from(asciiName);
|
|
1467
|
+
fnameBuf.copy(data, Headers_1.LOCAL_HDR.SIZE);
|
|
1468
|
+
let extraOffset = Headers_1.LOCAL_HDR.SIZE + fnameBuf.length;
|
|
1469
|
+
if (needsUnicode) {
|
|
1470
|
+
extraOffset = this.addUnicodePathField(data, extraOffset);
|
|
1471
|
+
}
|
|
1472
|
+
return data;
|
|
1473
|
+
}
|
|
1474
|
+
/**
|
|
1475
|
+
* Creates a central directory entry for this ZIP entry
|
|
1476
|
+
* @returns Buffer containing the central directory entry data
|
|
1477
|
+
*/
|
|
1478
|
+
centralDirEntry() {
|
|
1479
|
+
const commentLen = this.comment ? Buffer.from(this.comment, "utf8").length : 0;
|
|
1480
|
+
const utfLen = this.universalTime ? 9 : 0;
|
|
1481
|
+
const uidgidLen = this.uid && this.gid ? 11 + 4 : 0;
|
|
1482
|
+
const sha256Buf = this.sha256 ? Buffer.from(this.sha256, "hex") : null;
|
|
1483
|
+
const sha256Len = sha256Buf ? sha256Buf.length + 4 : 0;
|
|
1484
|
+
const symlinkLen = this.isSymlink && this.linkTarget ? 4 + 1 + 2 + Buffer.byteLength(this.linkTarget, "utf8") : 0;
|
|
1485
|
+
const hardlinkLen = this.isHardLink && this.originalEntry && this.inode !== null ? 4 + 1 + 4 + 2 + Buffer.byteLength(this.originalEntry, "utf8") : 0;
|
|
1486
|
+
const needsUnicode = this.needsUnicodeHandling();
|
|
1487
|
+
let unicodePathLen = 0;
|
|
1488
|
+
if (needsUnicode) {
|
|
1489
|
+
const unicodeNameLen = Buffer.from(this.filename, "utf8").length;
|
|
1490
|
+
unicodePathLen = 5 + unicodeNameLen + 4;
|
|
1491
|
+
}
|
|
1492
|
+
const extraLen = utfLen + sha256Len + uidgidLen + symlinkLen + hardlinkLen + (needsUnicode ? unicodePathLen : 0);
|
|
1493
|
+
const asciiName = this.filename.replace(/[^\x00-\x7E]/g, "?");
|
|
1494
|
+
const fnameLen = asciiName.length;
|
|
1495
|
+
const data = Buffer.alloc(Headers_1.CENTRAL_DIR.SIZE + fnameLen + commentLen + extraLen);
|
|
1496
|
+
data.writeUInt32LE(Headers_1.CENTRAL_DIR.SIGNATURE, 0);
|
|
1497
|
+
data.writeUInt16LE(this.isUpdated ? this.VER_MADE_BY : this.verMadeBy, Headers_1.CENTRAL_DIR.VER_MADE);
|
|
1498
|
+
data.writeInt16LE(this.isUpdated ? VER_EXTRACT : this.verMadeBy, Headers_1.CENTRAL_DIR.VER_EXT);
|
|
1499
|
+
data.writeInt16LE(this.bitFlags >>> 0, Headers_1.CENTRAL_DIR.FLAGS);
|
|
1500
|
+
data.writeInt16LE(this.cmpMethod, Headers_1.CENTRAL_DIR.CMP_METHOD);
|
|
1501
|
+
data.writeUInt32LE(this.timeDateDOS >>> 0, Headers_1.CENTRAL_DIR.TIMEDATE_DOS);
|
|
1502
|
+
data.writeUInt32LE(this.crc, Headers_1.CENTRAL_DIR.CRC);
|
|
1503
|
+
data.writeUInt32LE(this.compressedSize, Headers_1.CENTRAL_DIR.CMP_SIZE);
|
|
1504
|
+
data.writeUInt32LE(this.uncompressedSize, Headers_1.CENTRAL_DIR.UNCMP_SIZE);
|
|
1505
|
+
data.writeUInt16LE(this.filename.length, Headers_1.CENTRAL_DIR.FNAME_LEN);
|
|
1506
|
+
data.writeUInt16LE(extraLen, Headers_1.CENTRAL_DIR.EXTRA_LEN);
|
|
1507
|
+
data.writeUInt16LE(commentLen, Headers_1.CENTRAL_DIR.COMMENT_LEN);
|
|
1508
|
+
data.writeUInt16LE(0, Headers_1.CENTRAL_DIR.DISK_NUM);
|
|
1509
|
+
data.writeUInt16LE(this.intFileAttr >>> 0, Headers_1.CENTRAL_DIR.INT_FILE_ATTR);
|
|
1510
|
+
data.writeUInt32LE(this.extFileAttr >>> 0, Headers_1.CENTRAL_DIR.EXT_FILE_ATTR);
|
|
1511
|
+
data.writeUInt32LE(this.localHdrOffset, Headers_1.CENTRAL_DIR.LOCAL_HDR_OFFSET);
|
|
1512
|
+
const fnameBuf = Buffer.from(asciiName);
|
|
1513
|
+
fnameBuf.copy(data, Headers_1.CENTRAL_DIR.SIZE);
|
|
1514
|
+
let currentOffset = Headers_1.CENTRAL_DIR.SIZE + fnameLen;
|
|
1515
|
+
if (commentLen > 0 && this.comment) {
|
|
1516
|
+
const commentBuf = Buffer.from(this.comment, "utf8");
|
|
1517
|
+
commentBuf.copy(data, currentOffset);
|
|
1518
|
+
currentOffset += commentLen;
|
|
1519
|
+
}
|
|
1520
|
+
let extraOffset = currentOffset;
|
|
1521
|
+
if (this.universalTime) {
|
|
1522
|
+
data.writeUInt16LE(Headers_1.HDR_ID.UNV_TIME, extraOffset);
|
|
1523
|
+
data.writeUInt16LE(5, extraOffset + 2);
|
|
1524
|
+
data.writeUInt8(1, extraOffset + 4);
|
|
1525
|
+
data.writeUInt32LE(Math.floor(Date.now() / 1e3), extraOffset + 5);
|
|
1526
|
+
extraOffset += 9;
|
|
1527
|
+
}
|
|
1528
|
+
if (sha256Buf) {
|
|
1529
|
+
data.writeUInt16LE(Headers_1.HDR_ID.SHA256, extraOffset);
|
|
1530
|
+
data.writeUInt16LE(sha256Buf.length, extraOffset + 2);
|
|
1531
|
+
sha256Buf.copy(data, extraOffset + 4);
|
|
1532
|
+
extraOffset += 4 + sha256Buf.length;
|
|
1533
|
+
}
|
|
1534
|
+
if (this.uid && this.gid) {
|
|
1535
|
+
data.writeUInt16LE(Headers_1.HDR_ID.UID_GID, extraOffset);
|
|
1536
|
+
data.writeUInt16LE(11, extraOffset + 2);
|
|
1537
|
+
data.writeUInt8(1, extraOffset + 4);
|
|
1538
|
+
data.writeUInt8(4, extraOffset + 5);
|
|
1539
|
+
data.writeUInt32LE(this.uid, extraOffset + 6);
|
|
1540
|
+
data.writeUInt8(4, extraOffset + 10);
|
|
1541
|
+
data.writeUInt32LE(this.gid, extraOffset + 11);
|
|
1542
|
+
extraOffset += 15;
|
|
1543
|
+
}
|
|
1544
|
+
if (this.isSymlink && this.linkTarget) {
|
|
1545
|
+
const targetBuf = Buffer.from(this.linkTarget, "utf8");
|
|
1546
|
+
const dataLen = 1 + 2 + targetBuf.length;
|
|
1547
|
+
data.writeUInt16LE(Headers_1.HDR_ID.SYMLINK, extraOffset);
|
|
1548
|
+
data.writeUInt16LE(dataLen, extraOffset + 2);
|
|
1549
|
+
data.writeUInt8(1, extraOffset + 4);
|
|
1550
|
+
data.writeUInt16LE(targetBuf.length, extraOffset + 5);
|
|
1551
|
+
targetBuf.copy(data, extraOffset + 7);
|
|
1552
|
+
extraOffset += 4 + dataLen;
|
|
1553
|
+
}
|
|
1554
|
+
if (this.isHardLink && this.originalEntry && this.inode !== null) {
|
|
1555
|
+
const originalBuf = Buffer.from(this.originalEntry, "utf8");
|
|
1556
|
+
const dataLen = 1 + 4 + 2 + originalBuf.length;
|
|
1557
|
+
data.writeUInt16LE(Headers_1.HDR_ID.HARDLINK, extraOffset);
|
|
1558
|
+
data.writeUInt16LE(dataLen, extraOffset + 2);
|
|
1559
|
+
data.writeUInt8(1, extraOffset + 4);
|
|
1560
|
+
data.writeUInt32LE(this.inode, extraOffset + 5);
|
|
1561
|
+
data.writeUInt16LE(originalBuf.length, extraOffset + 9);
|
|
1562
|
+
originalBuf.copy(data, extraOffset + 11);
|
|
1563
|
+
extraOffset += 4 + dataLen;
|
|
1564
|
+
}
|
|
1565
|
+
if (needsUnicode) {
|
|
1566
|
+
extraOffset = this.addUnicodePathField(data, extraOffset);
|
|
1567
|
+
}
|
|
1568
|
+
return data;
|
|
1569
|
+
}
|
|
1570
|
+
// ======================================
|
|
1571
|
+
// Routines to handle the details of the Zip Entry
|
|
1572
|
+
// ======================================
|
|
1573
|
+
/**
|
|
1574
|
+
* Sets the DOS date/time for this entry
|
|
1575
|
+
* @param date - Date to convert to DOS format
|
|
1576
|
+
* @returns number - DOS format date/time
|
|
1577
|
+
*/
|
|
1578
|
+
setDateTime(date) {
|
|
1579
|
+
if (!date)
|
|
1580
|
+
return 0;
|
|
1581
|
+
const year = date.getFullYear() - 1980;
|
|
1582
|
+
const month = date.getMonth() + 1;
|
|
1583
|
+
const day = date.getDate();
|
|
1584
|
+
const hour = date.getHours();
|
|
1585
|
+
const minute = date.getMinutes();
|
|
1586
|
+
const second = date.getSeconds();
|
|
1587
|
+
const datePart = (year & 127) << 9 | (month & 15) << 5 | day & 31;
|
|
1588
|
+
const timePart = (hour & 31) << 11 | (minute & 63) << 5 | second >> 1 & 31;
|
|
1589
|
+
const time = datePart << 16 | timePart;
|
|
1590
|
+
return time;
|
|
1591
|
+
}
|
|
1592
|
+
/**
|
|
1593
|
+
* Converts DOS date/time to JavaScript Date
|
|
1594
|
+
* @param timeStamp - DOS format date/time
|
|
1595
|
+
* @returns Date object or null if timestamp is 0
|
|
1596
|
+
*/
|
|
1597
|
+
parseDateTime(timeStamp) {
|
|
1598
|
+
if (timeStamp == 0)
|
|
1599
|
+
return null;
|
|
1600
|
+
const datePart = timeStamp >> 16 & 65535;
|
|
1601
|
+
const year = (datePart >> 9 & 127) + 1980;
|
|
1602
|
+
const month = (datePart >> 5 & 15) - 1;
|
|
1603
|
+
const day = datePart & 31;
|
|
1604
|
+
const timePart = timeStamp & 65535;
|
|
1605
|
+
const hour = timePart >> 11 & 31;
|
|
1606
|
+
const minute = timePart >> 5 & 63;
|
|
1607
|
+
const second = (timePart & 31) << 1;
|
|
1608
|
+
return new Date(year, month, day, hour, minute, second);
|
|
1609
|
+
}
|
|
1610
|
+
/**
|
|
1611
|
+
* Formats the entry's date in local format
|
|
1612
|
+
* @returns String in MM/DD/YYYY format or "--/--/----" if no date
|
|
1613
|
+
*/
|
|
1614
|
+
toLocalDateString() {
|
|
1615
|
+
let _timeDate = this.parseDateTime(this.timeDateDOS);
|
|
1616
|
+
if (_timeDate === null)
|
|
1617
|
+
return "--/--/----";
|
|
1618
|
+
return _timeDate.toLocaleDateString("en-US", {
|
|
1619
|
+
year: "numeric",
|
|
1620
|
+
month: "2-digit",
|
|
1621
|
+
day: "2-digit"
|
|
1622
|
+
}).slice(0, 10);
|
|
1623
|
+
}
|
|
1624
|
+
/**
|
|
1625
|
+
* Formats the entry's time
|
|
1626
|
+
* @returns String in HH:MM format or "--:--" if no time
|
|
1627
|
+
*/
|
|
1628
|
+
toTimeString() {
|
|
1629
|
+
let _timeDate = this.parseDateTime(this.timeDateDOS);
|
|
1630
|
+
if (_timeDate === null)
|
|
1631
|
+
return "--:--";
|
|
1632
|
+
return _timeDate.toTimeString().slice(0, 5);
|
|
1633
|
+
}
|
|
1634
|
+
/**
|
|
1635
|
+
* Formats the entry's date and time in local format
|
|
1636
|
+
* @returns String like "Jan 01, 2024 13:45:30" or "--/--/-- --:--" if no date/time
|
|
1637
|
+
*/
|
|
1638
|
+
toFormattedDateString() {
|
|
1639
|
+
let _timeDate = this.parseDateTime(this.timeDateDOS);
|
|
1640
|
+
if (_timeDate == null)
|
|
1641
|
+
return "--/--/-- --:--";
|
|
1642
|
+
const datePart = _timeDate.toLocaleDateString("en-US", {
|
|
1643
|
+
year: "numeric",
|
|
1644
|
+
month: "short",
|
|
1645
|
+
day: "2-digit"
|
|
1646
|
+
});
|
|
1647
|
+
const timePart = _timeDate.toLocaleTimeString("en-US", {
|
|
1648
|
+
hour: "2-digit",
|
|
1649
|
+
minute: "2-digit",
|
|
1650
|
+
second: "2-digit",
|
|
1651
|
+
hour12: false
|
|
1652
|
+
});
|
|
1653
|
+
return `${datePart} ${timePart}`;
|
|
1654
|
+
}
|
|
1655
|
+
/**
|
|
1656
|
+
* Formats the entry's date and time in UTC
|
|
1657
|
+
* @returns String like "Jan 01, 2024 13:45:30 UTC" or "--/--/-- --:--" if no date/time
|
|
1658
|
+
*/
|
|
1659
|
+
toFormattedUTCDateString() {
|
|
1660
|
+
let _timeDate = this.parseDateTime(this.timeDateDOS);
|
|
1661
|
+
if (_timeDate == null)
|
|
1662
|
+
return "--/--/-- --:--";
|
|
1663
|
+
const datePart = _timeDate.toLocaleDateString("en-US", {
|
|
1664
|
+
year: "numeric",
|
|
1665
|
+
month: "short",
|
|
1666
|
+
day: "2-digit",
|
|
1667
|
+
timeZone: "UTC"
|
|
1668
|
+
});
|
|
1669
|
+
const timePart = _timeDate.toLocaleTimeString("en-US", {
|
|
1670
|
+
hour: "2-digit",
|
|
1671
|
+
minute: "2-digit",
|
|
1672
|
+
second: "2-digit",
|
|
1673
|
+
hour12: false,
|
|
1674
|
+
timeZone: "UTC"
|
|
1675
|
+
});
|
|
1676
|
+
return `${datePart} ${timePart} UTC`;
|
|
1677
|
+
}
|
|
1678
|
+
/**
|
|
1679
|
+
* Converts compression method code to human-readable string
|
|
1680
|
+
* @returns String describing the compression method
|
|
1681
|
+
*/
|
|
1682
|
+
cmpMethodToString() {
|
|
1683
|
+
switch (this.cmpMethod) {
|
|
1684
|
+
case Headers_1.CMP_METHOD.STORED:
|
|
1685
|
+
return "Stored";
|
|
1686
|
+
case Headers_1.CMP_METHOD.SHRUNK:
|
|
1687
|
+
return "Shrunk";
|
|
1688
|
+
case Headers_1.CMP_METHOD.REDUCED1:
|
|
1689
|
+
return "Reduced-1";
|
|
1690
|
+
case Headers_1.CMP_METHOD.REDUCED2:
|
|
1691
|
+
return "Reduced-2";
|
|
1692
|
+
case Headers_1.CMP_METHOD.REDUCED3:
|
|
1693
|
+
return "Reduced-3";
|
|
1694
|
+
case Headers_1.CMP_METHOD.REDUCED4:
|
|
1695
|
+
return "Reduced-4";
|
|
1696
|
+
case Headers_1.CMP_METHOD.IMPLODED:
|
|
1697
|
+
return "Imploded";
|
|
1698
|
+
case Headers_1.CMP_METHOD.DEFLATED:
|
|
1699
|
+
switch (this.bitFlags & 6) {
|
|
1700
|
+
case 0:
|
|
1701
|
+
return "Deflate-N";
|
|
1702
|
+
case 2:
|
|
1703
|
+
return "Deflate-M";
|
|
1704
|
+
case 4:
|
|
1705
|
+
return "Deflate-F";
|
|
1706
|
+
case 6:
|
|
1707
|
+
return "Deflate-S";
|
|
1708
|
+
}
|
|
1709
|
+
case Headers_1.CMP_METHOD.ENHANCED_DEFLATE:
|
|
1710
|
+
return "Deflate-Enh";
|
|
1711
|
+
case Headers_1.CMP_METHOD.IBM_TERSE:
|
|
1712
|
+
return "PKDCL-LZ77";
|
|
1713
|
+
case Headers_1.CMP_METHOD.ZSTD:
|
|
1714
|
+
return "Zstandard";
|
|
1715
|
+
default:
|
|
1716
|
+
return "Unknown";
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
/**
|
|
1720
|
+
* Converts file system code to human-readable string
|
|
1721
|
+
* @returns String describing the file system
|
|
1722
|
+
*/
|
|
1723
|
+
fileSystemToString() {
|
|
1724
|
+
switch (this.verMadeBy >> 8) {
|
|
1725
|
+
case Headers_1.FILE_SYSTEM.MSDOS:
|
|
1726
|
+
return "MS-DOS";
|
|
1727
|
+
case Headers_1.FILE_SYSTEM.AMIGA:
|
|
1728
|
+
return "Amiga";
|
|
1729
|
+
case Headers_1.FILE_SYSTEM.OPENVMS:
|
|
1730
|
+
return "OpenVMS";
|
|
1731
|
+
case Headers_1.FILE_SYSTEM.UNIX:
|
|
1732
|
+
return "Unix";
|
|
1733
|
+
case Headers_1.FILE_SYSTEM.VM_CMS:
|
|
1734
|
+
return "VM/CMS";
|
|
1735
|
+
case Headers_1.FILE_SYSTEM.ATARI:
|
|
1736
|
+
return "Atari ST";
|
|
1737
|
+
case Headers_1.FILE_SYSTEM.OS2:
|
|
1738
|
+
return "OS/2 HPFS";
|
|
1739
|
+
case Headers_1.FILE_SYSTEM.MAC:
|
|
1740
|
+
return "Macintosh";
|
|
1741
|
+
case Headers_1.FILE_SYSTEM.CP_M:
|
|
1742
|
+
return "CP/M";
|
|
1743
|
+
case Headers_1.FILE_SYSTEM.NTFS:
|
|
1744
|
+
return "Windows NTFS";
|
|
1745
|
+
case Headers_1.FILE_SYSTEM.MVS:
|
|
1746
|
+
return "MVS (OS/390 - Z/OS)";
|
|
1747
|
+
case Headers_1.FILE_SYSTEM.VSE:
|
|
1748
|
+
return "VSE";
|
|
1749
|
+
case Headers_1.FILE_SYSTEM.ACORN:
|
|
1750
|
+
return "Acorn Risc";
|
|
1751
|
+
case Headers_1.FILE_SYSTEM.ALTMVS:
|
|
1752
|
+
return "Alternate MVS";
|
|
1753
|
+
case Headers_1.FILE_SYSTEM.BEOS:
|
|
1754
|
+
return "BeOS";
|
|
1755
|
+
case Headers_1.FILE_SYSTEM.TANDEM:
|
|
1756
|
+
return "Tandem";
|
|
1757
|
+
case Headers_1.FILE_SYSTEM.OS400:
|
|
1758
|
+
return "OS/400";
|
|
1759
|
+
case Headers_1.FILE_SYSTEM.DARWIN:
|
|
1760
|
+
return "Apple OS/X (Darwin)";
|
|
1761
|
+
default:
|
|
1762
|
+
return "Unknown";
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
/**
|
|
1766
|
+
* Converts MS-DOS file attributes to string representation
|
|
1767
|
+
* @returns String like "----" where R=readonly, H=hidden, S=system, A=archive
|
|
1768
|
+
*/
|
|
1769
|
+
dosAttributesToString() {
|
|
1770
|
+
let dosAttr = this.extFileAttr & 65535;
|
|
1771
|
+
if (dosAttr === 0)
|
|
1772
|
+
return "none";
|
|
1773
|
+
let attrs = "";
|
|
1774
|
+
attrs += dosAttr & Headers_1.DOS_FILE_ATTR.READONLY ? "r" : "-";
|
|
1775
|
+
attrs += dosAttr & Headers_1.DOS_FILE_ATTR.HIDDEN ? "h" : "-";
|
|
1776
|
+
attrs += dosAttr & Headers_1.DOS_FILE_ATTR.SYSTEM ? "s" : "-";
|
|
1777
|
+
attrs += dosAttr & Headers_1.DOS_FILE_ATTR.DIRECTORY ? "d" : "-";
|
|
1778
|
+
attrs += dosAttr & Headers_1.DOS_FILE_ATTR.ARCHIVE ? "a" : "-";
|
|
1779
|
+
return attrs;
|
|
1780
|
+
}
|
|
1781
|
+
/**
|
|
1782
|
+
* Outputs detailed information about this entry for debugging
|
|
1783
|
+
* Includes compression, encryption, timestamps, and extra fields
|
|
1784
|
+
*/
|
|
1785
|
+
showVerboseInfo() {
|
|
1786
|
+
Logger_12.Logger.log("=== Central Directory Entry (%s) ===", this.filename);
|
|
1787
|
+
Logger_12.Logger.log("unzip from start of archive: ", this.localHdrOffset);
|
|
1788
|
+
Logger_12.Logger.log("File system or operating system of origin: ", this.fileSystemToString());
|
|
1789
|
+
Logger_12.Logger.log("Version of encoding software: ", this.verMadeBy);
|
|
1790
|
+
Logger_12.Logger.log("Compression Method: ", this.cmpMethodToString());
|
|
1791
|
+
Logger_12.Logger.log("File Security Status: ", this.bitFlags & Headers_1.GP_FLAG.ENCRYPTED ? this.bitFlags & Headers_1.GP_FLAG.STRONG_ENCRYPT ? "Strong Encrypt" : "Encrypted" : "Not Encrypted");
|
|
1792
|
+
Logger_12.Logger.log("File Modified (DOS date/time) ", this.toFormattedDateString());
|
|
1793
|
+
Logger_12.Logger.log("File Modified (UTC) ", this.toFormattedUTCDateString());
|
|
1794
|
+
Logger_12.Logger.log("Compressed Size: ", this.compressedSize);
|
|
1795
|
+
Logger_12.Logger.log("UnCompressed Size: ", this.uncompressedSize);
|
|
1796
|
+
Logger_12.Logger.log(`32-bit CRC value (hex): ${this.crc.toString(16).padStart(8, "0")}`);
|
|
1797
|
+
Logger_12.Logger.log("Length of extra field: ", this.extraField?.length ?? 0);
|
|
1798
|
+
Logger_12.Logger.log("Length of file comment: ", this.comment?.length ?? 0);
|
|
1799
|
+
Logger_12.Logger.log("Unix File Attributes: ");
|
|
1800
|
+
Logger_12.Logger.log("MS-DOS File Attributes: ", this.dosAttributesToString());
|
|
1801
|
+
if (this.extraField) {
|
|
1802
|
+
Logger_12.Logger.log("\nThe Central-Directory Extra Field contains:");
|
|
1803
|
+
try {
|
|
1804
|
+
for (let i = 0; i < this.extraField.length; ) {
|
|
1805
|
+
if (i + 4 > this.extraField.length) {
|
|
1806
|
+
Logger_12.Logger.log(` Warning: Truncated extra field at offset ${i}`);
|
|
1807
|
+
break;
|
|
1808
|
+
}
|
|
1809
|
+
let _id = this.extraField.readUInt16LE(i);
|
|
1810
|
+
let _idStr = _id.toString(16).padStart(4, "0");
|
|
1811
|
+
let _len = this.extraField.readUInt16LE(i + 2);
|
|
1812
|
+
if (_len < 0 || i + 4 + _len > this.extraField.length) {
|
|
1813
|
+
Logger_12.Logger.log(` Warning: Invalid extra field length (${_len}) at offset ${i} for ID ${_idStr}`);
|
|
1814
|
+
break;
|
|
1815
|
+
}
|
|
1816
|
+
let _data = this.extraField.subarray(i + 4, i + 4 + _len);
|
|
1817
|
+
try {
|
|
1818
|
+
if (_id === Headers_1.HDR_ID.SHA256) {
|
|
1819
|
+
Logger_12.Logger.log(` ID[0x${_idStr}] NeoZip-SHA256: ${_data.toString("hex")}`);
|
|
1820
|
+
} else if (_id === Headers_1.HDR_ID.UNV_TIME) {
|
|
1821
|
+
if (_len >= 5) {
|
|
1822
|
+
const flags = _data.readUInt8(0);
|
|
1823
|
+
const timestamp = _data.readUInt32LE(1);
|
|
1824
|
+
const date = new Date(timestamp * 1e3);
|
|
1825
|
+
Logger_12.Logger.log(` ID[0x${_idStr}] Universal Time: flags=${flags}, time=${date.toISOString()}`);
|
|
1826
|
+
} else {
|
|
1827
|
+
Logger_12.Logger.log(` ID[0x${_idStr}] Universal Time: (invalid length ${_len})`);
|
|
1828
|
+
}
|
|
1829
|
+
} else if (_id === Headers_1.HDR_ID.UID_GID) {
|
|
1830
|
+
if (_len >= 5) {
|
|
1831
|
+
const version = _data.readUInt8(0);
|
|
1832
|
+
const uidSize = _data.readUInt8(1);
|
|
1833
|
+
if (2 + uidSize > _len) {
|
|
1834
|
+
Logger_12.Logger.log(` ID[0x${_idStr}] Unix UID/GID: (invalid UID size ${uidSize})`);
|
|
1835
|
+
} else {
|
|
1836
|
+
const uid = _data.readUIntLE(2, Math.min(uidSize, 4));
|
|
1837
|
+
let gid = 0;
|
|
1838
|
+
if (2 + uidSize + 1 < _len) {
|
|
1839
|
+
const gidSize = _data.readUInt8(2 + uidSize);
|
|
1840
|
+
if (2 + uidSize + 1 + gidSize <= _len) {
|
|
1841
|
+
gid = _data.readUIntLE(2 + uidSize + 1, Math.min(gidSize, 4));
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
Logger_12.Logger.log(` ID[0x${_idStr}] Unix UID/GID: version=${version}, uid=${uid}, gid=${gid}`);
|
|
1845
|
+
}
|
|
1846
|
+
} else {
|
|
1847
|
+
Logger_12.Logger.log(` ID[0x${_idStr}] Unix UID/GID: (invalid length ${_len})`);
|
|
1848
|
+
}
|
|
1849
|
+
} else if (_id === Headers_1.HDR_ID.SYMLINK) {
|
|
1850
|
+
if (_len >= 3) {
|
|
1851
|
+
const version = _data.readUInt8(0);
|
|
1852
|
+
const targetLength = _data.readUInt16LE(1);
|
|
1853
|
+
if (targetLength > 0 && _len >= 3 + targetLength) {
|
|
1854
|
+
const target = _data.subarray(3, 3 + targetLength).toString("utf8");
|
|
1855
|
+
Logger_12.Logger.log(` ID[0x${_idStr}] Symbolic Link: version=${version}, target="${target}"`);
|
|
1856
|
+
} else {
|
|
1857
|
+
Logger_12.Logger.log(` ID[0x${_idStr}] Symbolic Link: (invalid target length ${targetLength})`);
|
|
1858
|
+
}
|
|
1859
|
+
} else {
|
|
1860
|
+
Logger_12.Logger.log(` ID[0x${_idStr}] Symbolic Link: (invalid length ${_len})`);
|
|
1861
|
+
}
|
|
1862
|
+
} else if (_id === Headers_1.HDR_ID.HARDLINK) {
|
|
1863
|
+
if (_len >= 11) {
|
|
1864
|
+
const version = _data.readUInt8(0);
|
|
1865
|
+
const inode = _data.readUInt32LE(1);
|
|
1866
|
+
const originalLength = _data.readUInt16LE(5);
|
|
1867
|
+
if (originalLength > 0 && _len >= 7 + originalLength) {
|
|
1868
|
+
const original = _data.subarray(7, 7 + originalLength).toString("utf8");
|
|
1869
|
+
Logger_12.Logger.log(` ID[0x${_idStr}] Hard Link: version=${version}, inode=${inode}, original="${original}"`);
|
|
1870
|
+
} else {
|
|
1871
|
+
Logger_12.Logger.log(` ID[0x${_idStr}] Hard Link: (invalid original length ${originalLength})`);
|
|
1872
|
+
}
|
|
1873
|
+
} else {
|
|
1874
|
+
Logger_12.Logger.log(` ID[0x${_idStr}] Hard Link: (invalid length ${_len})`);
|
|
1875
|
+
}
|
|
1876
|
+
} else if (_id === Headers_1.HDR_ID.UNICODE_PATH) {
|
|
1877
|
+
if (_len >= 5) {
|
|
1878
|
+
const version = _data.readUInt8(0);
|
|
1879
|
+
const nameCrc32 = _data.readUInt32LE(1);
|
|
1880
|
+
const unicodeName = _data.subarray(5).toString("utf8");
|
|
1881
|
+
const fnameBuf = Buffer.from(this.filename);
|
|
1882
|
+
const calculatedCrc = (0, ZipCrypto_12.crc32)(fnameBuf);
|
|
1883
|
+
const crcMatch = nameCrc32 === calculatedCrc ? "MATCH" : "MISMATCH";
|
|
1884
|
+
Logger_12.Logger.log(` ID[0x${_idStr}] Unicode Path: version=${version}, CRC32=${nameCrc32.toString(16)} (${crcMatch})`);
|
|
1885
|
+
Logger_12.Logger.log(` Path: "${unicodeName}"`);
|
|
1886
|
+
} else {
|
|
1887
|
+
Logger_12.Logger.log(` ID[0x${_idStr}] Unicode Path: (invalid length ${_len})`);
|
|
1888
|
+
}
|
|
1889
|
+
} else if (_id === Headers_1.HDR_ID.ZIP64) {
|
|
1890
|
+
Logger_12.Logger.log(` ID[0x${_idStr}] ZIP64 Extended Information:`);
|
|
1891
|
+
if (_len >= 8) {
|
|
1892
|
+
let offset = 0;
|
|
1893
|
+
if (offset + 8 <= _len) {
|
|
1894
|
+
const uncompressedSize = _data.readBigUInt64LE(offset);
|
|
1895
|
+
Logger_12.Logger.log(` Uncompressed Size (ZIP64): ${uncompressedSize.toString()} bytes`);
|
|
1896
|
+
offset += 8;
|
|
1897
|
+
}
|
|
1898
|
+
if (offset + 8 <= _len) {
|
|
1899
|
+
const compressedSize = _data.readBigUInt64LE(offset);
|
|
1900
|
+
Logger_12.Logger.log(` Compressed Size (ZIP64): ${compressedSize.toString()} bytes`);
|
|
1901
|
+
offset += 8;
|
|
1902
|
+
}
|
|
1903
|
+
if (offset + 8 <= _len) {
|
|
1904
|
+
const localHeaderOffset = _data.readBigUInt64LE(offset);
|
|
1905
|
+
Logger_12.Logger.log(` Local Header Offset (ZIP64): ${localHeaderOffset.toString()}`);
|
|
1906
|
+
offset += 8;
|
|
1907
|
+
}
|
|
1908
|
+
if (offset + 4 <= _len) {
|
|
1909
|
+
const diskNumber = _data.readUInt32LE(offset);
|
|
1910
|
+
Logger_12.Logger.log(` Disk Number (ZIP64): ${diskNumber}`);
|
|
1911
|
+
}
|
|
1912
|
+
} else {
|
|
1913
|
+
Logger_12.Logger.log(` ZIP64 Extended Information: (invalid length ${_len})`);
|
|
1914
|
+
}
|
|
1915
|
+
} else {
|
|
1916
|
+
const preview = _len > 0 ? _data.slice(0, Math.min(16, _len)).toString("hex") : "";
|
|
1917
|
+
Logger_12.Logger.log(` ID[0x${_idStr}] Unknown field: length=${_len} bytes${preview ? ", data=" + preview + "..." : ""}`);
|
|
1918
|
+
}
|
|
1919
|
+
} catch (error) {
|
|
1920
|
+
Logger_12.Logger.log(` Error parsing extra field ID[0x${_idStr}]: ${error.message}`);
|
|
1921
|
+
}
|
|
1922
|
+
i += 4 + _len;
|
|
1923
|
+
}
|
|
1924
|
+
} catch (error) {
|
|
1925
|
+
Logger_12.Logger.log(` Error parsing extra fields: ${error.message}`);
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
Logger_12.Logger.log("\n");
|
|
1929
|
+
}
|
|
1930
|
+
};
|
|
1931
|
+
exports2.default = ZipEntry;
|
|
1932
|
+
exports2.ZipEntry = ZipEntry;
|
|
1933
|
+
}
|
|
1934
|
+
});
|
|
1935
|
+
|
|
1936
|
+
// neozipkit/dist/types/index.js
|
|
1937
|
+
var require_types2 = __commonJS({
|
|
1938
|
+
"neozipkit/dist/types/index.js"(exports2) {
|
|
1939
|
+
"use strict";
|
|
1940
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
1941
|
+
exports2.NEOZIPKIT_INFO = exports2.NETWORKS = void 0;
|
|
1942
|
+
exports2.NETWORKS = {
|
|
1943
|
+
"base": {
|
|
1944
|
+
name: "Base Mainnet",
|
|
1945
|
+
rpcUrl: "https://mainnet.base.org",
|
|
1946
|
+
chainId: 8453,
|
|
1947
|
+
explorerUrl: "https://basescan.org"
|
|
1948
|
+
},
|
|
1949
|
+
"base-sepolia": {
|
|
1950
|
+
name: "Base Sepolia",
|
|
1951
|
+
rpcUrl: "https://sepolia.base.org",
|
|
1952
|
+
chainId: 84532,
|
|
1953
|
+
explorerUrl: "https://sepolia.basescan.org"
|
|
1954
|
+
},
|
|
1955
|
+
"base-goerli": {
|
|
1956
|
+
name: "Base Goerli",
|
|
1957
|
+
rpcUrl: "https://goerli.base.org",
|
|
1958
|
+
chainId: 84531,
|
|
1959
|
+
explorerUrl: "https://goerli.basescan.org"
|
|
1960
|
+
},
|
|
1961
|
+
"localhost": {
|
|
1962
|
+
name: "Localhost",
|
|
1963
|
+
rpcUrl: "http://localhost:8545",
|
|
1964
|
+
chainId: 31337,
|
|
1965
|
+
explorerUrl: "http://localhost:8545"
|
|
1966
|
+
}
|
|
1967
|
+
};
|
|
1968
|
+
exports2.NEOZIPKIT_INFO = {
|
|
1969
|
+
version: "0.70.0-alpha",
|
|
1970
|
+
releaseDate: "2024-10-04"
|
|
1971
|
+
};
|
|
1972
|
+
}
|
|
1973
|
+
});
|
|
1974
|
+
|
|
1975
|
+
// neozipkit/dist/core/components/HashCalculator.js
|
|
1976
|
+
var require_HashCalculator = __commonJS({
|
|
1977
|
+
"neozipkit/dist/core/components/HashCalculator.js"(exports2) {
|
|
1978
|
+
"use strict";
|
|
1979
|
+
var __createBinding2 = exports2 && exports2.__createBinding || (Object.create ? function(o, m, k, k2) {
|
|
1980
|
+
if (k2 === void 0)
|
|
1981
|
+
k2 = k;
|
|
1982
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
1983
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
1984
|
+
desc = { enumerable: true, get: function() {
|
|
1985
|
+
return m[k];
|
|
1986
|
+
} };
|
|
1987
|
+
}
|
|
1988
|
+
Object.defineProperty(o, k2, desc);
|
|
1989
|
+
} : function(o, m, k, k2) {
|
|
1990
|
+
if (k2 === void 0)
|
|
1991
|
+
k2 = k;
|
|
1992
|
+
o[k2] = m[k];
|
|
1993
|
+
});
|
|
1994
|
+
var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o, v) {
|
|
1995
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
1996
|
+
} : function(o, v) {
|
|
1997
|
+
o["default"] = v;
|
|
1998
|
+
});
|
|
1999
|
+
var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ function() {
|
|
2000
|
+
var ownKeys = /* @__PURE__ */ __name(function(o) {
|
|
2001
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
2002
|
+
var ar = [];
|
|
2003
|
+
for (var k in o2)
|
|
2004
|
+
if (Object.prototype.hasOwnProperty.call(o2, k))
|
|
2005
|
+
ar[ar.length] = k;
|
|
2006
|
+
return ar;
|
|
2007
|
+
};
|
|
2008
|
+
return ownKeys(o);
|
|
2009
|
+
}, "ownKeys");
|
|
2010
|
+
return function(mod) {
|
|
2011
|
+
if (mod && mod.__esModule)
|
|
2012
|
+
return mod;
|
|
2013
|
+
var result = {};
|
|
2014
|
+
if (mod != null) {
|
|
2015
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++)
|
|
2016
|
+
if (k[i] !== "default")
|
|
2017
|
+
__createBinding2(result, mod, k[i]);
|
|
2018
|
+
}
|
|
2019
|
+
__setModuleDefault(result, mod);
|
|
2020
|
+
return result;
|
|
2021
|
+
};
|
|
2022
|
+
}();
|
|
2023
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2024
|
+
exports2.HashCalculator = void 0;
|
|
2025
|
+
var crypto = __importStar(require("crypto"));
|
|
2026
|
+
var ZipCrypto_12 = require_ZipCrypto();
|
|
2027
|
+
var HashCalculator = class _HashCalculator {
|
|
2028
|
+
static {
|
|
2029
|
+
__name(this, "HashCalculator");
|
|
2030
|
+
}
|
|
2031
|
+
/**
|
|
2032
|
+
* Creates a new HashCalculator instance
|
|
2033
|
+
* @param options - Configuration options:
|
|
2034
|
+
* - useSHA256: Enable SHA-256 calculation for incremental mode (default: false)
|
|
2035
|
+
* - enableAccumulation: Enable hash accumulation mode (default: false)
|
|
2036
|
+
*/
|
|
2037
|
+
constructor(options) {
|
|
2038
|
+
this.crc32State = ~0;
|
|
2039
|
+
this.sha256Hash = null;
|
|
2040
|
+
this.useSHA256 = false;
|
|
2041
|
+
this.hashes = [];
|
|
2042
|
+
this.xorResult = Buffer.alloc(32, 0);
|
|
2043
|
+
this.enableAccumulation = false;
|
|
2044
|
+
this.merkleLeaves = [];
|
|
2045
|
+
this.merkleLayers = [];
|
|
2046
|
+
this.merkleOptions = {
|
|
2047
|
+
hashLeaves: false,
|
|
2048
|
+
sortLeaves: true,
|
|
2049
|
+
sortPairs: true,
|
|
2050
|
+
duplicateOdd: true
|
|
2051
|
+
};
|
|
2052
|
+
this.useSHA256 = options?.useSHA256 || false;
|
|
2053
|
+
this.enableAccumulation = options?.enableAccumulation || false;
|
|
2054
|
+
if (this.useSHA256) {
|
|
2055
|
+
this.sha256Hash = crypto.createHash("sha256");
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
// ============================================================================
|
|
2059
|
+
// Incremental Hash Calculation Methods (from StreamHashCalculator)
|
|
2060
|
+
// ============================================================================
|
|
2061
|
+
/**
|
|
2062
|
+
* Update hash state with a new chunk of data
|
|
2063
|
+
* Updates both CRC-32 and SHA-256 (if enabled) incrementally
|
|
2064
|
+
* @param chunk - Data chunk to process
|
|
2065
|
+
*/
|
|
2066
|
+
update(chunk) {
|
|
2067
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
2068
|
+
this.crc32State = (0, ZipCrypto_12.crc32update)(this.crc32State, chunk[i]);
|
|
2069
|
+
}
|
|
2070
|
+
if (this.sha256Hash) {
|
|
2071
|
+
this.sha256Hash.update(chunk);
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
/**
|
|
2075
|
+
* Get final CRC-32 value
|
|
2076
|
+
* @returns Final CRC-32 value as unsigned 32-bit integer
|
|
2077
|
+
*/
|
|
2078
|
+
finalizeCRC32() {
|
|
2079
|
+
return ~this.crc32State >>> 0;
|
|
2080
|
+
}
|
|
2081
|
+
/**
|
|
2082
|
+
* Get final SHA-256 hash as hex string
|
|
2083
|
+
* @returns SHA-256 hash as hex string, or null if SHA-256 not enabled
|
|
2084
|
+
*/
|
|
2085
|
+
finalizeSHA256() {
|
|
2086
|
+
if (this.sha256Hash) {
|
|
2087
|
+
return this.sha256Hash.digest("hex");
|
|
2088
|
+
}
|
|
2089
|
+
return null;
|
|
2090
|
+
}
|
|
2091
|
+
/**
|
|
2092
|
+
* Reset the incremental hash calculation state
|
|
2093
|
+
*/
|
|
2094
|
+
reset() {
|
|
2095
|
+
this.crc32State = ~0;
|
|
2096
|
+
if (this.sha256Hash) {
|
|
2097
|
+
this.sha256Hash = crypto.createHash("sha256");
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
// ============================================================================
|
|
2101
|
+
// Hash Accumulation Methods (from HashAccumulator)
|
|
2102
|
+
// ============================================================================
|
|
2103
|
+
/**
|
|
2104
|
+
* Adds a pre-computed SHA-256 hash to both the XOR accumulation and hash array
|
|
2105
|
+
* @param hash - Hash value as hex string or Buffer (must be 32 bytes for SHA-256)
|
|
2106
|
+
*/
|
|
2107
|
+
addHash(hash) {
|
|
2108
|
+
if (!this.enableAccumulation) {
|
|
2109
|
+
throw new Error("Hash accumulation not enabled. Set enableAccumulation: true in constructor.");
|
|
2110
|
+
}
|
|
2111
|
+
const hashBuffer = typeof hash === "string" ? Buffer.from(hash, "hex") : hash;
|
|
2112
|
+
this.hashes.push(hashBuffer);
|
|
2113
|
+
this.merkleLeaves.push(hashBuffer);
|
|
2114
|
+
for (let i = 0; i < 32; i++) {
|
|
2115
|
+
this.xorResult[i] ^= hashBuffer[i];
|
|
2116
|
+
}
|
|
2117
|
+
this.rebuildMerkleTree();
|
|
2118
|
+
}
|
|
2119
|
+
/**
|
|
2120
|
+
* Gets the accumulated XOR of all added hashes
|
|
2121
|
+
* @returns Hex string of XOR result
|
|
2122
|
+
*/
|
|
2123
|
+
xorHash() {
|
|
2124
|
+
if (!this.enableAccumulation) {
|
|
2125
|
+
throw new Error("Hash accumulation not enabled. Set enableAccumulation: true in constructor.");
|
|
2126
|
+
}
|
|
2127
|
+
return this.xorResult.toString("hex");
|
|
2128
|
+
}
|
|
2129
|
+
/**
|
|
2130
|
+
* Creates a Merkle tree from accumulated hashes and returns the root
|
|
2131
|
+
* @returns Hex string of Merkle root, or null if no hashes added
|
|
2132
|
+
*/
|
|
2133
|
+
merkleRoot() {
|
|
2134
|
+
if (!this.enableAccumulation) {
|
|
2135
|
+
throw new Error("Hash accumulation not enabled. Set enableAccumulation: true in constructor.");
|
|
2136
|
+
}
|
|
2137
|
+
if (this.merkleLeaves.length === 0) {
|
|
2138
|
+
return null;
|
|
2139
|
+
}
|
|
2140
|
+
if (this.merkleLayers.length === 0) {
|
|
2141
|
+
this.rebuildMerkleTree();
|
|
2142
|
+
}
|
|
2143
|
+
const root = this.merkleLayers[this.merkleLayers.length - 1];
|
|
2144
|
+
if (root && root.length > 0) {
|
|
2145
|
+
return root[0].toString("hex");
|
|
2146
|
+
}
|
|
2147
|
+
return null;
|
|
2148
|
+
}
|
|
2149
|
+
/**
|
|
2150
|
+
* Gets the number of hashes accumulated
|
|
2151
|
+
* @returns Number of accumulated hashes
|
|
2152
|
+
*/
|
|
2153
|
+
leafCount() {
|
|
2154
|
+
if (!this.enableAccumulation) {
|
|
2155
|
+
throw new Error("Hash accumulation not enabled. Set enableAccumulation: true in constructor.");
|
|
2156
|
+
}
|
|
2157
|
+
return this.hashes.length;
|
|
2158
|
+
}
|
|
2159
|
+
/**
|
|
2160
|
+
* Clears the accumulated hashes and resets XOR buffer
|
|
2161
|
+
*/
|
|
2162
|
+
clear() {
|
|
2163
|
+
if (!this.enableAccumulation) {
|
|
2164
|
+
throw new Error("Hash accumulation not enabled. Set enableAccumulation: true in constructor.");
|
|
2165
|
+
}
|
|
2166
|
+
this.hashes = [];
|
|
2167
|
+
this.merkleLeaves = [];
|
|
2168
|
+
this.merkleLayers = [];
|
|
2169
|
+
this.xorResult = Buffer.alloc(32, 0);
|
|
2170
|
+
}
|
|
2171
|
+
/**
|
|
2172
|
+
* Combines multiple hash results into a single Merkle root
|
|
2173
|
+
* Static method for combining results from multiple HashCalculator instances
|
|
2174
|
+
* @param results - Array of objects containing merkleRoot properties
|
|
2175
|
+
* @returns Combined Merkle root as hex string, or null if no valid roots
|
|
2176
|
+
*/
|
|
2177
|
+
static combineResults(results) {
|
|
2178
|
+
const calculator = new _HashCalculator({ enableAccumulation: true });
|
|
2179
|
+
for (const result of results) {
|
|
2180
|
+
if (result.merkleRoot) {
|
|
2181
|
+
calculator.addHash(result.merkleRoot);
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
return calculator.merkleRoot();
|
|
2185
|
+
}
|
|
2186
|
+
// ============================================================================
|
|
2187
|
+
// Merkle Tree Methods (from MerkleTree)
|
|
2188
|
+
// ============================================================================
|
|
2189
|
+
/**
|
|
2190
|
+
* Computes SHA-256 hash of input data
|
|
2191
|
+
* @param data - Data to hash
|
|
2192
|
+
* @returns Buffer containing hash
|
|
2193
|
+
*/
|
|
2194
|
+
hash(data) {
|
|
2195
|
+
return crypto.createHash("sha256").update(data).digest();
|
|
2196
|
+
}
|
|
2197
|
+
/**
|
|
2198
|
+
* Combines two child hashes to create parent hash
|
|
2199
|
+
* @param left - Left child hash
|
|
2200
|
+
* @param right - Right child hash
|
|
2201
|
+
* @returns Combined hash of children
|
|
2202
|
+
*/
|
|
2203
|
+
combinedHash(left, right) {
|
|
2204
|
+
if (this.merkleOptions.sortPairs && Buffer.compare(left, right) > 0) {
|
|
2205
|
+
[left, right] = [right, left];
|
|
2206
|
+
}
|
|
2207
|
+
return this.hash(Buffer.concat([left, right]));
|
|
2208
|
+
}
|
|
2209
|
+
/**
|
|
2210
|
+
* Builds the Merkle tree by creating successive layers of hashes
|
|
2211
|
+
* @param nodes - Array of nodes in current layer
|
|
2212
|
+
*/
|
|
2213
|
+
createHashes(nodes) {
|
|
2214
|
+
while (nodes.length > 1) {
|
|
2215
|
+
const layerIndex = this.merkleLayers.length;
|
|
2216
|
+
this.merkleLayers.push([]);
|
|
2217
|
+
for (let i = 0; i < nodes.length - 1; i += 2) {
|
|
2218
|
+
const left = nodes[i];
|
|
2219
|
+
const right = nodes[i + 1];
|
|
2220
|
+
const hash = this.combinedHash(left, right);
|
|
2221
|
+
this.merkleLayers[layerIndex].push(hash);
|
|
2222
|
+
}
|
|
2223
|
+
if (nodes.length % 2 === 1) {
|
|
2224
|
+
const last = nodes[nodes.length - 1];
|
|
2225
|
+
if (this.merkleOptions.duplicateOdd) {
|
|
2226
|
+
const hash = this.combinedHash(last, last);
|
|
2227
|
+
this.merkleLayers[layerIndex].push(hash);
|
|
2228
|
+
} else {
|
|
2229
|
+
this.merkleLayers[layerIndex].push(last);
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2232
|
+
nodes = this.merkleLayers[layerIndex];
|
|
2233
|
+
}
|
|
2234
|
+
}
|
|
2235
|
+
/**
|
|
2236
|
+
* Rebuilds the Merkle tree from current leaves
|
|
2237
|
+
*/
|
|
2238
|
+
rebuildMerkleTree() {
|
|
2239
|
+
if (this.merkleLeaves.length === 0) {
|
|
2240
|
+
this.merkleLayers = [];
|
|
2241
|
+
return;
|
|
2242
|
+
}
|
|
2243
|
+
const processedLeaves = this.merkleLeaves.map((leaf) => {
|
|
2244
|
+
if (this.merkleOptions.hashLeaves) {
|
|
2245
|
+
return this.hash(leaf);
|
|
2246
|
+
}
|
|
2247
|
+
return Buffer.isBuffer(leaf) ? leaf : Buffer.from(leaf);
|
|
2248
|
+
});
|
|
2249
|
+
if (this.merkleOptions.sortLeaves) {
|
|
2250
|
+
processedLeaves.sort(Buffer.compare);
|
|
2251
|
+
}
|
|
2252
|
+
this.merkleLayers = [processedLeaves];
|
|
2253
|
+
this.createHashes(processedLeaves);
|
|
2254
|
+
}
|
|
2255
|
+
/**
|
|
2256
|
+
* Generates a proof of inclusion for a leaf node
|
|
2257
|
+
* @param leaf - The leaf node to generate proof for
|
|
2258
|
+
* @returns Array of sibling hashes needed to reconstruct root
|
|
2259
|
+
* @throws Error if leaf not found in tree or accumulation not enabled
|
|
2260
|
+
*/
|
|
2261
|
+
getProof(leaf) {
|
|
2262
|
+
if (!this.enableAccumulation) {
|
|
2263
|
+
throw new Error("Hash accumulation not enabled. Set enableAccumulation: true in constructor.");
|
|
2264
|
+
}
|
|
2265
|
+
if (this.merkleLayers.length === 0) {
|
|
2266
|
+
this.rebuildMerkleTree();
|
|
2267
|
+
}
|
|
2268
|
+
let index = this.merkleLeaves.findIndex((item) => item.equals(leaf));
|
|
2269
|
+
if (index === -1) {
|
|
2270
|
+
throw new Error("Leaf not found in tree");
|
|
2271
|
+
}
|
|
2272
|
+
return this.merkleLayers.reduce((proof, layer) => {
|
|
2273
|
+
if (layer.length === 1)
|
|
2274
|
+
return proof;
|
|
2275
|
+
const pairIndex = index % 2 === 0 ? index + 1 : index - 1;
|
|
2276
|
+
if (pairIndex < layer.length) {
|
|
2277
|
+
proof.push(layer[pairIndex]);
|
|
2278
|
+
}
|
|
2279
|
+
index = Math.floor(index / 2);
|
|
2280
|
+
return proof;
|
|
2281
|
+
}, []);
|
|
2282
|
+
}
|
|
2283
|
+
/**
|
|
2284
|
+
* Verifies a proof of inclusion for a leaf node
|
|
2285
|
+
* @param proof - Array of sibling hashes from getProof()
|
|
2286
|
+
* @param targetHash - Hash of the leaf node being verified
|
|
2287
|
+
* @param root - Expected root hash
|
|
2288
|
+
* @returns boolean indicating if proof is valid
|
|
2289
|
+
*/
|
|
2290
|
+
verify(proof, targetHash, root) {
|
|
2291
|
+
let computedHash = targetHash;
|
|
2292
|
+
for (const proofElement of proof) {
|
|
2293
|
+
computedHash = Buffer.compare(computedHash, proofElement) <= 0 ? this.combinedHash(computedHash, proofElement) : this.combinedHash(proofElement, computedHash);
|
|
2294
|
+
}
|
|
2295
|
+
return computedHash.equals(root);
|
|
2296
|
+
}
|
|
2297
|
+
};
|
|
2298
|
+
exports2.HashCalculator = HashCalculator;
|
|
2299
|
+
exports2.default = HashCalculator;
|
|
2300
|
+
}
|
|
2301
|
+
});
|
|
2302
|
+
|
|
2303
|
+
// neozipkit/dist/core/ZipCompress.js
|
|
2304
|
+
var require_ZipCompress = __commonJS({
|
|
2305
|
+
"neozipkit/dist/core/ZipCompress.js"(exports2) {
|
|
2306
|
+
"use strict";
|
|
2307
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2308
|
+
exports2.ZipCompress = void 0;
|
|
2309
|
+
var pako = require("pako");
|
|
2310
|
+
var zstd_js_1 = require("@oneidentity/zstd-js");
|
|
2311
|
+
var Logger_12 = require_Logger();
|
|
2312
|
+
var Headers_1 = require_Headers();
|
|
2313
|
+
var HashCalculator_12 = require_HashCalculator();
|
|
2314
|
+
var ZipCrypto_12 = require_ZipCrypto();
|
|
2315
|
+
var zstdCodec = null;
|
|
2316
|
+
async function initZstd() {
|
|
2317
|
+
if (!zstdCodec) {
|
|
2318
|
+
zstdCodec = await (0, zstd_js_1.ZstdInit)();
|
|
2319
|
+
}
|
|
2320
|
+
return zstdCodec;
|
|
2321
|
+
}
|
|
2322
|
+
__name(initZstd, "initZstd");
|
|
2323
|
+
var ZipCompress = class _ZipCompress {
|
|
2324
|
+
static {
|
|
2325
|
+
__name(this, "ZipCompress");
|
|
2326
|
+
}
|
|
2327
|
+
/**
|
|
2328
|
+
* Internal logging method - only logs if class logging is enabled
|
|
2329
|
+
*/
|
|
2330
|
+
log(...args) {
|
|
2331
|
+
if (_ZipCompress.loggingEnabled) {
|
|
2332
|
+
Logger_12.Logger.debug(`[ZipCompress]`, ...args);
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
/**
|
|
2336
|
+
* Creates a new ZipCompress instance
|
|
2337
|
+
* @param zipkit - Zipkit instance to use for ZIP operations
|
|
2338
|
+
*/
|
|
2339
|
+
constructor(zipkit) {
|
|
2340
|
+
this.zipkit = zipkit;
|
|
2341
|
+
this.debug = false;
|
|
2342
|
+
if (_ZipCompress.loggingEnabled) {
|
|
2343
|
+
Logger_12.Logger.setLevel("debug");
|
|
2344
|
+
}
|
|
2345
|
+
this.log(`ZipCompress initialized`);
|
|
2346
|
+
}
|
|
2347
|
+
/**
|
|
2348
|
+
* Compresses data for a ZIP entry (Buffer-based only)
|
|
2349
|
+
* @param entry - ZIP entry to compress
|
|
2350
|
+
* @param data - Buffer containing data to compress
|
|
2351
|
+
* @param options - Compression options
|
|
2352
|
+
* @param onOutputBuffer - Optional callback for streaming output
|
|
2353
|
+
* @returns Buffer containing compressed data
|
|
2354
|
+
*/
|
|
2355
|
+
async compressData(entry, data, options, onOutputBuffer) {
|
|
2356
|
+
this.log(`compressData() called for entry: ${entry.filename}`);
|
|
2357
|
+
if (!entry.uncompressedSize || entry.uncompressedSize === 0) {
|
|
2358
|
+
entry.uncompressedSize = data.length;
|
|
2359
|
+
}
|
|
2360
|
+
const totalSize = data.length;
|
|
2361
|
+
const bufferSize = options?.bufferSize || this.zipkit.getBufferSize();
|
|
2362
|
+
this.log(`Compressing ${totalSize} bytes for entry: ${entry.filename}`);
|
|
2363
|
+
this.log(`Compression options:`, { level: options?.level, useZstd: options?.useZstd, bufferSize });
|
|
2364
|
+
let compressionMethod;
|
|
2365
|
+
if (options?.level === 0) {
|
|
2366
|
+
compressionMethod = Headers_1.CMP_METHOD.STORED;
|
|
2367
|
+
this.log(`Using STORED method (no compression)`);
|
|
2368
|
+
} else if (options?.useZstd) {
|
|
2369
|
+
if (totalSize < 100) {
|
|
2370
|
+
compressionMethod = Headers_1.CMP_METHOD.STORED;
|
|
2371
|
+
this.log(`ZSTD fallback to STORED (file too small: ${totalSize} bytes)`);
|
|
2372
|
+
} else {
|
|
2373
|
+
compressionMethod = Headers_1.CMP_METHOD.ZSTD;
|
|
2374
|
+
this.log(`Using ZSTD method (zstd compression)`);
|
|
2375
|
+
}
|
|
2376
|
+
} else {
|
|
2377
|
+
compressionMethod = Headers_1.CMP_METHOD.DEFLATED;
|
|
2378
|
+
this.log(`Using DEFLATED method (default compression)`);
|
|
2379
|
+
}
|
|
2380
|
+
entry.cmpMethod = compressionMethod;
|
|
2381
|
+
const needsHashCalculation = !entry.crc || entry.crc === 0 || options?.useSHA256 && !entry.sha256;
|
|
2382
|
+
const hashCalculator = needsHashCalculation ? new HashCalculator_12.HashCalculator({ useSHA256: options?.useSHA256 && !entry.sha256 || false }) : null;
|
|
2383
|
+
if (hashCalculator) {
|
|
2384
|
+
hashCalculator.update(data);
|
|
2385
|
+
if (!entry.crc || entry.crc === 0) {
|
|
2386
|
+
entry.crc = hashCalculator.finalizeCRC32();
|
|
2387
|
+
}
|
|
2388
|
+
if (options?.useSHA256 && !entry.sha256) {
|
|
2389
|
+
entry.sha256 = hashCalculator.finalizeSHA256();
|
|
2390
|
+
}
|
|
2391
|
+
this.log(`Final hashes: CRC32=0x${entry.crc.toString(16).padStart(8, "0")}, SHA256=${entry.sha256 || "N/A"}`);
|
|
2392
|
+
}
|
|
2393
|
+
if (options?.password) {
|
|
2394
|
+
this.log(`Encrypting compressed data for entry: ${entry.filename}`);
|
|
2395
|
+
entry.gpFlag = (entry.gpFlag || 0) | Headers_1.GP_FLAG.ENCRYPTED;
|
|
2396
|
+
entry.isEncrypted = true;
|
|
2397
|
+
}
|
|
2398
|
+
let compressedData;
|
|
2399
|
+
const methodName = compressionMethod === Headers_1.CMP_METHOD.ZSTD ? "ZSTD" : compressionMethod === Headers_1.CMP_METHOD.DEFLATED ? "DEFLATED" : "STORED";
|
|
2400
|
+
if (compressionMethod === Headers_1.CMP_METHOD.STORED) {
|
|
2401
|
+
compressedData = data;
|
|
2402
|
+
} else {
|
|
2403
|
+
this.log(`Processing sequence for ${methodName}: [HASH] -> [COMPRESS] -> [OUTPUT]`);
|
|
2404
|
+
this.log(`Compressing: method=${methodName}, input=${totalSize} bytes, buffer size=${bufferSize} bytes`);
|
|
2405
|
+
this.log(`Calculating hashes: CRC32=${!entry.crc || entry.crc === 0}, SHA256=${options?.useSHA256}`);
|
|
2406
|
+
if (compressionMethod === Headers_1.CMP_METHOD.ZSTD) {
|
|
2407
|
+
compressedData = await this.zstdCompress(data, options, bufferSize, entry, onOutputBuffer);
|
|
2408
|
+
} else {
|
|
2409
|
+
compressedData = await this.deflateCompress(data, options, bufferSize, entry, onOutputBuffer);
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
if (options?.password) {
|
|
2413
|
+
compressedData = this.encryptCompressedData(entry, compressedData, options.password);
|
|
2414
|
+
}
|
|
2415
|
+
entry.compressedSize = compressedData.length;
|
|
2416
|
+
return compressedData;
|
|
2417
|
+
}
|
|
2418
|
+
/**
|
|
2419
|
+
* Compress data using deflate algorithm with chunked processing
|
|
2420
|
+
* @param data - Data to compress (Buffer or chunked reader)
|
|
2421
|
+
* @param options - Compression options
|
|
2422
|
+
* @param bufferSize - Buffer size for chunked processing
|
|
2423
|
+
* @param entry - ZIP entry being compressed
|
|
2424
|
+
* @param onOutputBuffer - Optional callback for streaming output
|
|
2425
|
+
* @returns Buffer containing compressed data
|
|
2426
|
+
*/
|
|
2427
|
+
async deflateCompress(data, options, bufferSize, entry, onOutputBuffer) {
|
|
2428
|
+
this.log(`deflateCompress() called - entry: ${entry?.filename ?? "unknown"}, bufferSize: ${bufferSize}, level: ${options?.level ?? 6}`);
|
|
2429
|
+
const effectiveBufferSize = bufferSize || this.zipkit.getBufferSize();
|
|
2430
|
+
const level = options?.level ?? 6;
|
|
2431
|
+
if (typeof data === "object" && "totalSize" in data && "onReadChunk" in data) {
|
|
2432
|
+
throw new Error("Chunked reader mode not supported in ZipCompress");
|
|
2433
|
+
}
|
|
2434
|
+
if (data.length <= effectiveBufferSize) {
|
|
2435
|
+
return this.deflate(data, options);
|
|
2436
|
+
}
|
|
2437
|
+
const deflator = new pako.Deflate({ level, raw: true });
|
|
2438
|
+
const compressedChunks = [];
|
|
2439
|
+
let totalProcessed = 0;
|
|
2440
|
+
let totalCompressedSize = 0;
|
|
2441
|
+
try {
|
|
2442
|
+
for (let offset = 0; offset < data.length; offset += effectiveBufferSize) {
|
|
2443
|
+
const chunk = data.slice(offset, offset + effectiveBufferSize);
|
|
2444
|
+
const isLast = offset + effectiveBufferSize >= data.length;
|
|
2445
|
+
deflator.push(chunk, isLast);
|
|
2446
|
+
if (deflator.result && deflator.result.length > 0) {
|
|
2447
|
+
const compressedChunk = Buffer.from(deflator.result);
|
|
2448
|
+
compressedChunks.push(compressedChunk);
|
|
2449
|
+
totalCompressedSize += compressedChunk.length;
|
|
2450
|
+
if (onOutputBuffer) {
|
|
2451
|
+
await onOutputBuffer(compressedChunk);
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
totalProcessed += chunk.length;
|
|
2455
|
+
}
|
|
2456
|
+
const ratio = totalProcessed > 0 ? Math.round(totalCompressedSize / totalProcessed * 100) : 0;
|
|
2457
|
+
this.log(`Final hashes: CRC32=0x${entry?.crc?.toString(16).padStart(8, "0")}, SHA256=${entry?.sha256 || "N/A"}`);
|
|
2458
|
+
this.log(`Deflate compression complete: ${totalCompressedSize} bytes from ${totalProcessed} bytes (ratio=${ratio}%)`);
|
|
2459
|
+
return Buffer.concat(compressedChunks);
|
|
2460
|
+
} catch (e) {
|
|
2461
|
+
throw new Error(`Deflate compression failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
/**
|
|
2465
|
+
* Compress data using deflate algorithm (synchronous, small buffers only)
|
|
2466
|
+
* @param inbuf - Buffer containing data to compress
|
|
2467
|
+
* @param options - Compression options
|
|
2468
|
+
* @returns Buffer containing compressed data
|
|
2469
|
+
*/
|
|
2470
|
+
deflate(inbuf, options) {
|
|
2471
|
+
this.log(`deflate() called with buffer size: ${inbuf.length}, level: ${options?.level ?? 6}`);
|
|
2472
|
+
const level = options?.level ?? 6;
|
|
2473
|
+
const result = pako.deflateRaw(inbuf, { level });
|
|
2474
|
+
const ratio = inbuf.length > 0 ? Math.round(result.length / inbuf.length * 100) : 0;
|
|
2475
|
+
this.log(`Deflate compression complete: ${result.length} bytes from ${inbuf.length} bytes (ratio=${ratio}%)`);
|
|
2476
|
+
return Buffer.from(result.buffer, result.byteOffset, result.byteLength);
|
|
2477
|
+
}
|
|
2478
|
+
/**
|
|
2479
|
+
* Compress data using Zstandard (zstd) algorithm
|
|
2480
|
+
* @param input - Input data to compress (Buffer or chunked reader)
|
|
2481
|
+
* @param options - Compression options
|
|
2482
|
+
* @param bufferSize - Buffer size for chunked processing
|
|
2483
|
+
* @param entry - ZIP entry being compressed
|
|
2484
|
+
* @param onOutputBuffer - Optional callback for streaming output
|
|
2485
|
+
* @returns Buffer containing compressed data
|
|
2486
|
+
*/
|
|
2487
|
+
async zstdCompress(input, options, bufferSize, entry, onOutputBuffer) {
|
|
2488
|
+
this.log(`zstdCompress() called - entry: ${entry?.filename ?? "unknown"}, bufferSize: ${bufferSize}, level: ${options?.level ?? 6}`);
|
|
2489
|
+
const effectiveBufferSize = bufferSize || this.zipkit.getBufferSize();
|
|
2490
|
+
const level = options?.level ?? 6;
|
|
2491
|
+
if (typeof input === "object" && "totalSize" in input && "readChunk" in input) {
|
|
2492
|
+
throw new Error("Chunked reader mode not supported in ZipCompress");
|
|
2493
|
+
}
|
|
2494
|
+
const zstdCodec2 = await initZstd();
|
|
2495
|
+
if (!input || input.length === 0) {
|
|
2496
|
+
throw new Error("ZSTD compression: empty input buffer");
|
|
2497
|
+
}
|
|
2498
|
+
const inputArray = new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
|
|
2499
|
+
if (input.length <= effectiveBufferSize) {
|
|
2500
|
+
const compressed2 = zstdCodec2.ZstdSimple.compress(inputArray, level);
|
|
2501
|
+
const compressedBuffer2 = Buffer.from(compressed2);
|
|
2502
|
+
if (onOutputBuffer) {
|
|
2503
|
+
await onOutputBuffer(compressedBuffer2);
|
|
2504
|
+
}
|
|
2505
|
+
return compressedBuffer2;
|
|
2506
|
+
}
|
|
2507
|
+
const compressed = zstdCodec2.ZstdSimple.compress(inputArray, level);
|
|
2508
|
+
const compressedBuffer = Buffer.from(compressed);
|
|
2509
|
+
if (onOutputBuffer) {
|
|
2510
|
+
await onOutputBuffer(compressedBuffer);
|
|
2511
|
+
}
|
|
2512
|
+
return compressedBuffer;
|
|
2513
|
+
}
|
|
2514
|
+
/**
|
|
2515
|
+
* Encrypt compressed data using PKZIP encryption
|
|
2516
|
+
* @param entry - ZIP entry to encrypt
|
|
2517
|
+
* @param compressedData - Compressed data to encrypt
|
|
2518
|
+
* @param password - Password for encryption
|
|
2519
|
+
* @returns Buffer containing encrypted data (includes 12-byte header)
|
|
2520
|
+
*/
|
|
2521
|
+
encryptCompressedData(entry, compressedData, password) {
|
|
2522
|
+
this.log(`encryptCompressedData() called for entry: ${entry.filename}, compressed size: ${compressedData.length}`);
|
|
2523
|
+
const zipCrypto = new ZipCrypto_12.ZipCrypto();
|
|
2524
|
+
const encryptedData = zipCrypto.encryptBuffer(entry, compressedData, password);
|
|
2525
|
+
this.log(`Encryption complete: ${compressedData.length} bytes compressed -> ${encryptedData.length} bytes encrypted (includes ${Headers_1.ENCRYPT_HDR_SIZE}-byte header)`);
|
|
2526
|
+
return encryptedData;
|
|
2527
|
+
}
|
|
2528
|
+
/**
|
|
2529
|
+
* Compress file data in memory and return ZIP entry information as Buffer
|
|
2530
|
+
* @param entry - ZIP entry to compress
|
|
2531
|
+
* @param fileData - File data buffer to compress
|
|
2532
|
+
* @param cmpOptions - Compression options
|
|
2533
|
+
* @returns Buffer containing local header + compressed data
|
|
2534
|
+
*/
|
|
2535
|
+
async compressFileBuffer(entry, fileData, cmpOptions) {
|
|
2536
|
+
this.log(`compressFileBuffer() called for entry: ${entry.filename}, size: ${fileData.length}`);
|
|
2537
|
+
entry.uncompressedSize = fileData.length;
|
|
2538
|
+
const hashCalculator = new HashCalculator_12.HashCalculator({ useSHA256: cmpOptions?.useSHA256 || false });
|
|
2539
|
+
hashCalculator.update(fileData);
|
|
2540
|
+
entry.crc = hashCalculator.finalizeCRC32();
|
|
2541
|
+
if (cmpOptions?.useSHA256) {
|
|
2542
|
+
entry.sha256 = hashCalculator.finalizeSHA256();
|
|
2543
|
+
this.log(`SHA-256 calculated: ${entry.sha256}`);
|
|
2544
|
+
}
|
|
2545
|
+
const compressedData = await this.compressData(entry, fileData, cmpOptions);
|
|
2546
|
+
if (cmpOptions?.password) {
|
|
2547
|
+
this.log(`Encrypting compressed data for entry: ${entry.filename}`);
|
|
2548
|
+
entry.gpFlag = (entry.gpFlag || 0) | Headers_1.GP_FLAG.ENCRYPTED;
|
|
2549
|
+
entry.isEncrypted = true;
|
|
2550
|
+
const zipCrypto = new ZipCrypto_12.ZipCrypto();
|
|
2551
|
+
const encryptedData = zipCrypto.encryptBuffer(entry, compressedData, cmpOptions.password);
|
|
2552
|
+
return encryptedData;
|
|
2553
|
+
}
|
|
2554
|
+
return compressedData;
|
|
2555
|
+
}
|
|
2556
|
+
};
|
|
2557
|
+
exports2.ZipCompress = ZipCompress;
|
|
2558
|
+
ZipCompress.loggingEnabled = false;
|
|
2559
|
+
}
|
|
2560
|
+
});
|
|
2561
|
+
|
|
2562
|
+
// neozipkit/dist/core/ZipDecompress.js
|
|
2563
|
+
var require_ZipDecompress = __commonJS({
|
|
2564
|
+
"neozipkit/dist/core/ZipDecompress.js"(exports2) {
|
|
2565
|
+
"use strict";
|
|
2566
|
+
var __importDefault2 = exports2 && exports2.__importDefault || function(mod) {
|
|
2567
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
2568
|
+
};
|
|
2569
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2570
|
+
var pako = require("pako");
|
|
2571
|
+
var zstd_js_1 = require("@oneidentity/zstd-js");
|
|
2572
|
+
var Logger_12 = require_Logger();
|
|
2573
|
+
var Errors_1 = __importDefault2(require_Errors());
|
|
2574
|
+
var Headers_1 = require_Headers();
|
|
2575
|
+
var ZipCrypto_12 = require_ZipCrypto();
|
|
2576
|
+
var zstdCodec = null;
|
|
2577
|
+
async function initZstd() {
|
|
2578
|
+
if (!zstdCodec) {
|
|
2579
|
+
zstdCodec = await (0, zstd_js_1.ZstdInit)();
|
|
2580
|
+
}
|
|
2581
|
+
return zstdCodec;
|
|
2582
|
+
}
|
|
2583
|
+
__name(initZstd, "initZstd");
|
|
2584
|
+
var ZipDecompress = class _ZipDecompress {
|
|
2585
|
+
static {
|
|
2586
|
+
__name(this, "ZipDecompress");
|
|
2587
|
+
}
|
|
2588
|
+
/**
|
|
2589
|
+
* Internal logging method - only logs if class logging is enabled
|
|
2590
|
+
*/
|
|
2591
|
+
log(...args) {
|
|
2592
|
+
if (_ZipDecompress.loggingEnabled) {
|
|
2593
|
+
Logger_12.Logger.debug(`[ZipDecompress]`, ...args);
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
constructor(zipkit) {
|
|
2597
|
+
this.zstdCodec = null;
|
|
2598
|
+
this.zipkit = zipkit;
|
|
2599
|
+
this.debug = false;
|
|
2600
|
+
if (_ZipDecompress.loggingEnabled) {
|
|
2601
|
+
Logger_12.Logger.setLevel("debug");
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2604
|
+
/**
|
|
2605
|
+
* Extract file data (Buffer-based ZIP only)
|
|
2606
|
+
* Public method that validates buffer mode and extracts entry
|
|
2607
|
+
*
|
|
2608
|
+
* @param entry ZIP entry to extract
|
|
2609
|
+
* @param skipHashCheck Skip hash verification (CRC-32 or SHA-256)
|
|
2610
|
+
* @returns Promise resolving to extracted data as Buffer, or null if failed
|
|
2611
|
+
* @throws Error if not a Buffer-based ZIP
|
|
2612
|
+
*/
|
|
2613
|
+
async extract(entry, skipHashCheck) {
|
|
2614
|
+
if (!this.zipkit.hasInBuffer()) {
|
|
2615
|
+
throw new Error("extract() requires Buffer-based ZIP. Use ZipkitServer.extractToFile() for file-based ZIP or call loadZip() first.");
|
|
2616
|
+
}
|
|
2617
|
+
this.log(`extract() called for entry: ${entry.filename}, method: ${entry.cmpMethod}, skipHashCheck: ${skipHashCheck}`);
|
|
2618
|
+
if (entry.cmpMethod === Headers_1.CMP_METHOD.ZSTD && !this.zstdCodec) {
|
|
2619
|
+
this.zstdCodec = await initZstd();
|
|
2620
|
+
}
|
|
2621
|
+
const buffer = this.zipkit.ensureBuffer();
|
|
2622
|
+
let fdata = this.zipkit.parseLocalHeader(entry, buffer);
|
|
2623
|
+
if (entry.isEncrypted && this.zipkit?.password) {
|
|
2624
|
+
this.log(`Starting in-memory decryption for entry: ${entry.filename}`);
|
|
2625
|
+
const zipCrypto = new ZipCrypto_12.ZipCrypto();
|
|
2626
|
+
fdata = zipCrypto.decryptBuffer(entry, buffer, fdata, this.zipkit.password);
|
|
2627
|
+
this.log(`Decryption successful, decrypted compressed data length: ${fdata.length}`);
|
|
2628
|
+
}
|
|
2629
|
+
if (fdata.length === 0) {
|
|
2630
|
+
return null;
|
|
2631
|
+
}
|
|
2632
|
+
return this.unCompress(fdata, entry, skipHashCheck);
|
|
2633
|
+
}
|
|
2634
|
+
/**
|
|
2635
|
+
* Inflate data using pako (internal use only)
|
|
2636
|
+
*/
|
|
2637
|
+
inflate(data) {
|
|
2638
|
+
this.log(`inflate() called with ${data.length} bytes`);
|
|
2639
|
+
const result = pako.inflateRaw(data);
|
|
2640
|
+
return Buffer.from(result.buffer, result.byteOffset, result.byteLength);
|
|
2641
|
+
}
|
|
2642
|
+
/**
|
|
2643
|
+
* Synchronous zstd decompress method for in-memory mode
|
|
2644
|
+
* ZSTD codec is guaranteed to be initialized via factory method
|
|
2645
|
+
* Internal method only
|
|
2646
|
+
*/
|
|
2647
|
+
zstdDecompressSync(data) {
|
|
2648
|
+
this.log(`zstdDecompressSync() called with ${data.length} bytes`);
|
|
2649
|
+
try {
|
|
2650
|
+
if (!this.zstdCodec) {
|
|
2651
|
+
throw new Error("ZSTD codec not initialized.");
|
|
2652
|
+
}
|
|
2653
|
+
const decompressed = this.zstdCodec.ZstdSimple.decompress(data);
|
|
2654
|
+
this.log(`ZSTD synchronous decompression successful: ${data.length} bytes -> ${decompressed.length} bytes`);
|
|
2655
|
+
return Buffer.from(decompressed);
|
|
2656
|
+
} catch (error) {
|
|
2657
|
+
this.log(`ZSTD synchronous decompression failed: ${error}`);
|
|
2658
|
+
throw new Error(`ZSTD synchronous decompression failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
/**
|
|
2662
|
+
* Uncompress compressed data buffer (synchronous for in-memory mode)
|
|
2663
|
+
* Handles decompression and hash verification
|
|
2664
|
+
* Internal method only
|
|
2665
|
+
*/
|
|
2666
|
+
unCompress(compressedData, entry, skipHashCheck) {
|
|
2667
|
+
this.log(`unCompress() called for entry: ${entry.filename}, method: ${entry.cmpMethod}, data length: ${compressedData.length}`);
|
|
2668
|
+
if (compressedData.length === 0) {
|
|
2669
|
+
return Buffer.alloc(0);
|
|
2670
|
+
}
|
|
2671
|
+
let outBuf;
|
|
2672
|
+
if (entry.cmpMethod === Headers_1.CMP_METHOD.STORED) {
|
|
2673
|
+
outBuf = compressedData;
|
|
2674
|
+
} else if (entry.cmpMethod === Headers_1.CMP_METHOD.DEFLATED) {
|
|
2675
|
+
outBuf = this.inflate(compressedData);
|
|
2676
|
+
} else if (entry.cmpMethod === Headers_1.CMP_METHOD.ZSTD) {
|
|
2677
|
+
outBuf = this.zstdDecompressSync(compressedData);
|
|
2678
|
+
} else {
|
|
2679
|
+
throw new Error(`Unsupported compression method: ${entry.cmpMethod}`);
|
|
2680
|
+
}
|
|
2681
|
+
if (!skipHashCheck) {
|
|
2682
|
+
if (entry.sha256) {
|
|
2683
|
+
const isValid = this.zipkit.testSHA256(entry, outBuf);
|
|
2684
|
+
if (!isValid) {
|
|
2685
|
+
throw new Error(Errors_1.default.INVALID_SHA256);
|
|
2686
|
+
}
|
|
2687
|
+
} else {
|
|
2688
|
+
const isValid = this.zipkit.testCRC32(entry, outBuf);
|
|
2689
|
+
if (!isValid) {
|
|
2690
|
+
throw new Error(Errors_1.default.INVALID_CRC);
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
return outBuf;
|
|
2695
|
+
}
|
|
2696
|
+
};
|
|
2697
|
+
ZipDecompress.loggingEnabled = false;
|
|
2698
|
+
exports2.default = ZipDecompress;
|
|
2699
|
+
}
|
|
2700
|
+
});
|
|
2701
|
+
|
|
2702
|
+
// neozipkit/dist/core/Zipkit.js
|
|
2703
|
+
var require_Zipkit = __commonJS({
|
|
2704
|
+
"neozipkit/dist/core/Zipkit.js"(exports2) {
|
|
2705
|
+
"use strict";
|
|
2706
|
+
var __importDefault2 = exports2 && exports2.__importDefault || function(mod) {
|
|
2707
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
2708
|
+
};
|
|
2709
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2710
|
+
exports2.HDR_ID = exports2.CENTRAL_DIRECTORY_END = exports2.CENTRAL_FILE_HEADER = exports2.LOCAL_FILE_HEADER = exports2.GP_FLAG = exports2.ZIP64_CENTRAL_DIR = exports2.ZIP64_CENTRAL_END = exports2.CENTRAL_DIR = exports2.CENTRAL_END = exports2.ENCRYPT_HDR_SIZE = exports2.LOCAL_HDR = exports2.TOKENIZED_METADATA = exports2.TIMESTAMP_SUBMITTED = exports2.TIMESTAMP_METADATA = exports2.CMP_METHOD = exports2.Errors = exports2.ZipEntry = void 0;
|
|
2711
|
+
var ZipEntry_1 = __importDefault2(require_ZipEntry());
|
|
2712
|
+
exports2.ZipEntry = ZipEntry_1.default;
|
|
2713
|
+
var Errors_1 = __importDefault2(require_Errors());
|
|
2714
|
+
exports2.Errors = Errors_1.default;
|
|
2715
|
+
var Logger_12 = require_Logger();
|
|
2716
|
+
var types_1 = require_types2();
|
|
2717
|
+
var ZipCompress_12 = require_ZipCompress();
|
|
2718
|
+
var ZipDecompress_1 = __importDefault2(require_ZipDecompress());
|
|
2719
|
+
var ZipCrypto_12 = require_ZipCrypto();
|
|
2720
|
+
var HashCalculator_12 = __importDefault2(require_HashCalculator());
|
|
2721
|
+
var Headers_1 = require_Headers();
|
|
2722
|
+
Object.defineProperty(exports2, "LOCAL_HDR", { enumerable: true, get: function() {
|
|
2723
|
+
return Headers_1.LOCAL_HDR;
|
|
2724
|
+
} });
|
|
2725
|
+
Object.defineProperty(exports2, "ENCRYPT_HDR_SIZE", { enumerable: true, get: function() {
|
|
2726
|
+
return Headers_1.ENCRYPT_HDR_SIZE;
|
|
2727
|
+
} });
|
|
2728
|
+
Object.defineProperty(exports2, "CMP_METHOD", { enumerable: true, get: function() {
|
|
2729
|
+
return Headers_1.CMP_METHOD;
|
|
2730
|
+
} });
|
|
2731
|
+
Object.defineProperty(exports2, "CENTRAL_END", { enumerable: true, get: function() {
|
|
2732
|
+
return Headers_1.CENTRAL_END;
|
|
2733
|
+
} });
|
|
2734
|
+
Object.defineProperty(exports2, "CENTRAL_DIR", { enumerable: true, get: function() {
|
|
2735
|
+
return Headers_1.CENTRAL_DIR;
|
|
2736
|
+
} });
|
|
2737
|
+
Object.defineProperty(exports2, "ZIP64_CENTRAL_END", { enumerable: true, get: function() {
|
|
2738
|
+
return Headers_1.ZIP64_CENTRAL_END;
|
|
2739
|
+
} });
|
|
2740
|
+
Object.defineProperty(exports2, "ZIP64_CENTRAL_DIR", { enumerable: true, get: function() {
|
|
2741
|
+
return Headers_1.ZIP64_CENTRAL_DIR;
|
|
2742
|
+
} });
|
|
2743
|
+
Object.defineProperty(exports2, "GP_FLAG", { enumerable: true, get: function() {
|
|
2744
|
+
return Headers_1.GP_FLAG;
|
|
2745
|
+
} });
|
|
2746
|
+
Object.defineProperty(exports2, "TIMESTAMP_SUBMITTED", { enumerable: true, get: function() {
|
|
2747
|
+
return Headers_1.TIMESTAMP_SUBMITTED;
|
|
2748
|
+
} });
|
|
2749
|
+
Object.defineProperty(exports2, "TIMESTAMP_METADATA", { enumerable: true, get: function() {
|
|
2750
|
+
return Headers_1.TIMESTAMP_METADATA;
|
|
2751
|
+
} });
|
|
2752
|
+
Object.defineProperty(exports2, "TOKENIZED_METADATA", { enumerable: true, get: function() {
|
|
2753
|
+
return Headers_1.TOKENIZED_METADATA;
|
|
2754
|
+
} });
|
|
2755
|
+
Object.defineProperty(exports2, "LOCAL_FILE_HEADER", { enumerable: true, get: function() {
|
|
2756
|
+
return Headers_1.LOCAL_FILE_HEADER;
|
|
2757
|
+
} });
|
|
2758
|
+
Object.defineProperty(exports2, "CENTRAL_FILE_HEADER", { enumerable: true, get: function() {
|
|
2759
|
+
return Headers_1.CENTRAL_FILE_HEADER;
|
|
2760
|
+
} });
|
|
2761
|
+
Object.defineProperty(exports2, "CENTRAL_DIRECTORY_END", { enumerable: true, get: function() {
|
|
2762
|
+
return Headers_1.CENTRAL_DIRECTORY_END;
|
|
2763
|
+
} });
|
|
2764
|
+
Object.defineProperty(exports2, "HDR_ID", { enumerable: true, get: function() {
|
|
2765
|
+
return Headers_1.HDR_ID;
|
|
2766
|
+
} });
|
|
2767
|
+
var Zipkit = class {
|
|
2768
|
+
static {
|
|
2769
|
+
__name(this, "Zipkit");
|
|
2770
|
+
}
|
|
2771
|
+
/**
|
|
2772
|
+
* Creates a new Zipkit instance with optional configuration
|
|
2773
|
+
*
|
|
2774
|
+
* @param config - Optional configuration object (ZipkitConfig)
|
|
2775
|
+
* - bufferSize: Buffer size for streaming operations (default: 512KB)
|
|
2776
|
+
* - debug: Enable debug logging (default: false)
|
|
2777
|
+
*
|
|
2778
|
+
* @example
|
|
2779
|
+
* const zip = new Zipkit({ bufferSize: 512 * 1024, debug: true });
|
|
2780
|
+
*/
|
|
2781
|
+
constructor(config = {}) {
|
|
2782
|
+
this.inBuffer = null;
|
|
2783
|
+
this.zipEntries = [];
|
|
2784
|
+
this.centralDirSize = 0;
|
|
2785
|
+
this.centralDirOffset = 0;
|
|
2786
|
+
this.zipComment = null;
|
|
2787
|
+
this._zipkitCmp = null;
|
|
2788
|
+
this._zipkitDeCmp = null;
|
|
2789
|
+
this.config = {
|
|
2790
|
+
bufferSize: config.bufferSize || 512 * 1024,
|
|
2791
|
+
// 512KB default (optimal for modern systems)
|
|
2792
|
+
debug: config.debug || false
|
|
2793
|
+
// Default false
|
|
2794
|
+
};
|
|
2795
|
+
if (this.config.debug) {
|
|
2796
|
+
Logger_12.Logger.setLevel("debug");
|
|
2797
|
+
}
|
|
2798
|
+
}
|
|
2799
|
+
/**
|
|
2800
|
+
* Lazy-load ZipCompress instance
|
|
2801
|
+
* @returns ZipCompress instance (created on first access)
|
|
2802
|
+
*/
|
|
2803
|
+
getZipCompress() {
|
|
2804
|
+
if (!this._zipkitCmp) {
|
|
2805
|
+
this._zipkitCmp = new ZipCompress_12.ZipCompress(this);
|
|
2806
|
+
}
|
|
2807
|
+
return this._zipkitCmp;
|
|
2808
|
+
}
|
|
2809
|
+
/**
|
|
2810
|
+
* Lazy-load ZipDecompress instance
|
|
2811
|
+
* @returns ZipDecompress instance (created on first access)
|
|
2812
|
+
*/
|
|
2813
|
+
getZipDecompress() {
|
|
2814
|
+
if (!this._zipkitDeCmp) {
|
|
2815
|
+
this._zipkitDeCmp = new ZipDecompress_1.default(this);
|
|
2816
|
+
}
|
|
2817
|
+
return this._zipkitDeCmp;
|
|
2818
|
+
}
|
|
2819
|
+
/**
|
|
2820
|
+
* Get the configured buffer size for streaming operations
|
|
2821
|
+
* @returns Buffer size in bytes (default: 512KB)
|
|
2822
|
+
*/
|
|
2823
|
+
getBufferSize() {
|
|
2824
|
+
return this.config.bufferSize || 512 * 1024;
|
|
2825
|
+
}
|
|
2826
|
+
/**
|
|
2827
|
+
* Check if ZIP is loaded in buffer mode
|
|
2828
|
+
* @returns true if buffer-based ZIP is loaded
|
|
2829
|
+
*/
|
|
2830
|
+
hasInBuffer() {
|
|
2831
|
+
return this.inBuffer !== null && this.inBuffer.length > 0;
|
|
2832
|
+
}
|
|
2833
|
+
// ============================================================================
|
|
2834
|
+
// ZipCompress Wrapper Methods
|
|
2835
|
+
// ============================================================================
|
|
2836
|
+
/**
|
|
2837
|
+
* Compress data for a ZIP entry (Buffer-based only)
|
|
2838
|
+
* Wrapper for ZipCompress.compressData()
|
|
2839
|
+
*
|
|
2840
|
+
* @param entry - ZIP entry to compress
|
|
2841
|
+
* @param data - Buffer containing data to compress
|
|
2842
|
+
* @param options - Compression options
|
|
2843
|
+
* @param onOutputBuffer - Optional callback for streaming output
|
|
2844
|
+
* @returns Promise resolving to Buffer containing compressed data
|
|
2845
|
+
*/
|
|
2846
|
+
async compressData(entry, data, options, onOutputBuffer) {
|
|
2847
|
+
return this.getZipCompress().compressData(entry, data, options, onOutputBuffer);
|
|
2848
|
+
}
|
|
2849
|
+
/**
|
|
2850
|
+
* Compress data using deflate algorithm with chunked processing
|
|
2851
|
+
* Wrapper for ZipCompress.deflateCompress()
|
|
2852
|
+
*
|
|
2853
|
+
* @param data - Data to compress (Buffer or chunked reader)
|
|
2854
|
+
* @param options - Compression options
|
|
2855
|
+
* @param bufferSize - Size of buffer to read (default: 512KB)
|
|
2856
|
+
* @param entry - Optional ZIP entry for hash calculation
|
|
2857
|
+
* @param onOutputBuffer - Optional callback for streaming output
|
|
2858
|
+
* @returns Promise resolving to Buffer containing compressed data
|
|
2859
|
+
*/
|
|
2860
|
+
async deflateCompress(data, options, bufferSize, entry, onOutputBuffer) {
|
|
2861
|
+
return this.getZipCompress().deflateCompress(data, options, bufferSize, entry, onOutputBuffer);
|
|
2862
|
+
}
|
|
2863
|
+
/**
|
|
2864
|
+
* Compress data using deflate algorithm (synchronous, small buffers only)
|
|
2865
|
+
* Wrapper for ZipCompress.deflate()
|
|
2866
|
+
*
|
|
2867
|
+
* @param inbuf - Buffer containing data to compress
|
|
2868
|
+
* @param options - Compression options
|
|
2869
|
+
* @returns Buffer containing compressed data
|
|
2870
|
+
*/
|
|
2871
|
+
deflate(inbuf, options) {
|
|
2872
|
+
return this.getZipCompress().deflate(inbuf, options);
|
|
2873
|
+
}
|
|
2874
|
+
/**
|
|
2875
|
+
* Compress data using Zstandard (zstd) algorithm
|
|
2876
|
+
* Wrapper for ZipCompress.zstdCompress()
|
|
2877
|
+
*
|
|
2878
|
+
* Note: ZSTD codec is lazily initialized on first use (module-level singleton).
|
|
2879
|
+
* Initialization happens automatically when needed.
|
|
2880
|
+
*
|
|
2881
|
+
* @param input - Buffer to compress OR chunked reader object
|
|
2882
|
+
* @param options - Compression options
|
|
2883
|
+
* @param bufferSize - Size of buffer to read if using chunked reader (default: 512KB)
|
|
2884
|
+
* @param entry - Optional ZIP entry for hash calculation
|
|
2885
|
+
* @param onOutputBuffer - Optional callback for streaming output
|
|
2886
|
+
* @returns Promise resolving to Buffer containing compressed data
|
|
2887
|
+
*/
|
|
2888
|
+
async zstdCompress(input, options, bufferSize, entry, onOutputBuffer) {
|
|
2889
|
+
return this.getZipCompress().zstdCompress(input, options, bufferSize, entry, onOutputBuffer);
|
|
2890
|
+
}
|
|
2891
|
+
/**
|
|
2892
|
+
* Compress file data in memory and return ZIP entry information as Buffer
|
|
2893
|
+
* Wrapper for ZipCompress.compressFileBuffer()
|
|
2894
|
+
*
|
|
2895
|
+
* @param entry - ZIP entry to compress
|
|
2896
|
+
* @param fileData - File data buffer to compress
|
|
2897
|
+
* @param cmpOptions - Compression options
|
|
2898
|
+
* @returns Promise resolving to Buffer containing local header + compressed data
|
|
2899
|
+
*/
|
|
2900
|
+
async compressFileBuffer(entry, fileData, cmpOptions) {
|
|
2901
|
+
return this.getZipCompress().compressFileBuffer(entry, fileData, cmpOptions);
|
|
2902
|
+
}
|
|
2903
|
+
// ============================================================================
|
|
2904
|
+
// ZipDecompress Wrapper Methods
|
|
2905
|
+
// ============================================================================
|
|
2906
|
+
/**
|
|
2907
|
+
* Extract file data (Buffer-based ZIP only)
|
|
2908
|
+
* Wrapper for ZipDecompress.extract()
|
|
2909
|
+
*
|
|
2910
|
+
* @param entry - ZIP entry to extract
|
|
2911
|
+
* @param skipHashCheck - Skip hash verification (CRC-32 or SHA-256)
|
|
2912
|
+
* @returns Promise resolving to Buffer containing extracted data, or null if failed
|
|
2913
|
+
* @throws Error if not a Buffer-based ZIP
|
|
2914
|
+
*/
|
|
2915
|
+
async extract(entry, skipHashCheck) {
|
|
2916
|
+
return this.getZipDecompress().extract(entry, skipHashCheck);
|
|
2917
|
+
}
|
|
2918
|
+
// ============================================================================
|
|
2919
|
+
// Static Logging Wrapper Methods
|
|
2920
|
+
// ============================================================================
|
|
2921
|
+
/**
|
|
2922
|
+
* Note: Logging for ZipCompress and ZipDecompress is controlled by their
|
|
2923
|
+
* static loggingEnabled property. Set it directly:
|
|
2924
|
+
* ZipCompress.loggingEnabled = true/false;
|
|
2925
|
+
* ZipDecompress.loggingEnabled = true/false;
|
|
2926
|
+
*/
|
|
2927
|
+
/**
|
|
2928
|
+
* Load ZIP file from buffer (in-memory mode)
|
|
2929
|
+
*
|
|
2930
|
+
* **Required**: You must call this method (or the appropriate load method for your platform)
|
|
2931
|
+
* before calling `getDirectory()` or any other ZIP operations. This method:
|
|
2932
|
+
* 1. Resets all ZIP data
|
|
2933
|
+
* 2. Stores the buffer in this.inBuffer
|
|
2934
|
+
* 3. Loads EOCD and parses central directory
|
|
2935
|
+
* 4. Populates this.zipEntries[] array
|
|
2936
|
+
*
|
|
2937
|
+
* For browser applications, use `ZipkitBrowser.loadZipBlob()` instead.
|
|
2938
|
+
* For server applications with file paths, use `ZipkitServer.loadZipFile()` instead.
|
|
2939
|
+
*
|
|
2940
|
+
* @param inBuf - Buffer containing the complete ZIP file data
|
|
2941
|
+
* @returns ZipEntry[] Array of all entries in the ZIP file
|
|
2942
|
+
*/
|
|
2943
|
+
loadZip(inBuf) {
|
|
2944
|
+
this.resetZipData();
|
|
2945
|
+
this.inBuffer = inBuf;
|
|
2946
|
+
this.loadEOCDFromBuffer(inBuf);
|
|
2947
|
+
const entries = this.getDirectoryFromBuffer();
|
|
2948
|
+
this.zipEntries = entries;
|
|
2949
|
+
return entries;
|
|
2950
|
+
}
|
|
2951
|
+
/**
|
|
2952
|
+
* Reset all ZIP-related data to initial state
|
|
2953
|
+
*
|
|
2954
|
+
* Clears all internal state including zipEntries[], inBuffer, and zipComment.
|
|
2955
|
+
*
|
|
2956
|
+
* Note: ZipCompress and ZipDecompress instances are not recreated.
|
|
2957
|
+
* ZSTD codec is a module-level singleton and is lazily initialized on first use,
|
|
2958
|
+
* so no cleanup is needed. No memory buffers are allocated until compression/decompression
|
|
2959
|
+
* operations are performed.
|
|
2960
|
+
*/
|
|
2961
|
+
resetZipData() {
|
|
2962
|
+
this.inBuffer = null;
|
|
2963
|
+
this.zipEntries = [];
|
|
2964
|
+
this.reset();
|
|
2965
|
+
this.zipComment = null;
|
|
2966
|
+
this._zipkitCmp = null;
|
|
2967
|
+
this._zipkitDeCmp = null;
|
|
2968
|
+
}
|
|
2969
|
+
/**
|
|
2970
|
+
* Get central directory entries (synchronous, buffer-based only)
|
|
2971
|
+
*
|
|
2972
|
+
* Returns entries from zipEntries[] array which serves as unified storage.
|
|
2973
|
+
*
|
|
2974
|
+
* **Important**: This method does NOT load the ZIP file. You must call `loadZip()` first
|
|
2975
|
+
* to populate zipEntries[]. If the ZIP is not loaded, this method returns an empty array.
|
|
2976
|
+
*
|
|
2977
|
+
* @param debug - Optional debug flag for logging
|
|
2978
|
+
* @returns Array of ZipEntry objects, or empty array if ZIP not loaded
|
|
2979
|
+
*/
|
|
2980
|
+
getDirectory(debug) {
|
|
2981
|
+
return this.zipEntries;
|
|
2982
|
+
}
|
|
2983
|
+
/**
|
|
2984
|
+
* Get specific ZIP entry by filename from zipEntries[] array
|
|
2985
|
+
*
|
|
2986
|
+
* @param filename - The name/path of the file/directory to find
|
|
2987
|
+
* @returns ZipEntry object if found, null if not found
|
|
2988
|
+
*/
|
|
2989
|
+
getZipEntry(filename) {
|
|
2990
|
+
try {
|
|
2991
|
+
const centralDir = this.getDirectory();
|
|
2992
|
+
return centralDir.find((entry) => entry.filename === filename) || null;
|
|
2993
|
+
} catch (error) {
|
|
2994
|
+
return null;
|
|
2995
|
+
}
|
|
2996
|
+
}
|
|
2997
|
+
/**
|
|
2998
|
+
* Ensure buffer is available (in-memory mode)
|
|
2999
|
+
*/
|
|
3000
|
+
ensureBuffer() {
|
|
3001
|
+
if (!this.inBuffer) {
|
|
3002
|
+
this.inBuffer = Buffer.alloc(0);
|
|
3003
|
+
}
|
|
3004
|
+
return this.inBuffer;
|
|
3005
|
+
}
|
|
3006
|
+
/**
|
|
3007
|
+
* Parse local header (in-memory mode)
|
|
3008
|
+
*/
|
|
3009
|
+
parseLocalHeader(entry, buffer) {
|
|
3010
|
+
const localData = buffer.subarray(entry.localHdrOffset);
|
|
3011
|
+
if (localData.readUInt32LE(0) !== Headers_1.LOCAL_HDR.SIGNATURE) {
|
|
3012
|
+
throw new Error(Errors_1.default.INVALID_CEN);
|
|
3013
|
+
}
|
|
3014
|
+
let _encryptLen = 0;
|
|
3015
|
+
const _bitFlags = localData.readUInt16LE(Headers_1.LOCAL_HDR.FLAGS);
|
|
3016
|
+
if (_bitFlags & Headers_1.GP_FLAG.ENCRYPTED) {
|
|
3017
|
+
_encryptLen = Headers_1.ENCRYPT_HDR_SIZE;
|
|
3018
|
+
}
|
|
3019
|
+
let _fnameLen = localData.readUInt16LE(Headers_1.LOCAL_HDR.FNAME_LEN);
|
|
3020
|
+
let _extraLen = localData.readUInt16LE(Headers_1.LOCAL_HDR.EXTRA_LEN);
|
|
3021
|
+
let _localSize = Headers_1.LOCAL_HDR.SIZE + _fnameLen + _extraLen;
|
|
3022
|
+
const dataStart = _localSize + _encryptLen;
|
|
3023
|
+
const dataEnd = _localSize + entry.compressedSize;
|
|
3024
|
+
return localData.subarray(dataStart, dataEnd);
|
|
3025
|
+
}
|
|
3026
|
+
/**
|
|
3027
|
+
* Test CRC32 checksum
|
|
3028
|
+
* Always checks CRC against entry.crc from central directory
|
|
3029
|
+
* For DATA_DESC files, CRC is stored in central directory, not local header
|
|
3030
|
+
*/
|
|
3031
|
+
testCRC32(entry, data) {
|
|
3032
|
+
const _crc = (0, ZipCrypto_12.crc32)(data);
|
|
3033
|
+
const isValid = _crc === entry.crc;
|
|
3034
|
+
Logger_12.Logger.debug(`[DEBUG] testCRC32() comparison: calculated=${_crc}, stored=${entry.crc}, isValid=${isValid ? "\u2713" : "\u2717"}, DATA_DESC=${(entry.bitFlags & 8) !== 0 ? "YES" : "NO"}`);
|
|
3035
|
+
return isValid;
|
|
3036
|
+
}
|
|
3037
|
+
/**
|
|
3038
|
+
* Test SHA256 hash
|
|
3039
|
+
*/
|
|
3040
|
+
testSHA256(entry, data) {
|
|
3041
|
+
if (!entry.sha256) {
|
|
3042
|
+
throw new Error(Errors_1.default.UNKNOWN_SHA256);
|
|
3043
|
+
}
|
|
3044
|
+
const _sha256 = (0, ZipCrypto_12.sha256)(data);
|
|
3045
|
+
const isValid = _sha256 === entry.sha256;
|
|
3046
|
+
Logger_12.Logger.debug(`[DEBUG] testSHA256() comparison: calculated=${_sha256}, stored=${entry.sha256}, isValid=${isValid ? "\u2713" : "\u2717"}`);
|
|
3047
|
+
return isValid;
|
|
3048
|
+
}
|
|
3049
|
+
/**
|
|
3050
|
+
* Get memory usage statistics
|
|
3051
|
+
*
|
|
3052
|
+
* @returns Object containing backend type, total memory usage in bytes, and entry count
|
|
3053
|
+
*/
|
|
3054
|
+
getMemoryUsage() {
|
|
3055
|
+
const baseMemory = this.inBuffer?.length || 0;
|
|
3056
|
+
const entriesMemory = this.zipEntries.length * 1024;
|
|
3057
|
+
let backend;
|
|
3058
|
+
if (this.inBuffer) {
|
|
3059
|
+
backend = "buffer";
|
|
3060
|
+
} else {
|
|
3061
|
+
backend = "none";
|
|
3062
|
+
}
|
|
3063
|
+
return {
|
|
3064
|
+
backend,
|
|
3065
|
+
memoryUsage: baseMemory + entriesMemory,
|
|
3066
|
+
entries: this.zipEntries.length
|
|
3067
|
+
};
|
|
3068
|
+
}
|
|
3069
|
+
/**
|
|
3070
|
+
* Create a new ZIP entry and automatically add it to zipEntries[]
|
|
3071
|
+
*
|
|
3072
|
+
* @param filename - Entry filename
|
|
3073
|
+
* @param data - Optional entry data (for CRC calculation)
|
|
3074
|
+
* @param options - Optional entry options
|
|
3075
|
+
* @returns Created ZipEntry instance
|
|
3076
|
+
*/
|
|
3077
|
+
createZipEntry(filename, data, options) {
|
|
3078
|
+
const entry = new ZipEntry_1.default(filename, null, false);
|
|
3079
|
+
if (data) {
|
|
3080
|
+
entry.crc = (0, ZipCrypto_12.crc32)(data);
|
|
3081
|
+
entry.uncompressedSize = data.length;
|
|
3082
|
+
entry.compressedSize = data.length;
|
|
3083
|
+
} else {
|
|
3084
|
+
entry.crc = 0;
|
|
3085
|
+
entry.uncompressedSize = 0;
|
|
3086
|
+
entry.compressedSize = 0;
|
|
3087
|
+
}
|
|
3088
|
+
entry.cmpMethod = Headers_1.CMP_METHOD.STORED;
|
|
3089
|
+
entry.bitFlags = 0;
|
|
3090
|
+
this.zipEntries.push(entry);
|
|
3091
|
+
return entry;
|
|
3092
|
+
}
|
|
3093
|
+
/**
|
|
3094
|
+
* Copy entry from another ZIP (buffer-based only)
|
|
3095
|
+
* For file-based ZIP operations, use ZipkitServer.copyEntry()
|
|
3096
|
+
*/
|
|
3097
|
+
async copyEntry(sourceEntry) {
|
|
3098
|
+
if (sourceEntry.cmpData) {
|
|
3099
|
+
const localHdr = sourceEntry.createLocalHdr();
|
|
3100
|
+
return Buffer.concat([localHdr, sourceEntry.cmpData]);
|
|
3101
|
+
}
|
|
3102
|
+
throw new Error("Cannot copy entry: no compressed data available");
|
|
3103
|
+
}
|
|
3104
|
+
/**
|
|
3105
|
+
* Central end header getter (for compatibility)
|
|
3106
|
+
*
|
|
3107
|
+
* Returns a function that creates the central end header using totalEntries from zipEntries[].
|
|
3108
|
+
*
|
|
3109
|
+
* @returns Function that creates central end header buffer
|
|
3110
|
+
*/
|
|
3111
|
+
get centralEndHdr() {
|
|
3112
|
+
return (centralDirSize, centralDirOffset) => {
|
|
3113
|
+
const totalEntries = this.zipEntries.length;
|
|
3114
|
+
return this.centralEndHdrMethod(centralDirSize, centralDirOffset, totalEntries);
|
|
3115
|
+
};
|
|
3116
|
+
}
|
|
3117
|
+
/**
|
|
3118
|
+
* Get ZIP comment
|
|
3119
|
+
*
|
|
3120
|
+
* @returns ZIP file comment string or null
|
|
3121
|
+
*/
|
|
3122
|
+
getZipComment() {
|
|
3123
|
+
return this.zipComment;
|
|
3124
|
+
}
|
|
3125
|
+
// ============================================================================
|
|
3126
|
+
// Buffer-based ZIP Loading Methods (merged from ZipLoadEntries)
|
|
3127
|
+
// ============================================================================
|
|
3128
|
+
/**
|
|
3129
|
+
* Load EOCD from in-memory buffer (buffer mode)
|
|
3130
|
+
*/
|
|
3131
|
+
loadEOCDFromBuffer(buffer) {
|
|
3132
|
+
const fileSize = buffer.length;
|
|
3133
|
+
const searchSize = Math.min(65535 + 22, fileSize);
|
|
3134
|
+
const searchStart = fileSize - searchSize;
|
|
3135
|
+
const scan = buffer.subarray(searchStart, searchStart + searchSize);
|
|
3136
|
+
let eocdOffset = -1;
|
|
3137
|
+
for (let i = scan.length - 22; i >= 0; i--) {
|
|
3138
|
+
if (scan[i] === 80) {
|
|
3139
|
+
if (scan.readUInt32LE(i) === Headers_1.CENTRAL_END.SIGNATURE) {
|
|
3140
|
+
eocdOffset = searchStart + i;
|
|
3141
|
+
break;
|
|
3142
|
+
}
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3145
|
+
if (eocdOffset === -1) {
|
|
3146
|
+
throw new Error(Errors_1.default.INVALID_FORMAT);
|
|
3147
|
+
}
|
|
3148
|
+
const eocdBuffer = buffer.subarray(eocdOffset, eocdOffset + 22);
|
|
3149
|
+
if (eocdBuffer.readUInt32LE(0) === Headers_1.CENTRAL_END.SIGNATURE) {
|
|
3150
|
+
this.centralDirSize = eocdBuffer.readUInt32LE(Headers_1.CENTRAL_END.CENTRAL_DIR_SIZE);
|
|
3151
|
+
this.centralDirOffset = eocdBuffer.readUInt32LE(Headers_1.CENTRAL_END.CENTRAL_DIR_OFFSET);
|
|
3152
|
+
if (this.centralDirOffset === 4294967295) {
|
|
3153
|
+
const locatorOffset = eocdOffset - 20;
|
|
3154
|
+
const locatorBuffer = buffer.subarray(locatorOffset, locatorOffset + 20);
|
|
3155
|
+
if (locatorBuffer.readUInt32LE(0) === Headers_1.ZIP64_CENTRAL_END.SIGNATURE) {
|
|
3156
|
+
const zip64Offset = Number(locatorBuffer.readBigUInt64LE(8));
|
|
3157
|
+
const zip64Buffer = buffer.subarray(zip64Offset, zip64Offset + 56);
|
|
3158
|
+
this.centralDirSize = Number(zip64Buffer.readBigUInt64LE(Headers_1.ZIP64_CENTRAL_DIR.CENTRAL_DIR_SIZE));
|
|
3159
|
+
this.centralDirOffset = Number(zip64Buffer.readBigUInt64LE(Headers_1.ZIP64_CENTRAL_DIR.CENTRAL_DIR_OFFSET));
|
|
3160
|
+
}
|
|
3161
|
+
}
|
|
3162
|
+
} else {
|
|
3163
|
+
throw new Error(Errors_1.default.INVALID_FORMAT);
|
|
3164
|
+
}
|
|
3165
|
+
const commentLength = eocdBuffer.readUInt16LE(Headers_1.CENTRAL_END.ZIP_COMMENT_LEN);
|
|
3166
|
+
if (commentLength > 0) {
|
|
3167
|
+
const commentStart = eocdOffset + 22;
|
|
3168
|
+
this.zipComment = buffer.subarray(commentStart, commentStart + commentLength).toString();
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
3171
|
+
/**
|
|
3172
|
+
* Get directory from buffer (buffer mode only)
|
|
3173
|
+
* Note: zipEntries[] in Zipkit is the single source of truth for caching.
|
|
3174
|
+
* This method always parses fresh from the buffer.
|
|
3175
|
+
*/
|
|
3176
|
+
getDirectoryFromBuffer() {
|
|
3177
|
+
if (!this.inBuffer) {
|
|
3178
|
+
return [];
|
|
3179
|
+
}
|
|
3180
|
+
const buffer = this.inBuffer;
|
|
3181
|
+
const entries = [];
|
|
3182
|
+
let offset = this.centralDirOffset;
|
|
3183
|
+
let remaining = this.centralDirSize;
|
|
3184
|
+
const bufferSize = this.config.bufferSize || 512 * 1024;
|
|
3185
|
+
while (remaining > 0) {
|
|
3186
|
+
const currentBufferSize = Math.min(bufferSize, remaining);
|
|
3187
|
+
const chunk = buffer.subarray(offset, offset + currentBufferSize);
|
|
3188
|
+
let chunkOffset = 0;
|
|
3189
|
+
while (chunkOffset < chunk.length) {
|
|
3190
|
+
if (chunk.readUInt32LE(chunkOffset) !== Headers_1.CENTRAL_DIR.SIGNATURE) {
|
|
3191
|
+
break;
|
|
3192
|
+
}
|
|
3193
|
+
const entry = new ZipEntry_1.default(null, null, false);
|
|
3194
|
+
const entryData = chunk.subarray(chunkOffset);
|
|
3195
|
+
const remainingData = entry.readZipEntry(entryData);
|
|
3196
|
+
entries.push(entry);
|
|
3197
|
+
chunkOffset += entryData.length - remainingData.length;
|
|
3198
|
+
}
|
|
3199
|
+
offset += currentBufferSize;
|
|
3200
|
+
remaining -= currentBufferSize;
|
|
3201
|
+
}
|
|
3202
|
+
return entries;
|
|
3203
|
+
}
|
|
3204
|
+
/**
|
|
3205
|
+
* Reset internal state (private method for Zipkit to call)
|
|
3206
|
+
* Clears all ZIP-related data while keeping the instance alive
|
|
3207
|
+
*/
|
|
3208
|
+
reset() {
|
|
3209
|
+
this.centralDirSize = 0;
|
|
3210
|
+
this.centralDirOffset = 0;
|
|
3211
|
+
}
|
|
3212
|
+
/**
|
|
3213
|
+
* Create central end header
|
|
3214
|
+
* Note: totalEntries must be passed as parameter since zipEntries[] in Zipkit is the cache
|
|
3215
|
+
*/
|
|
3216
|
+
centralEndHdrMethod(centralDirSize, centralDirOffset, totalEntries) {
|
|
3217
|
+
const ceBuf = Buffer.alloc(Headers_1.CENTRAL_END.SIZE);
|
|
3218
|
+
ceBuf.writeUInt32LE(Headers_1.CENTRAL_END.SIGNATURE, 0);
|
|
3219
|
+
ceBuf.writeUInt16LE(0, 4);
|
|
3220
|
+
ceBuf.writeUInt16LE(0, 6);
|
|
3221
|
+
ceBuf.writeUInt16LE(totalEntries, 8);
|
|
3222
|
+
ceBuf.writeUInt16LE(totalEntries, 10);
|
|
3223
|
+
ceBuf.writeUInt32LE(centralDirSize, 12);
|
|
3224
|
+
ceBuf.writeUInt32LE(centralDirOffset, 16);
|
|
3225
|
+
ceBuf.writeUInt16LE(0, 20);
|
|
3226
|
+
return ceBuf;
|
|
3227
|
+
}
|
|
3228
|
+
/**
|
|
3229
|
+
* Calculate Merkle Root of the ZIP file
|
|
3230
|
+
*
|
|
3231
|
+
* Excludes blockchain metadata files to ensure consistent calculation.
|
|
3232
|
+
* Simply calls getDirectory() and returns null if empty.
|
|
3233
|
+
*
|
|
3234
|
+
* @returns Merkle root string or null if calculation fails
|
|
3235
|
+
*/
|
|
3236
|
+
getMerkleRoot() {
|
|
3237
|
+
let zipEntries;
|
|
3238
|
+
try {
|
|
3239
|
+
zipEntries = this.getDirectory();
|
|
3240
|
+
} catch (error) {
|
|
3241
|
+
Logger_12.Logger.error(`getMerkleRoot(): Error calling getDirectory(): ${error instanceof Error ? error.message : String(error)}`);
|
|
3242
|
+
Logger_12.Logger.error(`getMerkleRoot(): Stack trace: ${error instanceof Error ? error.stack : "No stack trace"}`);
|
|
3243
|
+
return null;
|
|
3244
|
+
}
|
|
3245
|
+
if (!zipEntries || zipEntries.length === 0) {
|
|
3246
|
+
return null;
|
|
3247
|
+
}
|
|
3248
|
+
const hashAccumulator = new HashCalculator_12.default({ enableAccumulation: true });
|
|
3249
|
+
const contentEntries = zipEntries.filter((entry) => {
|
|
3250
|
+
const filename = entry.filename || "";
|
|
3251
|
+
return filename !== Headers_1.TIMESTAMP_SUBMITTED && filename !== Headers_1.TIMESTAMP_METADATA && filename !== Headers_1.TOKENIZED_METADATA;
|
|
3252
|
+
});
|
|
3253
|
+
for (const entry of contentEntries) {
|
|
3254
|
+
if (entry.sha256) {
|
|
3255
|
+
const hashBuffer = Buffer.from(entry.sha256, "hex");
|
|
3256
|
+
hashAccumulator.addHash(hashBuffer);
|
|
3257
|
+
}
|
|
3258
|
+
}
|
|
3259
|
+
const merkleRoot = hashAccumulator.merkleRoot();
|
|
3260
|
+
if (!merkleRoot) {
|
|
3261
|
+
return null;
|
|
3262
|
+
}
|
|
3263
|
+
return merkleRoot;
|
|
3264
|
+
}
|
|
3265
|
+
/**
|
|
3266
|
+
* Calculate Merkle Root of the ZIP file asynchronously
|
|
3267
|
+
*
|
|
3268
|
+
* Excludes blockchain metadata files to ensure consistent calculation.
|
|
3269
|
+
* Works with both buffer-based and file-based ZIPs.
|
|
3270
|
+
*
|
|
3271
|
+
* @returns Promise resolving to Merkle root string or null if calculation fails
|
|
3272
|
+
*/
|
|
3273
|
+
async getMerkleRootAsync() {
|
|
3274
|
+
let zipEntries = [];
|
|
3275
|
+
try {
|
|
3276
|
+
if (this.inBuffer) {
|
|
3277
|
+
zipEntries = this.getDirectory();
|
|
3278
|
+
} else {
|
|
3279
|
+
Logger_12.Logger.error("getMerkleRootAsync() called on file-based ZIP. Use ZipkitServer.getMerkleRootAsync() instead.");
|
|
3280
|
+
return null;
|
|
3281
|
+
}
|
|
3282
|
+
} catch (error) {
|
|
3283
|
+
Logger_12.Logger.error(`Failed to get directory for merkle root calculation: ${error instanceof Error ? error.message : String(error)}`);
|
|
3284
|
+
return null;
|
|
3285
|
+
}
|
|
3286
|
+
if (!zipEntries || zipEntries.length === 0) {
|
|
3287
|
+
return null;
|
|
3288
|
+
}
|
|
3289
|
+
const hashAccumulator = new HashCalculator_12.default({ enableAccumulation: true });
|
|
3290
|
+
const contentEntries = zipEntries.filter((entry) => {
|
|
3291
|
+
const filename = entry.filename || "";
|
|
3292
|
+
return filename !== Headers_1.TIMESTAMP_SUBMITTED && filename !== Headers_1.TIMESTAMP_METADATA && filename !== Headers_1.TOKENIZED_METADATA;
|
|
3293
|
+
});
|
|
3294
|
+
for (const entry of contentEntries) {
|
|
3295
|
+
if (entry.sha256) {
|
|
3296
|
+
const hashBuffer = Buffer.from(entry.sha256, "hex");
|
|
3297
|
+
hashAccumulator.addHash(hashBuffer);
|
|
3298
|
+
}
|
|
3299
|
+
}
|
|
3300
|
+
const merkleRoot = hashAccumulator.merkleRoot();
|
|
3301
|
+
if (!merkleRoot) {
|
|
3302
|
+
return null;
|
|
3303
|
+
}
|
|
3304
|
+
return merkleRoot;
|
|
3305
|
+
}
|
|
3306
|
+
};
|
|
3307
|
+
Zipkit.version = types_1.NEOZIPKIT_INFO.version;
|
|
3308
|
+
Zipkit.releaseDate = types_1.NEOZIPKIT_INFO.releaseDate;
|
|
3309
|
+
exports2.default = Zipkit;
|
|
3310
|
+
}
|
|
3311
|
+
});
|
|
3312
|
+
|
|
3313
|
+
// neozipkit/dist/core/components/Support.js
|
|
3314
|
+
var require_Support = __commonJS({
|
|
3315
|
+
"neozipkit/dist/core/components/Support.js"(exports2) {
|
|
3316
|
+
"use strict";
|
|
3317
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3318
|
+
var Support = {
|
|
3319
|
+
/** Base64 encoding support (always true) */
|
|
3320
|
+
base64: true,
|
|
3321
|
+
/** Array support (always true) */
|
|
3322
|
+
array: true,
|
|
3323
|
+
/** String support (always true) */
|
|
3324
|
+
string: true,
|
|
3325
|
+
/**
|
|
3326
|
+
* Detects if code is running in Node.js environment
|
|
3327
|
+
* True if process.versions.node exists, undefined in browser
|
|
3328
|
+
*/
|
|
3329
|
+
isNode: true,
|
|
3330
|
+
/**
|
|
3331
|
+
* Detects if Node.js Buffer is available
|
|
3332
|
+
* True in Node.js, undefined in browser
|
|
3333
|
+
*/
|
|
3334
|
+
buffer: true,
|
|
3335
|
+
/**
|
|
3336
|
+
* Detects support for Uint8Array typed array
|
|
3337
|
+
* Used for binary data handling
|
|
3338
|
+
*/
|
|
3339
|
+
uint8array: true,
|
|
3340
|
+
/**
|
|
3341
|
+
* Detects support for both ArrayBuffer and Uint8Array
|
|
3342
|
+
* Required for binary data operations
|
|
3343
|
+
*/
|
|
3344
|
+
arrayBuffer: typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined",
|
|
3345
|
+
/**
|
|
3346
|
+
* Detects support for Blob with ArrayBuffer
|
|
3347
|
+
* Tests by attempting to create an empty ZIP Blob
|
|
3348
|
+
* @returns {boolean} True if Blob creation succeeds
|
|
3349
|
+
*/
|
|
3350
|
+
blob: true,
|
|
3351
|
+
/**
|
|
3352
|
+
* Detects support for Streams API
|
|
3353
|
+
* Checks for ReadableStream/WritableStream in browser
|
|
3354
|
+
* or 'stream' module in Node.js
|
|
3355
|
+
* @returns {boolean} True if streams are supported in current environment
|
|
3356
|
+
*/
|
|
3357
|
+
streams: true,
|
|
3358
|
+
/**
|
|
3359
|
+
* Detects support for FileReader
|
|
3360
|
+
* @returns {boolean} True if FileReader is supported
|
|
3361
|
+
*/
|
|
3362
|
+
fileReader: false
|
|
3363
|
+
};
|
|
3364
|
+
exports2.default = Support;
|
|
3365
|
+
}
|
|
3366
|
+
});
|
|
3367
|
+
|
|
3368
|
+
// neozipkit/dist/core/components/Util.js
|
|
3369
|
+
var require_Util = __commonJS({
|
|
3370
|
+
"neozipkit/dist/core/components/Util.js"(exports2) {
|
|
3371
|
+
"use strict";
|
|
3372
|
+
var __importDefault2 = exports2 && exports2.__importDefault || function(mod) {
|
|
3373
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
3374
|
+
};
|
|
3375
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3376
|
+
exports2.isMetadataFile = exports2.uMul = exports2.DATATYPE = void 0;
|
|
3377
|
+
exports2.readBigUInt64LE = readBigUInt64LE;
|
|
3378
|
+
exports2.isStream = isStream;
|
|
3379
|
+
exports2.getTypeOf = getTypeOf;
|
|
3380
|
+
var Support_1 = __importDefault2(require_Support());
|
|
3381
|
+
var Errors_1 = __importDefault2(require_Errors());
|
|
3382
|
+
var Headers_1 = require_Headers();
|
|
3383
|
+
exports2.DATATYPE = {
|
|
3384
|
+
STRING: "string",
|
|
3385
|
+
BUFFER: "buffer",
|
|
3386
|
+
ARRAY: "array",
|
|
3387
|
+
ARRAYBUFFER: "arraybuffer",
|
|
3388
|
+
U8ARRAY: "uint8array",
|
|
3389
|
+
BLOB: "blob",
|
|
3390
|
+
STREAM: "stream"
|
|
3391
|
+
};
|
|
3392
|
+
function readBigUInt64LE(buffer, index) {
|
|
3393
|
+
var buf = Buffer.from(buffer.subarray(index, index + 8));
|
|
3394
|
+
buf.swap64();
|
|
3395
|
+
return parseInt(`0x${buf.toString("hex")}`);
|
|
3396
|
+
}
|
|
3397
|
+
__name(readBigUInt64LE, "readBigUInt64LE");
|
|
3398
|
+
var uMul = /* @__PURE__ */ __name((a, b) => Math.imul(a, b) >>> 0, "uMul");
|
|
3399
|
+
exports2.uMul = uMul;
|
|
3400
|
+
function isStream(obj) {
|
|
3401
|
+
if (!obj || typeof obj !== "object")
|
|
3402
|
+
return false;
|
|
3403
|
+
const streamLike = obj;
|
|
3404
|
+
return typeof streamLike.on === "function" && typeof streamLike.pause === "function" && typeof streamLike.resume === "function";
|
|
3405
|
+
}
|
|
3406
|
+
__name(isStream, "isStream");
|
|
3407
|
+
function getTypeOf(input) {
|
|
3408
|
+
if (typeof input === "string") {
|
|
3409
|
+
if (!Support_1.default.string)
|
|
3410
|
+
throw new Error(Errors_1.default.DATATYPE_STRING_UNSUPPORTED);
|
|
3411
|
+
return exports2.DATATYPE.STRING;
|
|
3412
|
+
} else if (Object.prototype.toString.call(input) === "[object Array]") {
|
|
3413
|
+
if (!Support_1.default.array)
|
|
3414
|
+
throw new Error(Errors_1.default.DATATYPE_ARRAY_UNSUPPORTED);
|
|
3415
|
+
return exports2.DATATYPE.ARRAY;
|
|
3416
|
+
} else if (Buffer.isBuffer(input)) {
|
|
3417
|
+
if (!Support_1.default.buffer)
|
|
3418
|
+
throw new Error(Errors_1.default.DATATYPE_BUFFER_UNSUPPORTED);
|
|
3419
|
+
return exports2.DATATYPE.BUFFER;
|
|
3420
|
+
} else if (input instanceof Blob) {
|
|
3421
|
+
if (!Support_1.default.blob)
|
|
3422
|
+
throw new Error(Errors_1.default.DATATYPE_BLOB_UNSUPPORTED);
|
|
3423
|
+
return exports2.DATATYPE.BLOB;
|
|
3424
|
+
} else if (input instanceof Uint8Array) {
|
|
3425
|
+
if (!Support_1.default.uint8array)
|
|
3426
|
+
throw new Error(Errors_1.default.DATATYPE_U8ARRAY_UNSUPPORTED);
|
|
3427
|
+
return exports2.DATATYPE.U8ARRAY;
|
|
3428
|
+
} else if (input instanceof ArrayBuffer) {
|
|
3429
|
+
if (!Support_1.default.arrayBuffer)
|
|
3430
|
+
throw new Error(Errors_1.default.DATATYPE_ARRAYBUFFER_UNSUPPORTED);
|
|
3431
|
+
return exports2.DATATYPE.ARRAYBUFFER;
|
|
3432
|
+
} else {
|
|
3433
|
+
throw new Error(Errors_1.default.DATATYPE_UNSUPPORTED);
|
|
3434
|
+
}
|
|
3435
|
+
}
|
|
3436
|
+
__name(getTypeOf, "getTypeOf");
|
|
3437
|
+
var isMetadataFile = /* @__PURE__ */ __name((filename) => {
|
|
3438
|
+
return filename === Headers_1.TIMESTAMP_SUBMITTED || filename === Headers_1.TIMESTAMP_METADATA || filename === Headers_1.TOKENIZED_METADATA;
|
|
3439
|
+
}, "isMetadataFile");
|
|
3440
|
+
exports2.isMetadataFile = isMetadataFile;
|
|
3441
|
+
}
|
|
3442
|
+
});
|
|
3443
|
+
|
|
3444
|
+
// neozipkit/dist/core/components/ProgressTracker.js
|
|
3445
|
+
var require_ProgressTracker = __commonJS({
|
|
3446
|
+
"neozipkit/dist/core/components/ProgressTracker.js"(exports2) {
|
|
3447
|
+
"use strict";
|
|
3448
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3449
|
+
exports2.ProgressTracker = void 0;
|
|
3450
|
+
var ProgressTracker = class {
|
|
3451
|
+
static {
|
|
3452
|
+
__name(this, "ProgressTracker");
|
|
3453
|
+
}
|
|
3454
|
+
constructor(fileName, totalBytes) {
|
|
3455
|
+
this.lastReportedPercent = -1;
|
|
3456
|
+
this.fileName = fileName;
|
|
3457
|
+
this.totalBytes = totalBytes;
|
|
3458
|
+
this.processedBytes = 0;
|
|
3459
|
+
this.startTime = Date.now();
|
|
3460
|
+
this.lastUpdateTime = this.startTime;
|
|
3461
|
+
}
|
|
3462
|
+
/**
|
|
3463
|
+
* Update progress with bytes processed
|
|
3464
|
+
* @param bytesProcessed - Number of bytes processed in this update
|
|
3465
|
+
*/
|
|
3466
|
+
update(bytesProcessed) {
|
|
3467
|
+
this.processedBytes += bytesProcessed;
|
|
3468
|
+
this.reportProgress();
|
|
3469
|
+
}
|
|
3470
|
+
/**
|
|
3471
|
+
* Set total bytes (useful when file size changes)
|
|
3472
|
+
*/
|
|
3473
|
+
setTotalBytes(totalBytes) {
|
|
3474
|
+
this.totalBytes = totalBytes;
|
|
3475
|
+
}
|
|
3476
|
+
/**
|
|
3477
|
+
* Report progress if enough time has passed or significant progress made
|
|
3478
|
+
*/
|
|
3479
|
+
reportProgress() {
|
|
3480
|
+
const now = Date.now();
|
|
3481
|
+
const percent = Math.floor(this.processedBytes / this.totalBytes * 100);
|
|
3482
|
+
const shouldReport = percent > this.lastReportedPercent || now - this.lastUpdateTime > 500;
|
|
3483
|
+
if (shouldReport) {
|
|
3484
|
+
this.lastReportedPercent = percent;
|
|
3485
|
+
this.lastUpdateTime = now;
|
|
3486
|
+
this.printProgress();
|
|
3487
|
+
}
|
|
3488
|
+
}
|
|
3489
|
+
/**
|
|
3490
|
+
* Print progress information
|
|
3491
|
+
*/
|
|
3492
|
+
printProgress() {
|
|
3493
|
+
const elapsed = (Date.now() - this.startTime) / 1e3;
|
|
3494
|
+
const rate = this.processedBytes / elapsed;
|
|
3495
|
+
const eta = this.totalBytes > this.processedBytes ? (this.totalBytes - this.processedBytes) / rate : 0;
|
|
3496
|
+
const percent = Math.floor(this.processedBytes / this.totalBytes * 100);
|
|
3497
|
+
const formatBytes = /* @__PURE__ */ __name((bytes) => {
|
|
3498
|
+
const units = ["B", "KB", "MB", "GB"];
|
|
3499
|
+
let size = bytes;
|
|
3500
|
+
let unitIndex = 0;
|
|
3501
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
3502
|
+
size /= 1024;
|
|
3503
|
+
unitIndex++;
|
|
3504
|
+
}
|
|
3505
|
+
return `${size.toFixed(1)}${units[unitIndex]}`;
|
|
3506
|
+
}, "formatBytes");
|
|
3507
|
+
const formatTime = /* @__PURE__ */ __name((seconds) => {
|
|
3508
|
+
if (seconds < 60)
|
|
3509
|
+
return `${seconds.toFixed(0)}s`;
|
|
3510
|
+
if (seconds < 3600)
|
|
3511
|
+
return `${Math.floor(seconds / 60)}m ${(seconds % 60).toFixed(0)}s`;
|
|
3512
|
+
return `${Math.floor(seconds / 3600)}h ${Math.floor(seconds % 3600 / 60)}m`;
|
|
3513
|
+
}, "formatTime");
|
|
3514
|
+
process.stdout.write(`\r${this.fileName}: ${percent}% (${formatBytes(this.processedBytes)}/${formatBytes(this.totalBytes)}) [${formatBytes(rate)}/s] ETA: ${formatTime(eta)}`);
|
|
3515
|
+
}
|
|
3516
|
+
/**
|
|
3517
|
+
* Complete progress tracking
|
|
3518
|
+
*/
|
|
3519
|
+
complete() {
|
|
3520
|
+
const elapsed = (Date.now() - this.startTime) / 1e3;
|
|
3521
|
+
const rate = this.processedBytes / elapsed;
|
|
3522
|
+
const formatBytes = /* @__PURE__ */ __name((bytes) => {
|
|
3523
|
+
const units = ["B", "KB", "MB", "GB"];
|
|
3524
|
+
let size = bytes;
|
|
3525
|
+
let unitIndex = 0;
|
|
3526
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
3527
|
+
size /= 1024;
|
|
3528
|
+
unitIndex++;
|
|
3529
|
+
}
|
|
3530
|
+
return `${size.toFixed(1)}${units[unitIndex]}`;
|
|
3531
|
+
}, "formatBytes");
|
|
3532
|
+
console.log(`\r${this.fileName}: 100% (${formatBytes(this.processedBytes)}) [${formatBytes(rate)}/s] completed in ${elapsed.toFixed(1)}s`);
|
|
3533
|
+
}
|
|
3534
|
+
/**
|
|
3535
|
+
* Get current progress percentage
|
|
3536
|
+
*/
|
|
3537
|
+
getProgressPercent() {
|
|
3538
|
+
return Math.floor(this.processedBytes / this.totalBytes * 100);
|
|
3539
|
+
}
|
|
3540
|
+
/**
|
|
3541
|
+
* Get processing rate in bytes per second
|
|
3542
|
+
*/
|
|
3543
|
+
getProcessingRate() {
|
|
3544
|
+
const elapsed = (Date.now() - this.startTime) / 1e3;
|
|
3545
|
+
return this.processedBytes / elapsed;
|
|
3546
|
+
}
|
|
3547
|
+
};
|
|
3548
|
+
exports2.ProgressTracker = ProgressTracker;
|
|
3549
|
+
}
|
|
3550
|
+
});
|
|
3551
|
+
|
|
3552
|
+
// neozipkit/dist/core/encryption/Manager.js
|
|
3553
|
+
var require_Manager = __commonJS({
|
|
3554
|
+
"neozipkit/dist/core/encryption/Manager.js"(exports2) {
|
|
3555
|
+
"use strict";
|
|
3556
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3557
|
+
exports2.EncryptionManager = void 0;
|
|
3558
|
+
var types_1 = require_types();
|
|
3559
|
+
var ZipCrypto_12 = require_ZipCrypto();
|
|
3560
|
+
var EncryptionManager = class {
|
|
3561
|
+
static {
|
|
3562
|
+
__name(this, "EncryptionManager");
|
|
3563
|
+
}
|
|
3564
|
+
constructor() {
|
|
3565
|
+
this.providers = /* @__PURE__ */ new Map();
|
|
3566
|
+
this.registerProvider(new ZipCrypto_12.ZipCrypto());
|
|
3567
|
+
}
|
|
3568
|
+
/**
|
|
3569
|
+
* Register a new encryption provider
|
|
3570
|
+
*/
|
|
3571
|
+
registerProvider(provider) {
|
|
3572
|
+
if (provider.canHandle(types_1.EncryptionMethod.ZIP_CRYPTO)) {
|
|
3573
|
+
this.providers.set(types_1.EncryptionMethod.ZIP_CRYPTO, provider);
|
|
3574
|
+
}
|
|
3575
|
+
}
|
|
3576
|
+
/**
|
|
3577
|
+
* Get available encryption methods
|
|
3578
|
+
*/
|
|
3579
|
+
getAvailableMethods() {
|
|
3580
|
+
return Array.from(this.providers.keys());
|
|
3581
|
+
}
|
|
3582
|
+
/**
|
|
3583
|
+
* Get encryption provider for a specific method
|
|
3584
|
+
*/
|
|
3585
|
+
getProvider(method) {
|
|
3586
|
+
return this.providers.get(method) || null;
|
|
3587
|
+
}
|
|
3588
|
+
/**
|
|
3589
|
+
* Encrypt data using specified method
|
|
3590
|
+
*/
|
|
3591
|
+
async encrypt(data, options) {
|
|
3592
|
+
const provider = this.getProvider(options.method);
|
|
3593
|
+
if (!provider) {
|
|
3594
|
+
return {
|
|
3595
|
+
success: false,
|
|
3596
|
+
error: `No encryption provider available for method ${options.method}`
|
|
3597
|
+
};
|
|
3598
|
+
}
|
|
3599
|
+
return await provider.encrypt(data, options);
|
|
3600
|
+
}
|
|
3601
|
+
/**
|
|
3602
|
+
* Decrypt data using specified method
|
|
3603
|
+
*/
|
|
3604
|
+
async decrypt(data, options) {
|
|
3605
|
+
const provider = this.getProvider(options.method);
|
|
3606
|
+
if (!provider) {
|
|
3607
|
+
return {
|
|
3608
|
+
success: false,
|
|
3609
|
+
error: `No decryption provider available for method ${options.method}`
|
|
3610
|
+
};
|
|
3611
|
+
}
|
|
3612
|
+
return await provider.decrypt(data, options);
|
|
3613
|
+
}
|
|
3614
|
+
/**
|
|
3615
|
+
* Get recommended encryption method (ZIP_CRYPTO)
|
|
3616
|
+
*/
|
|
3617
|
+
getRecommendedMethod() {
|
|
3618
|
+
return types_1.EncryptionMethod.ZIP_CRYPTO;
|
|
3619
|
+
}
|
|
3620
|
+
/**
|
|
3621
|
+
* Validate encryption options
|
|
3622
|
+
*/
|
|
3623
|
+
validateOptions(options) {
|
|
3624
|
+
const errors = [];
|
|
3625
|
+
if (!options.method) {
|
|
3626
|
+
errors.push("Encryption method is required");
|
|
3627
|
+
}
|
|
3628
|
+
if (!options.password || options.password.length === 0) {
|
|
3629
|
+
errors.push("Password is required");
|
|
3630
|
+
}
|
|
3631
|
+
if (options.password && options.password.length < 4) {
|
|
3632
|
+
errors.push("Password must be at least 4 characters long");
|
|
3633
|
+
}
|
|
3634
|
+
return {
|
|
3635
|
+
isValid: errors.length === 0,
|
|
3636
|
+
errors
|
|
3637
|
+
};
|
|
3638
|
+
}
|
|
3639
|
+
/**
|
|
3640
|
+
* Get encryption method info
|
|
3641
|
+
*/
|
|
3642
|
+
getMethodInfo(method) {
|
|
3643
|
+
const provider = this.getProvider(method);
|
|
3644
|
+
if (!provider) {
|
|
3645
|
+
return null;
|
|
3646
|
+
}
|
|
3647
|
+
return {
|
|
3648
|
+
name: provider.getMethodName(),
|
|
3649
|
+
keyLength: provider.getKeyLength(),
|
|
3650
|
+
secure: false
|
|
3651
|
+
};
|
|
3652
|
+
}
|
|
3653
|
+
/**
|
|
3654
|
+
* List all available encryption methods with their details
|
|
3655
|
+
*/
|
|
3656
|
+
listMethods() {
|
|
3657
|
+
const methods = [];
|
|
3658
|
+
for (const [method, provider] of this.providers) {
|
|
3659
|
+
methods.push({
|
|
3660
|
+
method,
|
|
3661
|
+
name: provider.getMethodName(),
|
|
3662
|
+
keyLength: provider.getKeyLength(),
|
|
3663
|
+
secure: false
|
|
3664
|
+
});
|
|
3665
|
+
}
|
|
3666
|
+
return methods.sort((a, b) => {
|
|
3667
|
+
return a.name.localeCompare(b.name);
|
|
3668
|
+
});
|
|
3669
|
+
}
|
|
3670
|
+
};
|
|
3671
|
+
exports2.EncryptionManager = EncryptionManager;
|
|
3672
|
+
}
|
|
3673
|
+
});
|
|
3674
|
+
|
|
3675
|
+
// neozipkit/dist/core/version.js
|
|
3676
|
+
var require_version = __commonJS({
|
|
3677
|
+
"neozipkit/dist/core/version.js"(exports2) {
|
|
3678
|
+
"use strict";
|
|
3679
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3680
|
+
exports2.VERSION = void 0;
|
|
3681
|
+
var currentDate = /* @__PURE__ */ new Date();
|
|
3682
|
+
var releaseDate = `${String(currentDate.getMonth() + 1).padStart(2, "0")}-${String(currentDate.getDate()).padStart(2, "0")}-${currentDate.getFullYear()}`;
|
|
3683
|
+
exports2.VERSION = {
|
|
3684
|
+
number: "0.3.0",
|
|
3685
|
+
// packageJson.version,
|
|
3686
|
+
date: releaseDate
|
|
3687
|
+
};
|
|
3688
|
+
}
|
|
3689
|
+
});
|
|
3690
|
+
|
|
3691
|
+
// neozipkit/dist/core/index.js
|
|
3692
|
+
var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
|
|
3693
|
+
if (k2 === void 0)
|
|
3694
|
+
k2 = k;
|
|
3695
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
3696
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
3697
|
+
desc = { enumerable: true, get: function() {
|
|
3698
|
+
return m[k];
|
|
3699
|
+
} };
|
|
3700
|
+
}
|
|
3701
|
+
Object.defineProperty(o, k2, desc);
|
|
3702
|
+
} : function(o, m, k, k2) {
|
|
3703
|
+
if (k2 === void 0)
|
|
3704
|
+
k2 = k;
|
|
3705
|
+
o[k2] = m[k];
|
|
3706
|
+
});
|
|
3707
|
+
var __exportStar = exports && exports.__exportStar || function(m, exports2) {
|
|
3708
|
+
for (var p in m)
|
|
3709
|
+
if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p))
|
|
3710
|
+
__createBinding(exports2, m, p);
|
|
3711
|
+
};
|
|
3712
|
+
var __importDefault = exports && exports.__importDefault || function(mod) {
|
|
3713
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
3714
|
+
};
|
|
3715
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3716
|
+
exports.configureLoggerFromEnvironment = exports.Logger = exports.sha256 = exports.crc32update = exports.crc32 = exports.ZipCrypto = exports.EncryptionManager = exports.ProgressTracker = exports.HashCalculatorClass = exports.HashCalculator = exports.ZipCompress = void 0;
|
|
3717
|
+
var Zipkit_1 = __importDefault(require_Zipkit());
|
|
3718
|
+
__exportStar(require_Zipkit(), exports);
|
|
3719
|
+
__exportStar(require_ZipEntry(), exports);
|
|
3720
|
+
var ZipCompress_1 = require_ZipCompress();
|
|
3721
|
+
Object.defineProperty(exports, "ZipCompress", { enumerable: true, get: function() {
|
|
3722
|
+
return ZipCompress_1.ZipCompress;
|
|
3723
|
+
} });
|
|
3724
|
+
exports.default = Zipkit_1.default;
|
|
3725
|
+
var HashCalculator_1 = require_HashCalculator();
|
|
3726
|
+
Object.defineProperty(exports, "HashCalculator", { enumerable: true, get: function() {
|
|
3727
|
+
return __importDefault(HashCalculator_1).default;
|
|
3728
|
+
} });
|
|
3729
|
+
Object.defineProperty(exports, "HashCalculatorClass", { enumerable: true, get: function() {
|
|
3730
|
+
return HashCalculator_1.HashCalculator;
|
|
3731
|
+
} });
|
|
3732
|
+
__exportStar(require_Util(), exports);
|
|
3733
|
+
__exportStar(require_Support(), exports);
|
|
3734
|
+
var ProgressTracker_1 = require_ProgressTracker();
|
|
3735
|
+
Object.defineProperty(exports, "ProgressTracker", { enumerable: true, get: function() {
|
|
3736
|
+
return ProgressTracker_1.ProgressTracker;
|
|
3737
|
+
} });
|
|
3738
|
+
var Manager_1 = require_Manager();
|
|
3739
|
+
Object.defineProperty(exports, "EncryptionManager", { enumerable: true, get: function() {
|
|
3740
|
+
return Manager_1.EncryptionManager;
|
|
3741
|
+
} });
|
|
3742
|
+
var ZipCrypto_1 = require_ZipCrypto();
|
|
3743
|
+
Object.defineProperty(exports, "ZipCrypto", { enumerable: true, get: function() {
|
|
3744
|
+
return ZipCrypto_1.ZipCrypto;
|
|
3745
|
+
} });
|
|
3746
|
+
Object.defineProperty(exports, "crc32", { enumerable: true, get: function() {
|
|
3747
|
+
return ZipCrypto_1.crc32;
|
|
3748
|
+
} });
|
|
3749
|
+
Object.defineProperty(exports, "crc32update", { enumerable: true, get: function() {
|
|
3750
|
+
return ZipCrypto_1.crc32update;
|
|
3751
|
+
} });
|
|
3752
|
+
Object.defineProperty(exports, "sha256", { enumerable: true, get: function() {
|
|
3753
|
+
return ZipCrypto_1.sha256;
|
|
3754
|
+
} });
|
|
3755
|
+
__exportStar(require_types2(), exports);
|
|
3756
|
+
__exportStar(require_Headers(), exports);
|
|
3757
|
+
__exportStar(require_Errors(), exports);
|
|
3758
|
+
__exportStar(require_version(), exports);
|
|
3759
|
+
var Logger_1 = require_Logger();
|
|
3760
|
+
Object.defineProperty(exports, "Logger", { enumerable: true, get: function() {
|
|
3761
|
+
return Logger_1.Logger;
|
|
3762
|
+
} });
|
|
3763
|
+
Object.defineProperty(exports, "configureLoggerFromEnvironment", { enumerable: true, get: function() {
|
|
3764
|
+
return Logger_1.configureLoggerFromEnvironment;
|
|
3765
|
+
} });
|
|
3766
|
+
//# sourceMappingURL=core.js.map
|