appium-ios-remotexpc 2.2.4 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/build/src/index.d.ts +1 -0
  3. package/build/src/index.d.ts.map +1 -1
  4. package/build/src/index.js.map +1 -1
  5. package/build/src/services/ios/afc/codec.d.ts +5 -0
  6. package/build/src/services/ios/afc/codec.d.ts.map +1 -1
  7. package/build/src/services/ios/afc/codec.js +10 -0
  8. package/build/src/services/ios/afc/codec.js.map +1 -1
  9. package/build/src/services/ios/installation-proxy/index.d.ts.map +1 -1
  10. package/build/src/services/ios/installation-proxy/index.js +1 -24
  11. package/build/src/services/ios/installation-proxy/index.js.map +1 -1
  12. package/build/src/services/ios/zipconduit/constants.d.ts +20 -0
  13. package/build/src/services/ios/zipconduit/constants.d.ts.map +1 -0
  14. package/build/src/services/ios/zipconduit/constants.js +20 -0
  15. package/build/src/services/ios/zipconduit/constants.js.map +1 -0
  16. package/build/src/services/ios/zipconduit/index.d.ts +38 -0
  17. package/build/src/services/ios/zipconduit/index.d.ts.map +1 -0
  18. package/build/src/services/ios/zipconduit/index.js +148 -0
  19. package/build/src/services/ios/zipconduit/index.js.map +1 -0
  20. package/build/src/services/ios/zipconduit/plists.d.ts +46 -0
  21. package/build/src/services/ios/zipconduit/plists.d.ts.map +1 -0
  22. package/build/src/services/ios/zipconduit/plists.js +87 -0
  23. package/build/src/services/ios/zipconduit/plists.js.map +1 -0
  24. package/build/src/services/ios/zipconduit/stream-zip.d.ts +105 -0
  25. package/build/src/services/ios/zipconduit/stream-zip.d.ts.map +1 -0
  26. package/build/src/services/ios/zipconduit/stream-zip.js +883 -0
  27. package/build/src/services/ios/zipconduit/stream-zip.js.map +1 -0
  28. package/build/src/services/ios/zipconduit/zip-reader.d.ts +15 -0
  29. package/build/src/services/ios/zipconduit/zip-reader.d.ts.map +1 -0
  30. package/build/src/services/ios/zipconduit/zip-reader.js +33 -0
  31. package/build/src/services/ios/zipconduit/zip-reader.js.map +1 -0
  32. package/build/src/services/ios/zipconduit/zip-utils.d.ts +27 -0
  33. package/build/src/services/ios/zipconduit/zip-utils.d.ts.map +1 -0
  34. package/build/src/services/ios/zipconduit/zip-utils.js +116 -0
  35. package/build/src/services/ios/zipconduit/zip-utils.js.map +1 -0
  36. package/build/src/services.d.ts +6 -0
  37. package/build/src/services.d.ts.map +1 -1
  38. package/build/src/services.js +14 -0
  39. package/build/src/services.js.map +1 -1
  40. package/package.json +2 -1
  41. package/src/index.ts +6 -0
  42. package/src/services/ios/afc/codec.ts +15 -0
  43. package/src/services/ios/installation-proxy/index.ts +1 -42
  44. package/src/services/ios/zipconduit/constants.ts +30 -0
  45. package/src/services/ios/zipconduit/index.ts +242 -0
  46. package/src/services/ios/zipconduit/plists.ts +139 -0
  47. package/src/services/ios/zipconduit/stream-zip.ts +1082 -0
  48. package/src/services/ios/zipconduit/zip-reader.ts +48 -0
  49. package/src/services/ios/zipconduit/zip-utils.ts +185 -0
  50. package/src/services.ts +19 -0
