zip.js 26 KB

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