zip.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. /* jshint esversion: 6 */
  2. var zip = zip || {};
  3. var zlib = zlib || {};
  4. zip.Archive = class {
  5. static open(buffer) {
  6. const stream = buffer instanceof Uint8Array ? new zip.BinaryReader(buffer) : buffer;
  7. if (stream.length > 2 && stream.peek(1)[0] === 0x78) { // zlib
  8. return new zlib.Archive(stream);
  9. }
  10. const signature = [ 0x50, 0x4B, 0x01, 0x02 ];
  11. if (stream.length > 4 && stream.peek(2).every((value, index) => value === signature[index])) {
  12. return new zip.Archive(stream);
  13. }
  14. return null;
  15. }
  16. constructor(stream) {
  17. this._entries = [];
  18. const position = stream.position;
  19. const lookup = (stream, signature) => {
  20. let position = stream.length;
  21. do {
  22. position = Math.max(0, position - 64000);
  23. stream.seek(position);
  24. const buffer = stream.read(Math.min(stream.length - position, 65536));
  25. for (let i = buffer.length - 4; i >= 0; i--) {
  26. if (signature[0] === buffer[i] && signature[1] === buffer[i + 1] && signature[2] === buffer[i + 2] && signature[3] === buffer[i + 3]) {
  27. stream.seek(position + i + 4);
  28. return true;
  29. }
  30. }
  31. }
  32. while (position > 0);
  33. return false;
  34. };
  35. if (!lookup(stream, [ 0x50, 0x4B, 0x05, 0x06 ])) {
  36. throw new zip.Error('End of Zip central directory not found.');
  37. }
  38. let reader = new zip.BinaryReader(stream.read(16));
  39. reader.skip(12);
  40. let offset = reader.uint32(); // central directory offset
  41. if (offset > stream.length) {
  42. if (!lookup(stream, [ 0x50, 0x4B, 0x06, 0x06 ])) {
  43. throw new zip.Error('Zip64 end of central directory not found.');
  44. }
  45. reader = new zip.BinaryReader(stream.read(52));
  46. reader.skip(44);
  47. offset = reader.uint32();
  48. if (reader.uint32() !== 0) {
  49. throw new zip.Error('Zip 64-bit central directory offset not supported.');
  50. }
  51. }
  52. if (offset > stream.length) {
  53. throw new zip.Error('Invalid Zip central directory offset.');
  54. }
  55. stream.seek(offset); // central directory offset
  56. const entries = [];
  57. const signature = [ 0x50, 0x4B, 0x01, 0x02 ];
  58. while (stream.position + 4 < stream.length && stream.read(4).every((value, index) => value === signature[index])) {
  59. const entry = {};
  60. const reader = new zip.BinaryReader(stream.read(42));
  61. reader.uint16(); // version made by
  62. reader.skip(2); // version needed to extract
  63. const flags = reader.uint16();
  64. if ((flags & 1) == 1) {
  65. throw new zip.Error('Encrypted Zip entries not supported.');
  66. }
  67. entry.encoding = flags & 0x800 ? 'utf-8' : 'ascii';
  68. entry.compressionMethod = reader.uint16();
  69. reader.uint32(); // date
  70. reader.uint32(); // crc32
  71. entry.compressedSize = reader.uint32();
  72. entry.size = reader.uint32();
  73. entry.nameLength = reader.uint16(); // file name length
  74. const extraDataLength = reader.uint16();
  75. const commentLength = reader.uint16();
  76. entry.disk = reader.uint16(); // disk number start
  77. reader.uint16(); // internal file attributes
  78. reader.uint32(); // external file attributes
  79. entry.localHeaderOffset = reader.uint32();
  80. const nameBuffer = stream.read(entry.nameLength);
  81. const decoder = new TextDecoder(entry.encoding);
  82. entry.name = decoder.decode(nameBuffer);
  83. const extraData = stream.read(extraDataLength);
  84. if (extraData.length > 0) {
  85. const reader = new zip.BinaryReader(extraData);
  86. while (reader.position < reader.length) {
  87. const type = reader.uint16();
  88. const length = reader.uint16();
  89. switch (type) {
  90. case 0x0001:
  91. if (entry.size === 0xffffffff) {
  92. entry.size = reader.uint32();
  93. if (reader.uint32() !== 0) {
  94. throw new zip.Error('Zip 64-bit offset not supported.');
  95. }
  96. }
  97. if (entry.compressedSize === 0xffffffff) {
  98. entry.compressedSize = reader.uint32();
  99. if (reader.uint32() !== 0) {
  100. throw new zip.Error('Zip 64-bit offset not supported.');
  101. }
  102. }
  103. if (entry.localHeaderOffset === 0xffffffff) {
  104. entry.localHeaderOffset = reader.uint32();
  105. if (reader.uint32() !== 0) {
  106. throw new zip.Error('Zip 64-bit offset not supported.');
  107. }
  108. }
  109. if (entry.disk === 0xffff) {
  110. entry.disk = reader.uint32();
  111. }
  112. break;
  113. default:
  114. reader.skip(length);
  115. break;
  116. }
  117. }
  118. }
  119. stream.read(commentLength); // comment
  120. entries.push(entry);
  121. }
  122. for (const entry of entries) {
  123. if (entry.size === 0 && entry.name.endsWith('/')) {
  124. continue;
  125. }
  126. this._entries.push(new zip.Entry(stream, entry));
  127. }
  128. stream.seek(position);
  129. }
  130. get entries() {
  131. return this._entries;
  132. }
  133. };
  134. zip.Entry = class {
  135. constructor(stream, entry) {
  136. stream.seek(entry.localHeaderOffset);
  137. const signature = [ 0x50, 0x4B, 0x03, 0x04 ];
  138. if (stream.position + 4 > stream.length || !stream.read(4).every((value, index) => value === signature[index])) {
  139. throw new zip.Error('Invalid Zip local file header signature.');
  140. }
  141. const reader = new zip.BinaryReader(stream.read(26));
  142. reader.skip(22);
  143. entry.nameLength = reader.uint16();
  144. const extraDataLength = reader.uint16();
  145. entry.nameBuffer = stream.read(entry.nameLength);
  146. stream.skip(extraDataLength);
  147. const decoder = new TextDecoder(entry.encoding);
  148. this._name = decoder.decode(entry.nameBuffer);
  149. this._stream = stream.stream(entry.compressedSize);
  150. switch (entry.compressionMethod) {
  151. case 0: { // Stored
  152. if (entry.size !== entry.compressedSize) {
  153. throw new zip.Error('Invalid compression size.');
  154. }
  155. break;
  156. }
  157. case 8: {
  158. // Deflate
  159. this._stream = new zip.InflaterStream(this._stream, entry.size);
  160. break;
  161. }
  162. default:
  163. throw new zip.Error('Invalid compression method.');
  164. }
  165. }
  166. get name() {
  167. return this._name;
  168. }
  169. get stream() {
  170. return this._stream;
  171. }
  172. get data() {
  173. return this.stream.peek();
  174. }
  175. };
  176. zip.Inflater = class {
  177. inflateRaw(data, length) {
  178. let buffer = null;
  179. if (typeof process === 'object' && typeof process.versions == 'object' && typeof process.versions.node !== 'undefined') {
  180. buffer = require('zlib').inflateRawSync(data);
  181. }
  182. else {
  183. const reader = new zip.BitReader(data);
  184. const writer = length === undefined ? new zip.BlockWriter() : new zip.BufferWriter(length);
  185. if (!zip.Inflater._staticLengthTree) {
  186. zip.Inflater._codeLengths = new Uint8Array(19);
  187. zip.Inflater._codeOrder = [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
  188. zip.Inflater._lengthBase = [ 24, 32, 40, 48, 56, 64, 72, 80, 89, 105, 121, 137, 154, 186, 218, 250, 283, 347, 411, 475, 540, 668, 796, 924, 1053, 1309, 1565, 1821, 2064, 7992, 7992, 7992 ];
  189. zip.Inflater._distanceBase = [ 16, 32, 48, 64, 81, 113, 146, 210, 275, 403, 532, 788, 1045, 1557, 2070, 3094, 4119, 6167, 8216, 12312, 16409, 24601, 32794, 49178, 65563, 98331, 131100, 196636, 262173, 393245, 1048560, 1048560 ];
  190. }
  191. let type;
  192. do {
  193. type = reader.bits(3);
  194. switch (type >>> 1) {
  195. case 0: { // uncompressed block
  196. this._copyUncompressedBlock(reader, writer);
  197. break;
  198. }
  199. case 1: { // block with fixed huffman trees
  200. if (!zip.Inflater._staticLengthTree) {
  201. zip.Inflater._staticLengthTree = zip.HuffmanTree.create(new Uint8Array([].concat.apply([], [[144, 8], [112, 9], [24, 7], [8, 8]].map((x) => [...Array(x[0])].map(() => x[1])))));
  202. zip.Inflater._staticDistanceTree = zip.HuffmanTree.create(new Uint8Array([...Array(32)].map(() => 5)));
  203. }
  204. this._lengthTree = zip.Inflater._staticLengthTree;
  205. this._distanceTree = zip.Inflater._staticDistanceTree;
  206. this._inflateBlock(reader, writer);
  207. break;
  208. }
  209. case 2: { // block with dynamic huffman trees
  210. this._decodeTrees(reader);
  211. this._inflateBlock(reader, writer);
  212. break;
  213. }
  214. default: {
  215. throw new zip.Error('Unknown block type.');
  216. }
  217. }
  218. } while ((type & 1) == 0);
  219. if (length !== undefined && length !== writer.length) {
  220. throw new zip.Error('Invalid uncompressed size.');
  221. }
  222. buffer = writer.toBuffer();
  223. }
  224. if (length !== undefined && length !== buffer.length) {
  225. throw new zip.Error('Invalid uncompressed size.');
  226. }
  227. return buffer;
  228. }
  229. _copyUncompressedBlock(reader, writer) {
  230. const length = reader.uint16();
  231. const inverseLength = reader.uint16();
  232. if (length !== (~inverseLength & 0xffff)) {
  233. throw new zip.Error('Invalid uncompressed block length.');
  234. }
  235. writer.write(reader.read(length));
  236. }
  237. _decodeTrees(reader) {
  238. const hlit = reader.bits(5) + 257;
  239. const hdist = reader.bits(5) + 1;
  240. const hclen = reader.bits(4) + 4;
  241. const codeLengths = zip.Inflater._codeLengths;
  242. for (let i = 0; i < codeLengths.length; i++) {
  243. codeLengths[i] = 0;
  244. }
  245. const codeOrder = zip.Inflater._codeOrder;
  246. for (let i = 0; i < hclen; i++) {
  247. codeLengths[codeOrder[i]] = reader.bits(3);
  248. }
  249. const codeTree = zip.HuffmanTree.create(codeLengths);
  250. const codeMask = codeTree.length - 1;
  251. const lengths = new Uint8Array(hlit + hdist);
  252. let value = 0;
  253. let length = 0;
  254. for (let i = 0; i < hlit + hdist;) {
  255. const code = codeTree[reader.bits16() & codeMask];
  256. reader.position += code & 0x0f;
  257. const literal = code >>> 4;
  258. switch (literal) {
  259. case 16: length = reader.bits(2) + 3; break;
  260. case 17: length = reader.bits(3) + 3; value = 0; break;
  261. case 18: length = reader.bits(7) + 11; value = 0; break;
  262. default: length = 1; value = literal; break;
  263. }
  264. for (; length > 0; length--) {
  265. lengths[i++] = value;
  266. }
  267. }
  268. this._lengthTree = zip.HuffmanTree.create(lengths.subarray(0, hlit));
  269. this._distanceTree = zip.HuffmanTree.create(lengths.subarray(hlit, hlit + hdist));
  270. }
  271. _inflateBlock(reader, writer) {
  272. const lengthTree = this._lengthTree;
  273. const distanceTree = this._distanceTree;
  274. const lengthMask = lengthTree.length - 1;
  275. const distanceMask = distanceTree.length - 1;
  276. const buffer = writer.buffer;
  277. const threshold = writer.threshold !== undefined ? writer.threshold : writer.length;
  278. let position = writer.position;
  279. for (;;) {
  280. if (position > threshold) {
  281. position = writer.push(position);
  282. }
  283. const code = lengthTree[reader.bits16() & lengthMask];
  284. reader.position += code & 0x0f;
  285. const literal = code >>> 4;
  286. if (literal < 256) {
  287. buffer[position++] = literal;
  288. }
  289. else if (literal === 256) {
  290. writer.push(position);
  291. return;
  292. }
  293. else {
  294. let length = literal - 254;
  295. if (literal > 264) {
  296. const lengthBase = zip.Inflater._lengthBase[literal - 257];
  297. length = (lengthBase >>> 3) + reader.bits(lengthBase & 0x07);
  298. }
  299. const code = distanceTree[reader.bits16() & distanceMask];
  300. reader.position += code & 0x0f;
  301. const distanceBase = zip.Inflater._distanceBase[code >>> 4];
  302. const bits = distanceBase & 0x0f;
  303. const distance = (distanceBase >>> 4) + (reader.bits16() & ((1 << bits) - 1));
  304. reader.position += bits;
  305. let offset = position - distance;
  306. for (let i = 0; i < length; i++) {
  307. buffer[position++] = buffer[offset++];
  308. }
  309. }
  310. }
  311. }
  312. };
  313. zip.HuffmanTree = class {
  314. static create(tree) {
  315. let bits = tree[0];
  316. for (let i = 1; i < tree.length; ++i) {
  317. if (tree[i] > bits) {
  318. bits = tree[i];
  319. }
  320. }
  321. // Algorithm from https://github.com/photopea/UZIP.js
  322. let rev15 = zip.HuffmanTree._rev15;
  323. if (!rev15) {
  324. const length = 1 << 15;
  325. rev15 = new Uint16Array(length);
  326. for (let i = 0; i < length; i++) {
  327. let x = i;
  328. x = (((x & 0xaaaaaaaa) >>> 1) | ((x & 0x55555555) << 1));
  329. x = (((x & 0xcccccccc) >>> 2) | ((x & 0x33333333) << 2));
  330. x = (((x & 0xf0f0f0f0) >>> 4) | ((x & 0x0f0f0f0f) << 4));
  331. x = (((x & 0xff00ff00) >>> 8) | ((x & 0x00ff00ff) << 8));
  332. rev15[i] = (((x >>> 16) | (x << 16))) >>> 17;
  333. }
  334. zip.HuffmanTree._rev15 = rev15;
  335. zip.HuffmanTree._bitLengthCounts = new Uint16Array(16);
  336. zip.HuffmanTree._nextCodes = new Uint16Array(16);
  337. }
  338. const length = tree.length;
  339. const bitLengthCounts = zip.HuffmanTree._bitLengthCounts;
  340. for (let i = 0; i < 16; i++) {
  341. bitLengthCounts[i] = 0;
  342. }
  343. for (let i = 0; i < length; i++) {
  344. bitLengthCounts[tree[i]]++;
  345. }
  346. const nextCodes = zip.HuffmanTree._nextCodes;
  347. let code = 0;
  348. bitLengthCounts[0] = 0;
  349. for (let i = 0; i < bits; i++) {
  350. code = (code + bitLengthCounts[i]) << 1;
  351. nextCodes[i + 1] = code;
  352. }
  353. const codes = new Uint16Array(length);
  354. for (let i = 0; i < length; i++) {
  355. const index = tree[i];
  356. if (index !== 0) {
  357. codes[i] = nextCodes[index];
  358. nextCodes[index]++;
  359. }
  360. }
  361. const shift = 15 - bits;
  362. const table = new Uint16Array(1 << bits);
  363. for (let i = 0; i < length; i++) {
  364. const c = tree[i];
  365. if (c !== 0) {
  366. const value = (i << 4) | c;
  367. const rest = bits - c;
  368. let index = codes[i] << rest;
  369. const max = index + (1 << rest);
  370. for (; index != max; index++) {
  371. table[rev15[index] >>> shift] = value;
  372. }
  373. }
  374. }
  375. return table;
  376. }
  377. };
  378. zip.BitReader = class {
  379. constructor(buffer) {
  380. this.buffer = buffer;
  381. this.position = 0;
  382. }
  383. bits(count) {
  384. const offset = (this.position / 8) >> 0;
  385. const shift = (this.position & 7);
  386. this.position += count;
  387. return ((this.buffer[offset] | (this.buffer[offset + 1] << 8)) >>> shift) & ((1 << count) - 1);
  388. }
  389. bits16() {
  390. const offset = (this.position / 8) >> 0;
  391. return ((this.buffer[offset] | (this.buffer[offset + 1] << 8) | (this.buffer[offset + 2] << 16)) >>> (this.position & 7));
  392. }
  393. read(length) {
  394. this.position = (this.position + 7) & ~7; // align
  395. const offset = (this.position / 8) >> 0;
  396. this.position += length * 8;
  397. return this.buffer.subarray(offset, offset + length);
  398. }
  399. uint16() {
  400. this.position = (this.position + 7) & ~7; // align
  401. const offset = (this.position / 8) >> 0;
  402. this.position += 16;
  403. return this.buffer[offset] | (this.buffer[offset + 1] << 8);
  404. }
  405. };
  406. zip.BlockWriter = class {
  407. constructor() {
  408. this.blocks = [];
  409. this.buffer = new Uint8Array(65536);
  410. this.position = 0;
  411. this.length = 0;
  412. this.threshold = 0xf400;
  413. }
  414. push(position) {
  415. this.blocks.push(new Uint8Array(this.buffer.subarray(this.position, position)));
  416. this.length += position - this.position;
  417. this.position = position;
  418. return this._reset();
  419. }
  420. write(buffer) {
  421. this.blocks.push(buffer);
  422. const length = buffer.length;
  423. this.length += length;
  424. if (length > 32768) {
  425. this.buffer.set(buffer.subarray(length - 32768, length), 0);
  426. this.position = 32768;
  427. }
  428. else {
  429. this._reset();
  430. this.buffer.set(buffer, this.position);
  431. this.position += length;
  432. }
  433. }
  434. toBuffer() {
  435. const buffer = new Uint8Array(this.length);
  436. let offset = 0;
  437. for (const block of this.blocks) {
  438. buffer.set(block, offset);
  439. offset += block.length;
  440. }
  441. return buffer;
  442. }
  443. _reset() {
  444. if (this.position > 32768) {
  445. this.buffer.set(this.buffer.subarray(this.position - 32768, this.position), 0);
  446. this.position = 32768;
  447. }
  448. return this.position;
  449. }
  450. };
  451. zip.BufferWriter = class {
  452. constructor(length) {
  453. this.buffer = new Uint8Array(length);
  454. this.length = length;
  455. this.position = 0;
  456. }
  457. push(position) {
  458. this.position = position;
  459. if (this.position > this.length) {
  460. throw new zip.Error('Invalid size.');
  461. }
  462. return this.position;
  463. }
  464. write(buffer) {
  465. this.buffer.set(buffer, this.position);
  466. this.position += buffer.length;
  467. if (this.position > this.length) {
  468. throw new zip.Error('Invalid size.');
  469. }
  470. return this.position;
  471. }
  472. toBuffer() {
  473. return this.buffer;
  474. }
  475. };
  476. zip.InflaterStream = class {
  477. constructor(stream, length) {
  478. this._stream = stream;
  479. this._offset = this._stream.position;
  480. this._position = 0;
  481. this._length = length;
  482. }
  483. get position() {
  484. return this._position;
  485. }
  486. get length() {
  487. if (this._length === undefined) {
  488. this._inflate();
  489. }
  490. return this._length;
  491. }
  492. seek(position) {
  493. if (this._buffer === undefined) {
  494. this._inflate();
  495. }
  496. this._position = position >= 0 ? position : this._length + position;
  497. }
  498. skip(offset) {
  499. if (this._buffer === undefined) {
  500. this._inflate();
  501. }
  502. this._position += offset;
  503. }
  504. peek(length) {
  505. const position = this._position;
  506. length = length !== undefined ? length : this._length - position;
  507. this.skip(length);
  508. const end = this._position;
  509. this.seek(position);
  510. if (position === 0 && length === this._length) {
  511. return this._buffer;
  512. }
  513. return this._buffer.subarray(position, end);
  514. }
  515. read(length) {
  516. const position = this._position;
  517. length = length !== undefined ? length : this._length - position;
  518. this.skip(length);
  519. if (position === 0 && length === this._length) {
  520. return this._buffer;
  521. }
  522. return this._buffer.subarray(position, this._position);
  523. }
  524. byte() {
  525. const position = this._position;
  526. this.skip(1);
  527. return this._buffer[position];
  528. }
  529. _inflate() {
  530. if (this._buffer === undefined) {
  531. const position = this._stream.position;
  532. this._stream.seek(this._offset);
  533. const buffer = this._stream.peek();
  534. this._buffer = new zip.Inflater().inflateRaw(buffer, this._length);
  535. this._length = this._buffer.length;
  536. this._stream.seek(position);
  537. delete this._stream;
  538. }
  539. }
  540. };
  541. zip.BinaryReader = class {
  542. constructor(buffer) {
  543. this._buffer = buffer;
  544. this._length = buffer.length;
  545. this._position = 0;
  546. this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
  547. }
  548. get position() {
  549. return this._position;
  550. }
  551. get length() {
  552. return this._length;
  553. }
  554. create(buffer) {
  555. return new zip.BinaryReader(buffer);
  556. }
  557. stream(length) {
  558. return this.create(this.read(length));
  559. }
  560. seek(position) {
  561. this._position = position >= 0 ? position : this._length + position;
  562. }
  563. skip(offset) {
  564. this._position += offset;
  565. }
  566. peek(length) {
  567. if (this._position === 0 && length === undefined) {
  568. return this._buffer;
  569. }
  570. const position = this._position;
  571. this.skip(length !== undefined ? length : this._length - this._position);
  572. const end = this._position;
  573. this.seek(position);
  574. return this._buffer.subarray(position, end);
  575. }
  576. read(length) {
  577. if (this._position === 0 && length === undefined) {
  578. this._position = this._length;
  579. return this._buffer;
  580. }
  581. const position = this._position;
  582. this.skip(length !== undefined ? length : this._length - this._position);
  583. return this._buffer.subarray(position, this._position);
  584. }
  585. byte() {
  586. const position = this._position;
  587. this.skip(1);
  588. return this._buffer[position];
  589. }
  590. uint16() {
  591. const position = this._position;
  592. this.skip(2);
  593. return this._view.getUint16(position, true);
  594. }
  595. uint32() {
  596. const position = this._position;
  597. this.skip(4);
  598. return this._view.getUint32(position, true);
  599. }
  600. };
  601. zlib.Archive = class {
  602. constructor(stream) {
  603. const position = stream.position;
  604. stream.read(2);
  605. this._entries = [ new zlib.Entry(stream) ];
  606. stream.seek(position);
  607. }
  608. get entries() {
  609. return this._entries;
  610. }
  611. };
  612. zlib.Entry = class {
  613. constructor(stream) {
  614. this._stream = new zip.InflaterStream(stream);
  615. }
  616. get name() {
  617. return '';
  618. }
  619. get stream() {
  620. return this._stream;
  621. }
  622. get data() {
  623. return this.stream.peek();
  624. }
  625. };
  626. zip.Error = class extends Error {
  627. constructor(message) {
  628. super(message);
  629. this.name = 'Zip Error';
  630. }
  631. };
  632. if (typeof module !== 'undefined' && typeof module.exports === 'object') {
  633. module.exports.Archive = zip.Archive;
  634. module.exports.Inflater = zip.Inflater;
  635. }