zip.js 25 KB

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