@@ -0,0 +1,883 @@
1
+ /**
2
+ * @license node-stream-zip | (c) 2020 Antelle | https://github.com/antelle/node-stream-zip/blob/master/LICENSE
3
+ * Portions copyright https://github.com/cthackers/adm-zip | https://raw.githubusercontent.com/cthackers/adm-zip/master/LICENSE
4
+ *
5
+ * Vendored from node-stream-zip@1.15.0, trimmed to the archive-reading paths
6
+ * used by ZipConduit (central-directory listing + streaming entry reads).
7
+ * Removed unused features: extract-to-disk, synchronous entry data, setFs,
8
+ * and the async helpers entriesCount/comment/entry/entryData/extract.
9
+ */
10
+ import { EventEmitter } from 'node:events';
11
+ import fs from 'node:fs';
12
+ import stream from 'node:stream';
13
+ import zlib from 'node:zlib';
14
+ const ZIP = {
15
+ LOCHDR: 30,
16
+ LOCSIG: 0x04034b50,
17
+ LOCVER: 4,
18
+ LOCFLG: 6,
19
+ LOCHOW: 8,
20
+ LOCTIM: 10,
21
+ LOCCRC: 14,
22
+ LOCSIZ: 18,
23
+ LOCLEN: 22,
24
+ LOCNAM: 26,
25
+ LOCEXT: 28,
26
+ CENHDR: 46,
27
+ CENSIG: 0x02014b50,
28
+ CENVEM: 4,
29
+ CENVER: 6,
30
+ CENFLG: 8,
31
+ CENHOW: 10,
32
+ CENTIM: 12,
33
+ CENCRC: 16,
34
+ CENSIZ: 20,
35
+ CENLEN: 24,
36
+ CENNAM: 28,
37
+ CENEXT: 30,
38
+ CENCOM: 32,
39
+ CENDSK: 34,
40
+ CENATT: 36,
41
+ CENATX: 38,
42
+ CENOFF: 42,
43
+ ENDHDR: 22,
44
+ ENDSIG: 0x06054b50,
45
+ ENDSIGFIRST: 0x50,
46
+ ENDSUB: 8,
47
+ ENDTOT: 10,
48
+ ENDSIZ: 12,
49
+ ENDOFF: 16,
50
+ ENDCOM: 20,
51
+ MAXFILECOMMENT: 0xffff,
52
+ ENDL64HDR: 20,
53
+ ENDL64SIG: 0x07064b50,
54
+ ENDL64SIGFIRST: 0x50,
55
+ END64HDR: 56,
56
+ END64SIG: 0x06064b50,
57
+ END64SIGFIRST: 0x50,
58
+ END64SUB: 24,
59
+ END64TOT: 32,
60
+ END64SIZ: 40,
61
+ END64OFF: 48,
62
+ STORED: 0,
63
+ DEFLATED: 8,
64
+ FLG_ENTRY_ENC: 1,
65
+ ID_ZIP64: 0x0001,
66
+ EF_ZIP64_OR_32: 0xffffffff,
67
+ EF_ZIP64_OR_16: 0xffff,
68
+ };
69
+ class CentralDirectoryHeader {
70
+ volumeEntries = 0;
71
+ totalEntries = 0;
72
+ size = 0;
73
+ offset = 0;
74
+ commentLength = 0;
75
+ headerOffset = 0;
76
+ read(data) {
77
+ if (data.length !== ZIP.ENDHDR || data.readUInt32LE(0) !== ZIP.ENDSIG) {
78
+ throw new Error('Invalid central directory');
79
+ }
80
+ this.volumeEntries = data.readUInt16LE(ZIP.ENDSUB);
81
+ this.totalEntries = data.readUInt16LE(ZIP.ENDTOT);
82
+ this.size = data.readUInt32LE(ZIP.ENDSIZ);
83
+ this.offset = data.readUInt32LE(ZIP.ENDOFF);
84
+ this.commentLength = data.readUInt16LE(ZIP.ENDCOM);
85
+ }
86
+ }
87
+ class CentralDirectoryLoc64Header {
88
+ headerOffset = 0;
89
+ read(data) {
90
+ if (data.length !== ZIP.ENDL64HDR ||
91
+ data.readUInt32LE(0) !== ZIP.ENDL64SIG) {
92
+ throw new Error('Invalid zip64 central directory locator');
93
+ }
94
+ this.headerOffset = readUInt64LE(data, ZIP.ENDSUB);
95
+ }
96
+ }
97
+ class CentralDirectoryZip64Header {
98
+ volumeEntries = 0;
99
+ totalEntries = 0;
100
+ size = 0;
101
+ offset = 0;
102
+ read(data) {
103
+ if (data.length !== ZIP.END64HDR || data.readUInt32LE(0) !== ZIP.END64SIG) {
104
+ throw new Error('Invalid central directory');
105
+ }
106
+ this.volumeEntries = readUInt64LE(data, ZIP.END64SUB);
107
+ this.totalEntries = readUInt64LE(data, ZIP.END64TOT);
108
+ this.size = readUInt64LE(data, ZIP.END64SIZ);
109
+ this.offset = readUInt64LE(data, ZIP.END64OFF);
110
+ }
111
+ }
112
+ class FsRead {
113
+ fd;
114
+ buffer;
115
+ offset;
116
+ length;
117
+ position;
118
+ callback;
119
+ bytesRead = 0;
120
+ waiting = false;
121
+ constructor(fd, buffer, offset, length, position, callback) {
122
+ this.fd = fd;
123
+ this.buffer = buffer;
124
+ this.offset = offset;
125
+ this.length = length;
126
+ this.position = position;
127
+ this.callback = callback;
128
+ }
129
+ read(sync = false) {
130
+ this.waiting = true;
131
+ if (sync) {
132
+ let err;
133
+ let bytesRead = 0;
134
+ try {
135
+ bytesRead = fs.readSync(this.fd, this.buffer, this.offset + this.bytesRead, this.length - this.bytesRead, this.position + this.bytesRead);
136
+ }
137
+ catch (e) {
138
+ err = e;
139
+ }
140
+ this.readCallback(sync, err ?? null, err ? bytesRead : null);
141
+ }
142
+ else {
143
+ fs.read(this.fd, this.buffer, this.offset + this.bytesRead, this.length - this.bytesRead, this.position + this.bytesRead, (err, bytesRead) => this.readCallback(sync, err, bytesRead));
144
+ }
145
+ return this;
146
+ }
147
+ readCallback(sync, err, bytesRead) {
148
+ if (typeof bytesRead === 'number') {
149
+ this.bytesRead += bytesRead;
150
+ }
151
+ if (err || !bytesRead || this.bytesRead === this.length) {
152
+ this.waiting = false;
153
+ this.callback(err, this.bytesRead);
154
+ return;
155
+ }
156
+ this.read(sync);
157
+ }
158
+ }
159
+ class FileWindowBuffer {
160
+ fd;
161
+ position = 0;
162
+ buffer = Buffer.alloc(0);
163
+ fsOp = null;
164
+ constructor(fd) {
165
+ this.fd = fd;
166
+ }
167
+ read(pos, length, callback) {
168
+ this.checkOp();
169
+ if (this.buffer.length < length) {
170
+ this.buffer = Buffer.alloc(length);
171
+ }
172
+ this.position = pos;
173
+ this.fsOp = new FsRead(this.fd, this.buffer, 0, length, this.position, callback);
174
+ this.fsOp.read();
175
+ }
176
+ expandLeft(length, callback) {
177
+ this.checkOp();
178
+ this.buffer = Buffer.concat([Buffer.alloc(length), this.buffer]);
179
+ this.position -= length;
180
+ if (this.position < 0) {
181
+ this.position = 0;
182
+ }
183
+ this.fsOp = new FsRead(this.fd, this.buffer, 0, length, this.position, callback);
184
+ this.fsOp.read();
185
+ }
186
+ expandRight(length, callback) {
187
+ this.checkOp();
188
+ const offset = this.buffer.length;
189
+ this.buffer = Buffer.concat([this.buffer, Buffer.alloc(length)]);
190
+ this.fsOp = new FsRead(this.fd, this.buffer, offset, length, this.position + offset, callback);
191
+ this.fsOp.read();
192
+ }
193
+ moveRight(length, callback, shift = 0) {
194
+ this.checkOp();
195
+ if (shift) {
196
+ this.buffer.copy(this.buffer, 0, shift);
197
+ }
198
+ this.position += shift;
199
+ this.fsOp = new FsRead(this.fd, this.buffer, this.buffer.length - shift, shift, this.position + this.buffer.length - shift, callback);
200
+ this.fsOp.read();
201
+ }
202
+ checkOp() {
203
+ if (this.fsOp?.waiting) {
204
+ throw new Error('Operation in progress');
205
+ }
206
+ }
207
+ }
208
+ class EntryDataReaderStream extends stream.Readable {
209
+ fd;
210
+ dataOffset;
211
+ length;
212
+ readChunkSize;
213
+ pos = 0;
214
+ constructor(fd, dataOffset, length, readChunkSize) {
215
+ super({ highWaterMark: readChunkSize });
216
+ this.fd = fd;
217
+ this.dataOffset = dataOffset;
218
+ this.length = length;
219
+ this.readChunkSize = readChunkSize;
220
+ }
221
+ _read() {
222
+ const toRead = Math.min(this.readChunkSize, this.length - this.pos);
223
+ const buffer = Buffer.allocUnsafe(toRead);
224
+ if (buffer.length) {
225
+ fs.read(this.fd, buffer, 0, buffer.length, this.dataOffset + this.pos, (err, bytesRead) => this.onRead(err, bytesRead, buffer));
226
+ }
227
+ else {
228
+ this.push(null);
229
+ }
230
+ }
231
+ onRead(err, bytesRead, buffer) {
232
+ this.pos += bytesRead;
233
+ if (err) {
234
+ this.emit('error', err);
235
+ this.push(null);
236
+ return;
237
+ }
238
+ if (!bytesRead) {
239
+ this.push(null);
240
+ return;
241
+ }
242
+ this.push(bytesRead === buffer.length ? buffer : buffer.subarray(0, bytesRead));
243
+ }
244
+ }
245
+ class CrcVerify {
246
+ expectedCrc;
247
+ expectedSize;
248
+ static crcTable;
249
+ state = { crc: ~0, size: 0 };
250
+ constructor(expectedCrc, expectedSize) {
251
+ this.expectedCrc = expectedCrc;
252
+ this.expectedSize = expectedSize;
253
+ }
254
+ data(data) {
255
+ const crcTable = CrcVerify.getCrcTable();
256
+ let crc = this.state.crc;
257
+ let off = 0;
258
+ let len = data.length;
259
+ while (--len >= 0) {
260
+ crc = crcTable[(crc ^ data[off++]) & 0xff] ^ (crc >>> 8);
261
+ }
262
+ this.state.crc = crc;
263
+ this.state.size += data.length;
264
+ if (this.state.size >= this.expectedSize) {
265
+ const buf = Buffer.alloc(4);
266
+ buf.writeInt32LE(~this.state.crc & 0xffffffff, 0);
267
+ crc = buf.readUInt32LE(0);
268
+ if (crc !== this.expectedCrc) {
269
+ throw new Error('Invalid CRC');
270
+ }
271
+ if (this.state.size !== this.expectedSize) {
272
+ throw new Error('Invalid size');
273
+ }
274
+ }
275
+ }
276
+ static getCrcTable() {
277
+ if (CrcVerify.crcTable) {
278
+ return CrcVerify.crcTable;
279
+ }
280
+ const crcTable = [];
281
+ const b = Buffer.alloc(4);
282
+ for (let n = 0; n < 256; n++) {
283
+ let c = n;
284
+ for (let k = 7; k >= 0; k--) {
285
+ c = (c & 1) !== 0 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
286
+ }
287
+ if (c < 0) {
288
+ b.writeInt32LE(c, 0);
289
+ c = b.readUInt32LE(0);
290
+ }
291
+ crcTable[n] = c;
292
+ }
293
+ CrcVerify.crcTable = crcTable;
294
+ return crcTable;
295
+ }
296
+ }
297
+ class EntryVerifyStream extends stream.Transform {
298
+ verify;
299
+ constructor(baseStm, crc, size) {
300
+ super();
301
+ this.verify = new CrcVerify(crc, size);
302
+ baseStm.on('error', (e) => this.emit('error', e));
303
+ }
304
+ _transform(data, _encoding, callback) {
305
+ let err;
306
+ try {
307
+ this.verify.data(data);
308
+ }
309
+ catch (e) {
310
+ err = e;
311
+ }
312
+ callback(err, data);
313
+ }
314
+ }
315
+ /** ZIP central-directory entry (also returned from {@link StreamZip.entries}). */
316
+ export class ZipEntry {
317
+ verMade = 0;
318
+ version = 0;
319
+ flags = 0;
320
+ method = 0;
321
+ time = 0;
322
+ crc = 0;
323
+ compressedSize = 0;
324
+ size = 0;
325
+ fnameLen = 0;
326
+ extraLen = 0;
327
+ comLen = 0;
328
+ diskStart = 0;
329
+ inattr = 0;
330
+ attr = 0;
331
+ offset = 0;
332
+ headerOffset = 0;
333
+ name = '';
334
+ isDirectory = false;
335
+ comment = null;
336
+ readHeader(data, offset) {
337
+ if (data.length < offset + ZIP.CENHDR ||
338
+ data.readUInt32LE(offset) !== ZIP.CENSIG) {
339
+ throw new Error('Invalid entry header');
340
+ }
341
+ this.verMade = data.readUInt16LE(offset + ZIP.CENVEM);
342
+ this.version = data.readUInt16LE(offset + ZIP.CENVER);
343
+ this.flags = data.readUInt16LE(offset + ZIP.CENFLG);
344
+ this.method = data.readUInt16LE(offset + ZIP.CENHOW);
345
+ const timebytes = data.readUInt16LE(offset + ZIP.CENTIM);
346
+ const datebytes = data.readUInt16LE(offset + ZIP.CENTIM + 2);
347
+ this.time = parseZipTime(timebytes, datebytes);
348
+ this.crc = data.readUInt32LE(offset + ZIP.CENCRC);
349
+ this.compressedSize = data.readUInt32LE(offset + ZIP.CENSIZ);
350
+ this.size = data.readUInt32LE(offset + ZIP.CENLEN);
351
+ this.fnameLen = data.readUInt16LE(offset + ZIP.CENNAM);
352
+ this.extraLen = data.readUInt16LE(offset + ZIP.CENEXT);
353
+ this.comLen = data.readUInt16LE(offset + ZIP.CENCOM);
354
+ this.diskStart = data.readUInt16LE(offset + ZIP.CENDSK);
355
+ this.inattr = data.readUInt16LE(offset + ZIP.CENATT);
356
+ this.attr = data.readUInt32LE(offset + ZIP.CENATX);
357
+ this.offset = data.readUInt32LE(offset + ZIP.CENOFF);
358
+ }
359
+ readDataHeader(data) {
360
+ if (data.readUInt32LE(0) !== ZIP.LOCSIG) {
361
+ throw new Error('Invalid local header');
362
+ }
363
+ this.version = data.readUInt16LE(ZIP.LOCVER);
364
+ this.flags = data.readUInt16LE(ZIP.LOCFLG);
365
+ this.method = data.readUInt16LE(ZIP.LOCHOW);
366
+ const timebytes = data.readUInt16LE(ZIP.LOCTIM);
367
+ const datebytes = data.readUInt16LE(ZIP.LOCTIM + 2);
368
+ this.time = parseZipTime(timebytes, datebytes);
369
+ this.crc = data.readUInt32LE(ZIP.LOCCRC) || this.crc;
370
+ const compressedSize = data.readUInt32LE(ZIP.LOCSIZ);
371
+ if (compressedSize && compressedSize !== ZIP.EF_ZIP64_OR_32) {
372
+ this.compressedSize = compressedSize;
373
+ }
374
+ const size = data.readUInt32LE(ZIP.LOCLEN);
375
+ if (size && size !== ZIP.EF_ZIP64_OR_32) {
376
+ this.size = size;
377
+ }
378
+ this.fnameLen = data.readUInt16LE(ZIP.LOCNAM);
379
+ this.extraLen = data.readUInt16LE(ZIP.LOCEXT);
380
+ }
381
+ read(data, offset, textDecoder) {
382
+ const nameData = data.slice(offset, (offset += this.fnameLen));
383
+ this.name = textDecoder
384
+ ? textDecoder.decode(new Uint8Array(nameData))
385
+ : nameData.toString('utf8');
386
+ const lastChar = data[offset - 1];
387
+ this.isDirectory = lastChar === 47 || lastChar === 92;
388
+ if (this.extraLen) {
389
+ this.readExtra(data, offset);
390
+ offset += this.extraLen;
391
+ }
392
+ this.comment = this.comLen
393
+ ? data.slice(offset, offset + this.comLen).toString()
394
+ : null;
395
+ }
396
+ validateName() {
397
+ if (/\\|^\w+:|^\/|(^|\/)\.\.(\/|$)/.test(this.name)) {
398
+ throw new Error(`Malicious entry: ${this.name}`);
399
+ }
400
+ }
401
+ readExtra(data, offset) {
402
+ const maxPos = offset + this.extraLen;
403
+ while (offset < maxPos) {
404
+ const signature = data.readUInt16LE(offset);
405
+ offset += 2;
406
+ const size = data.readUInt16LE(offset);
407
+ offset += 2;
408
+ if (ZIP.ID_ZIP64 === signature) {
409
+ this.parseZip64Extra(data, offset, size);
410
+ }
411
+ offset += size;
412
+ }
413
+ }
414
+ parseZip64Extra(data, offset, length) {
415
+ if (length >= 8 && this.size === ZIP.EF_ZIP64_OR_32) {
416
+ this.size = readUInt64LE(data, offset);
417
+ offset += 8;
418
+ length -= 8;
419
+ }
420
+ if (length >= 8 && this.compressedSize === ZIP.EF_ZIP64_OR_32) {
421
+ this.compressedSize = readUInt64LE(data, offset);
422
+ offset += 8;
423
+ length -= 8;
424
+ }
425
+ if (length >= 8 && this.offset === ZIP.EF_ZIP64_OR_32) {
426
+ this.offset = readUInt64LE(data, offset);
427
+ offset += 8;
428
+ length -= 8;
429
+ }
430
+ if (length >= 4 && this.diskStart === ZIP.EF_ZIP64_OR_16) {
431
+ this.diskStart = data.readUInt32LE(offset);
432
+ }
433
+ }
434
+ get encrypted() {
435
+ return (this.flags & ZIP.FLG_ENTRY_ENC) === ZIP.FLG_ENTRY_ENC;
436
+ }
437
+ get isFile() {
438
+ return !this.isDirectory;
439
+ }
440
+ }
441
+ /** Streaming ZIP reader with promise-based entry access. */
442
+ export class StreamZip extends EventEmitter {
443
+ config;
444
+ entriesCount = 0;
445
+ comment = null;
446
+ centralDirectory;
447
+ fd = null;
448
+ fileSize = 0;
449
+ chunkSize = 0;
450
+ closed = false;
451
+ signatureOp = null;
452
+ entriesOp = null;
453
+ entryMap;
454
+ textDecoder;
455
+ readyPromise;
456
+ constructor(config) {
457
+ super();
458
+ this.config = config;
459
+ this.entryMap = config.storeEntries !== false ? {} : null;
460
+ this.textDecoder = config.nameEncoding
461
+ ? new TextDecoder(config.nameEncoding)
462
+ : null;
463
+ this.readyPromise = new Promise((resolve, reject) => {
464
+ this.once('ready', () => {
465
+ this.removeListener('error', reject);
466
+ resolve();
467
+ });
468
+ this.once('error', reject);
469
+ });
470
+ this.open();
471
+ }
472
+ /** Resolves when the central directory has been parsed. */
473
+ async waitUntilReady() {
474
+ await this.readyPromise;
475
+ }
476
+ async entries() {
477
+ await this.readyPromise;
478
+ const entryMap = this.entryMap;
479
+ if (!entryMap) {
480
+ throw new Error('storeEntries disabled');
481
+ }
482
+ return entryMap;
483
+ }
484
+ async stream(entry) {
485
+ await this.readyPromise;
486
+ const resolvedEntry = await this.resolveFileEntry(entry);
487
+ const openedEntry = this.config.skipLocalHeaderRead === true &&
488
+ resolvedEntry.method === ZIP.STORED
489
+ ? resolvedEntry
490
+ : await this.openEntry(resolvedEntry);
491
+ if (openedEntry.encrypted) {
492
+ throw new Error('Entry encrypted');
493
+ }
494
+ const offset = this.dataOffset(openedEntry);
495
+ if (this.fd === null) {
496
+ throw new Error('Archive closed');
497
+ }
498
+ let entryStream = new EntryDataReaderStream(this.fd, offset, openedEntry.compressedSize, this.chunkSize || 1024 * 1024);
499
+ if (openedEntry.method === ZIP.STORED) {
500
+ // stored — pass through
501
+ }
502
+ else if (openedEntry.method === ZIP.DEFLATED) {
503
+ entryStream = entryStream.pipe(zlib.createInflateRaw());
504
+ }
505
+ else {
506
+ throw new Error(`Unknown compression method: ${openedEntry.method}`);
507
+ }
508
+ if (this.config.verifyEntryCrc !== false &&
509
+ this.canVerifyCrc(openedEntry)) {
510
+ entryStream = entryStream.pipe(new EntryVerifyStream(entryStream, openedEntry.crc, openedEntry.size));
511
+ }
512
+ return entryStream;
513
+ }
514
+ async openEntry(entry) {
515
+ await this.readyPromise;
516
+ let resolvedEntry;
517
+ if (typeof entry === 'string') {
518
+ const entryMap = this.entryMap;
519
+ if (!entryMap) {
520
+ throw new Error('storeEntries disabled');
521
+ }
522
+ resolvedEntry = entryMap[entry];
523
+ if (!resolvedEntry) {
524
+ throw new Error('Entry not found');
525
+ }
526
+ }
527
+ else {
528
+ resolvedEntry = entry;
529
+ }
530
+ if (!resolvedEntry.isFile) {
531
+ throw new Error('Entry is not file');
532
+ }
533
+ const fd = this.fd;
534
+ if (fd === null) {
535
+ throw new Error('Archive closed');
536
+ }
537
+ const entryOffset = resolvedEntry.offset;
538
+ const buffer = Buffer.alloc(ZIP.LOCHDR);
539
+ await new Promise((resolve, reject) => {
540
+ new FsRead(fd, buffer, 0, buffer.length, entryOffset, (err) => {
541
+ if (err) {
542
+ reject(err);
543
+ return;
544
+ }
545
+ resolve();
546
+ }).read();
547
+ });
548
+ resolvedEntry.readDataHeader(buffer);
549
+ if (resolvedEntry.encrypted) {
550
+ throw new Error('Entry encrypted');
551
+ }
552
+ return resolvedEntry;
553
+ }
554
+ async close() {
555
+ if (this.closed || this.fd === null) {
556
+ this.closed = true;
557
+ return;
558
+ }
559
+ this.closed = true;
560
+ const fd = this.fd;
561
+ this.fd = null;
562
+ await new Promise((resolve, reject) => {
563
+ fs.close(fd, (err) => (err ? reject(err) : resolve()));
564
+ });
565
+ }
566
+ emit(event, ...args) {
567
+ if (this.closed) {
568
+ return false;
569
+ }
570
+ return super.emit(event, ...args);
571
+ }
572
+ async resolveFileEntry(entry) {
573
+ if (typeof entry === 'string') {
574
+ const entryMap = this.entryMap;
575
+ if (!entryMap) {
576
+ throw new Error('storeEntries disabled');
577
+ }
578
+ const resolvedEntry = entryMap[entry];
579
+ if (!resolvedEntry) {
580
+ throw new Error('Entry not found');
581
+ }
582
+ if (!resolvedEntry.isFile) {
583
+ throw new Error('Entry is not file');
584
+ }
585
+ return resolvedEntry;
586
+ }
587
+ if (!entry.isFile) {
588
+ throw new Error('Entry is not file');
589
+ }
590
+ return entry;
591
+ }
592
+ open() {
593
+ if (this.config.fd !== undefined) {
594
+ this.fd = this.config.fd;
595
+ this.readFile();
596
+ return;
597
+ }
598
+ const filePath = this.config.file;
599
+ if (!filePath) {
600
+ this.emit('error', new Error('ZIP file path is required'));
601
+ return;
602
+ }
603
+ fs.open(filePath, 'r', (err, f) => {
604
+ if (err) {
605
+ this.emit('error', err);
606
+ return;
607
+ }
608
+ this.fd = f;
609
+ this.readFile();
610
+ });
611
+ }
612
+ readFile() {
613
+ if (this.fd === null) {
614
+ return;
615
+ }
616
+ fs.fstat(this.fd, (err, stat) => {
617
+ if (err) {
618
+ this.emit('error', err);
619
+ return;
620
+ }
621
+ this.fileSize = stat.size;
622
+ let chunk = this.config.chunkSize ?? Math.round(this.fileSize / 1000);
623
+ chunk = Math.max(Math.min(chunk, Math.min(128 * 1024, this.fileSize)), Math.min(1024, this.fileSize));
624
+ this.chunkSize = chunk;
625
+ this.readCentralDirectory();
626
+ });
627
+ }
628
+ readUntilFoundCallback = (err, bytesRead) => {
629
+ const op = this.signatureOp;
630
+ if (!op) {
631
+ return;
632
+ }
633
+ if (err || !bytesRead) {
634
+ this.emit('error', err ?? new Error('Archive read error'));
635
+ return;
636
+ }
637
+ let pos = op.lastPos;
638
+ let bufferPosition = pos - op.win.position;
639
+ const buffer = op.win.buffer;
640
+ const minPos = op.minPos;
641
+ while (--pos >= minPos && --bufferPosition >= 0) {
642
+ if (buffer.length - bufferPosition >= 4 &&
643
+ buffer[bufferPosition] === op.firstByte) {
644
+ if (buffer.readUInt32LE(bufferPosition) === op.sig) {
645
+ op.lastBufferPosition = bufferPosition;
646
+ op.lastBytesRead = bytesRead;
647
+ op.complete();
648
+ return;
649
+ }
650
+ }
651
+ }
652
+ if (pos === minPos) {
653
+ this.emit('error', new Error('Bad archive'));
654
+ return;
655
+ }
656
+ op.lastPos = pos + 1;
657
+ op.chunkSize *= 2;
658
+ if (pos <= minPos) {
659
+ this.emit('error', new Error('Bad archive'));
660
+ return;
661
+ }
662
+ const expandLength = Math.min(op.chunkSize, pos - minPos);
663
+ op.win.expandLeft(expandLength, this.readUntilFoundCallback);
664
+ };
665
+ readCentralDirectory() {
666
+ if (this.fd === null) {
667
+ return;
668
+ }
669
+ const totalReadLength = Math.min(ZIP.ENDHDR + ZIP.MAXFILECOMMENT, this.fileSize);
670
+ this.signatureOp = {
671
+ win: new FileWindowBuffer(this.fd),
672
+ totalReadLength,
673
+ minPos: this.fileSize - totalReadLength,
674
+ lastPos: this.fileSize,
675
+ chunkSize: Math.min(1024, this.chunkSize),
676
+ firstByte: ZIP.ENDSIGFIRST,
677
+ sig: ZIP.ENDSIG,
678
+ lastBufferPosition: 0,
679
+ lastBytesRead: 0,
680
+ complete: () => this.readCentralDirectoryComplete(),
681
+ };
682
+ const op = this.signatureOp;
683
+ op.win.read(this.fileSize - op.chunkSize, op.chunkSize, this.readUntilFoundCallback);
684
+ }
685
+ readCentralDirectoryComplete() {
686
+ const op = this.signatureOp;
687
+ if (!op) {
688
+ return;
689
+ }
690
+ const buffer = op.win.buffer;
691
+ const pos = op.lastBufferPosition;
692
+ try {
693
+ const centralDirectory = new CentralDirectoryHeader();
694
+ centralDirectory.read(buffer.subarray(pos, pos + ZIP.ENDHDR));
695
+ centralDirectory.headerOffset = op.win.position + pos;
696
+ if (centralDirectory.commentLength) {
697
+ this.comment = buffer
698
+ .subarray(pos + ZIP.ENDHDR, pos + ZIP.ENDHDR + centralDirectory.commentLength)
699
+ .toString();
700
+ }
701
+ else {
702
+ this.comment = null;
703
+ }
704
+ this.entriesCount = centralDirectory.volumeEntries;
705
+ this.centralDirectory = centralDirectory;
706
+ if ((centralDirectory.volumeEntries === ZIP.EF_ZIP64_OR_16 &&
707
+ centralDirectory.totalEntries === ZIP.EF_ZIP64_OR_16) ||
708
+ centralDirectory.size === ZIP.EF_ZIP64_OR_32 ||
709
+ centralDirectory.offset === ZIP.EF_ZIP64_OR_32) {
710
+ this.readZip64CentralDirectoryLocator();
711
+ }
712
+ else {
713
+ this.signatureOp = null;
714
+ this.readEntries();
715
+ }
716
+ }
717
+ catch (err) {
718
+ this.emit('error', err);
719
+ }
720
+ }
721
+ readZip64CentralDirectoryLocator() {
722
+ const op = this.signatureOp;
723
+ if (!op) {
724
+ return;
725
+ }
726
+ const length = ZIP.ENDL64HDR;
727
+ if (op.lastBufferPosition > length) {
728
+ op.lastBufferPosition -= length;
729
+ this.readZip64CentralDirectoryLocatorComplete();
730
+ return;
731
+ }
732
+ this.signatureOp = {
733
+ win: op.win,
734
+ totalReadLength: length,
735
+ minPos: op.win.position - length,
736
+ lastPos: op.win.position,
737
+ chunkSize: op.chunkSize,
738
+ firstByte: ZIP.ENDL64SIGFIRST,
739
+ sig: ZIP.ENDL64SIG,
740
+ lastBufferPosition: op.lastBufferPosition,
741
+ lastBytesRead: op.lastBytesRead,
742
+ complete: () => this.readZip64CentralDirectoryLocatorComplete(),
743
+ };
744
+ const next = this.signatureOp;
745
+ next.win.read(next.lastPos - next.chunkSize, next.chunkSize, this.readUntilFoundCallback);
746
+ }
747
+ readZip64CentralDirectoryLocatorComplete() {
748
+ const op = this.signatureOp;
749
+ if (!op) {
750
+ return;
751
+ }
752
+ const buffer = op.win.buffer;
753
+ const locHeader = new CentralDirectoryLoc64Header();
754
+ locHeader.read(buffer.subarray(op.lastBufferPosition, op.lastBufferPosition + ZIP.ENDL64HDR));
755
+ const readLength = this.fileSize - locHeader.headerOffset;
756
+ this.signatureOp = {
757
+ win: op.win,
758
+ totalReadLength: readLength,
759
+ minPos: locHeader.headerOffset,
760
+ lastPos: op.lastPos,
761
+ chunkSize: op.chunkSize,
762
+ firstByte: ZIP.END64SIGFIRST,
763
+ sig: ZIP.END64SIG,
764
+ lastBufferPosition: op.lastBufferPosition,
765
+ lastBytesRead: op.lastBytesRead,
766
+ complete: () => this.readZip64CentralDirectoryComplete(),
767
+ };
768
+ const next = this.signatureOp;
769
+ next.win.read(this.fileSize - next.chunkSize, next.chunkSize, this.readUntilFoundCallback);
770
+ }
771
+ readZip64CentralDirectoryComplete() {
772
+ const op = this.signatureOp;
773
+ if (!op) {
774
+ return;
775
+ }
776
+ const buffer = op.win.buffer;
777
+ const zip64cd = new CentralDirectoryZip64Header();
778
+ zip64cd.read(buffer.subarray(op.lastBufferPosition, op.lastBufferPosition + ZIP.END64HDR));
779
+ this.centralDirectory.volumeEntries = zip64cd.volumeEntries;
780
+ this.centralDirectory.totalEntries = zip64cd.totalEntries;
781
+ this.centralDirectory.size = zip64cd.size;
782
+ this.centralDirectory.offset = zip64cd.offset;
783
+ this.entriesCount = zip64cd.volumeEntries;
784
+ this.signatureOp = null;
785
+ this.readEntries();
786
+ }
787
+ readEntries() {
788
+ if (this.fd === null) {
789
+ return;
790
+ }
791
+ this.entriesOp = {
792
+ win: new FileWindowBuffer(this.fd),
793
+ pos: this.centralDirectory.offset,
794
+ chunkSize: this.chunkSize,
795
+ entriesLeft: this.centralDirectory.volumeEntries,
796
+ entry: null,
797
+ };
798
+ const op = this.entriesOp;
799
+ op.win.read(op.pos, Math.min(this.chunkSize, this.fileSize - op.pos), this.readEntriesCallback);
800
+ }
801
+ readEntriesCallback = (err, bytesRead) => {
802
+ const op = this.entriesOp;
803
+ if (!op) {
804
+ return;
805
+ }
806
+ if (err || !bytesRead) {
807
+ this.emit('error', err ?? new Error('Entries read error'));
808
+ return;
809
+ }
810
+ let bufferPos = op.pos - op.win.position;
811
+ let entry = op.entry;
812
+ const buffer = op.win.buffer;
813
+ const bufferLength = buffer.length;
814
+ try {
815
+ while (op.entriesLeft > 0) {
816
+ if (!entry) {
817
+ entry = new ZipEntry();
818
+ entry.readHeader(buffer, bufferPos);
819
+ entry.headerOffset = op.win.position + bufferPos;
820
+ op.entry = entry;
821
+ op.pos += ZIP.CENHDR;
822
+ bufferPos += ZIP.CENHDR;
823
+ }
824
+ const entryHeaderSize = entry.fnameLen + entry.extraLen + entry.comLen;
825
+ const advanceBytes = entryHeaderSize + (op.entriesLeft > 1 ? ZIP.CENHDR : 0);
826
+ if (bufferLength - bufferPos < advanceBytes) {
827
+ op.win.moveRight(this.chunkSize, this.readEntriesCallback, bufferPos);
828
+ op.move = true;
829
+ return;
830
+ }
831
+ entry.read(buffer, bufferPos, this.textDecoder);
832
+ if (!this.config.skipEntryNameValidation) {
833
+ entry.validateName();
834
+ }
835
+ if (this.entryMap) {
836
+ this.entryMap[entry.name] = entry;
837
+ }
838
+ this.emit('entry', entry);
839
+ op.entry = null;
840
+ entry = null;
841
+ op.entriesLeft--;
842
+ op.pos += entryHeaderSize;
843
+ bufferPos += entryHeaderSize;
844
+ }
845
+ this.emit('ready');
846
+ }
847
+ catch (readErr) {
848
+ this.emit('error', readErr);
849
+ }
850
+ };
851
+ dataOffset(entry) {
852
+ return entry.offset + ZIP.LOCHDR + entry.fnameLen + entry.extraLen;
853
+ }
854
+ canVerifyCrc(entry) {
855
+ return (entry.flags & 0x8) !== 0x8;
856
+ }
857
+ }
858
+ function parseZipTime(timebytes, datebytes) {
859
+ const timebits = toBits(timebytes, 16);
860
+ const datebits = toBits(datebytes, 16);
861
+ const mt = {
862
+ h: Number.parseInt(timebits.slice(0, 5).join(''), 2),
863
+ m: Number.parseInt(timebits.slice(5, 11).join(''), 2),
864
+ s: Number.parseInt(timebits.slice(11, 16).join(''), 2) * 2,
865
+ Y: Number.parseInt(datebits.slice(0, 7).join(''), 2) + 1980,
866
+ M: Number.parseInt(datebits.slice(7, 11).join(''), 2),
867
+ D: Number.parseInt(datebits.slice(11, 16).join(''), 2),
868
+ };
869
+ const dtStr = `${[mt.Y, mt.M, mt.D].join('-')} ${[mt.h, mt.m, mt.s].join(':')} GMT+0`;
870
+ return new Date(dtStr).getTime();
871
+ }
872
+ function toBits(dec, size) {
873
+ let b = (dec >>> 0).toString(2);
874
+ while (b.length < size) {
875
+ b = `0${b}`;
876
+ }
877
+ return b.split('');
878
+ }
879
+ function readUInt64LE(buffer, offset) {
880
+ return (buffer.readUInt32LE(offset + 4) * 0x0000000100000000 +
881
+ buffer.readUInt32LE(offset));
882
+ }
883
+ //# sourceMappingURL=stream-zip.js.map