1 /*
  2     Copyright 2008-2023
  3         Matthias Ehmann,
  4         Michael Gerhaeuser,
  5         Carsten Miller,
  6         Bianca Valentin,
  7         Alfred Wassermann,
  8         Peter Wilfahrt
  9 
 10     This file is part of JSXGraph and JSXCompressor.
 11 
 12     JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
 13     JSXCompressor is free software dual licensed under the GNU LGPL or Apache License.
 14 
 15     You can redistribute it and/or modify it under the terms of the
 16 
 17       * GNU Lesser General Public License as published by
 18         the Free Software Foundation, either version 3 of the License, or
 19         (at your option) any later version
 20       OR
 21       * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
 22       OR
 23       * Apache License Version 2.0
 24 
 25     JSXGraph is distributed in the hope that it will be useful,
 26     but WITHOUT ANY WARRANTY; without even the implied warranty of
 27     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 28     GNU Lesser General Public License for more details.
 29 
 30     You should have received a copy of the GNU Lesser General Public License, Apache
 31     License, and the MIT License along with JSXGraph. If not, see
 32     <https://www.gnu.org/licenses/>, <https://www.apache.org/licenses/LICENSE-2.0.html>,
 33     and <https://opensource.org/licenses/MIT/>.
 34  */
 35 
 36 /*global JXG: true, define: true*/
 37 /*jslint nomen: true, plusplus: true, bitwise: true*/
 38 
 39 /**
 40  * @fileoverview Utilities for uncompressing and base64 decoding
 41  */
 42 
 43 import JXG from "../jxg";
 44 
 45 // Zip routine constants
 46 
 47 var bitReverse = [
 48         0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0,
 49         0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8,
 50         0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94,
 51         0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
 52         0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2,
 53         0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca,
 54         0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86,
 55         0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
 56         0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe,
 57         0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1,
 58         0x31, 0xb1, 0x71, 0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99,
 59         0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
 60         0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad,
 61         0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3,
 62         0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b,
 63         0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
 64         0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7,
 65         0x77, 0xf7, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf,
 66         0x3f, 0xbf, 0x7f, 0xff
 67     ],
 68     cplens = [
 69         3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99,
 70         115, 131, 163, 195, 227, 258, 0, 0
 71     ],
 72     cplext = [
 73         0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0,
 74         99, 99
 75     ] /* 99==invalid */,
 76     cpdist = [
 77         0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0007, 0x0009, 0x000d, 0x0011, 0x0019, 0x0021,
 78         0x0031, 0x0041, 0x0061, 0x0081, 0x00c1, 0x0101, 0x0181, 0x0201, 0x0301, 0x0401, 0x0601,
 79         0x0801, 0x0c01, 0x1001, 0x1801, 0x2001, 0x3001, 0x4001, 0x6001
 80     ],
 81     cpdext = [
 82         0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
 83         12, 13, 13
 84     ],
 85     border = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15],
 86     NAMEMAX = 256;
 87 
 88 // Util namespace
 89 JXG.Util = JXG.Util || {};
 90 
 91 /**
 92  * @class Unzip class
 93  * Class for gunzipping, unzipping and base64 decoding of files.
 94  * It is used for reading GEONExT, Geogebra and Intergeo files.
 95  *
 96  * Only Huffman codes are decoded in gunzip.
 97  * The code is based on the source code for gunzip.c by Pasi Ojala
 98  * @see http://www.cs.tut.fi/~albert/Dev/gunzip/gunzip.c
 99  * @see http://www.cs.tut.fi/~albert
100  */
101 JXG.Util.Unzip = function (barray) {
102     var gpflags,
103         // SIZE,
104         fileout,
105         flens,
106         fmax,
107         outputArr = [],
108         files = 0,
109         unzipped = [],
110         buf32k = new Array(32768),
111         bIdx = 0,
112         modeZIP = false,
113         barraylen = barray.length,
114         bytepos = 0,
115         bb = 1,
116         // bits = 0,
117         literalTree = new Array(288),
118         distanceTree = new Array(32),
119         treepos = 0,
120         Places = null,
121         // crc,
122         // output = "",
123         // debug = false,
124         // bitpos = 0,
125         // Places2 = null,
126         // impDistanceTree = new Array(64),
127         // impLengthTree = new Array(64),
128         len = 0,
129         fpos = new Array(17),
130         nameBuf = [];
131 
132     fpos[0] = 0;
133 
134     function readByte() {
135         // bits += 8;
136 
137         if (bytepos < barraylen) {
138             return barray[bytepos++];
139         }
140 
141         return -1;
142     }
143 
144     function byteAlign() {
145         bb = 1;
146     }
147 
148     function readBit() {
149         var carry;
150 
151         // Prevent problems on iOS7 with >>
152         try {
153             // bits++;
154             carry = bb & 1;
155             bb >>= 1;
156 
157             if (bb === 0) {
158                 bb = readByte();
159                 carry = bb & 1;
160                 bb = (bb >> 1) | 0x80;
161             }
162         } catch (e) {
163             console.log("Probably problems on iOS7 with >>");
164             throw e;
165         }
166 
167         return carry;
168     }
169 
170     function readBits(a) {
171         var res = 0,
172             i = a;
173 
174         // Prevent problems on iOS7 with >>
175         try {
176             while (i--) {
177                 res = (res << 1) | readBit();
178             }
179 
180             if (a) {
181                 res = bitReverse[res] >> (8 - a);
182             }
183         } catch (e) {
184             console.log("Probably problems on iOS7 with >>");
185             throw e;
186         }
187         return res;
188     }
189 
190     function flushBuffer() {
191         bIdx = 0;
192     }
193 
194     function addBuffer(a) {
195         // SIZE++;
196         buf32k[bIdx++] = a;
197         outputArr.push(String.fromCharCode(a));
198 
199         if (bIdx === 0x8000) {
200             bIdx = 0;
201         }
202     }
203 
204     function HufNode() {
205         this.b0 = 0;
206         this.b1 = 0;
207         this.jump = null;
208         this.jumppos = -1;
209     }
210 
211     function isPat() {
212         var endless = true;
213         while (endless) {
214             if (fpos[len] >= fmax) {
215                 return -1;
216             }
217 
218             if (flens[fpos[len]] === len) {
219                 return fpos[len]++;
220             }
221 
222             fpos[len]++;
223         }
224     }
225 
226     function rec() {
227         var curplace = Places[treepos],
228             tmp;
229 
230         if (len === 17) {
231             return -1;
232         }
233         treepos++;
234         len++;
235 
236         tmp = isPat();
237 
238         if (tmp >= 0) {
239             /* leaf cell for 0-bit */
240             curplace.b0 = tmp;
241         } else {
242             /* Not a Leaf cell */
243             curplace.b0 = 0x8000;
244 
245             if (rec()) {
246                 return -1;
247             }
248         }
249 
250         tmp = isPat();
251 
252         if (tmp >= 0) {
253             /* leaf cell for 1-bit */
254             curplace.b1 = tmp;
255             /* Just for the display routine */
256             curplace.jump = null;
257         } else {
258             /* Not a Leaf cell */
259             curplace.b1 = 0x8000;
260             curplace.jump = Places[treepos];
261             curplace.jumppos = treepos;
262             if (rec()) {
263                 return -1;
264             }
265         }
266         len--;
267 
268         return 0;
269     }
270 
271     function createTree(currentTree, numval, lengths, show) {
272         var i;
273 
274         Places = currentTree;
275         treepos = 0;
276         flens = lengths;
277         fmax = numval;
278 
279         for (i = 0; i < 17; i++) {
280             fpos[i] = 0;
281         }
282         len = 0;
283 
284         if (rec()) {
285             return -1;
286         }
287 
288         return 0;
289     }
290 
291     function decodeValue(currentTree) {
292         var len,
293             i, b,
294             endless = true,
295             xtreepos = 0,
296             X = currentTree[xtreepos];
297 
298         /* decode one symbol of the data */
299         while (endless) {
300             b = readBit();
301 
302             if (b) {
303                 if (!(X.b1 & 0x8000)) {
304                     /* If leaf node, return data */
305                     return X.b1;
306                 }
307 
308                 X = X.jump;
309                 len = currentTree.length;
310 
311                 for (i = 0; i < len; i++) {
312                     if (currentTree[i] === X) {
313                         xtreepos = i;
314                         break;
315                     }
316                 }
317             } else {
318                 if (!(X.b0 & 0x8000)) {
319                     /* If leaf node, return data */
320                     return X.b0;
321                 }
322                 xtreepos++;
323                 X = currentTree[xtreepos];
324             }
325         }
326     }
327 
328     function deflateLoop() {
329         var last, c, type, i, j, l, ll, ll2,
330             len, blockLen, dist, cSum, n,// z,
331             literalCodes, distCodes, lenCodes,
332             endless = true;
333 
334         do {
335             last = readBit();
336             type = readBits(2);
337 
338             if (type === 0) {
339                 // Stored
340                 byteAlign();
341                 blockLen = readByte();
342                 blockLen |= readByte() << 8;
343 
344                 cSum = readByte();
345                 cSum |= readByte() << 8;
346 
347                 if ((blockLen ^ ~cSum) & 0xffff) {
348                     JXG.debug("BlockLen checksum mismatch\n");
349                 }
350 
351                 while (blockLen--) {
352                     c = readByte();
353                     addBuffer(c);
354                 }
355             } else if (type === 1) {
356                 /* Fixed Huffman tables -- fixed decode routine */
357                 while (endless) {
358                     /*
359                          256    0000000        0
360                          :   :     :
361                          279    0010111        23
362                          0   00110000    48
363                          :    :      :
364                          143    10111111    191
365                          280 11000000    192
366                          :    :      :
367                          287 11000111    199
368                          144    110010000    400
369                          :    :       :
370                          255    111111111    511
371 
372                          Note the bit order!
373                          */
374 
375                     j = bitReverse[readBits(7)] >> 1;
376 
377                     if (j > 23) {
378                         j = (j << 1) | readBit(); /* 48..255 */
379 
380                         if (j > 199) {
381                             /* 200..255 */
382                             j -= 128; /*  72..127 */
383                             j = (j << 1) | readBit(); /* 144..255 << */
384                         } else {
385                             /*  48..199 */
386                             j -= 48; /*   0..151 */
387                             if (j > 143) {
388                                 j = j + 136; /* 280..287 << */
389                                 /*   0..143 << */
390                             }
391                         }
392                     } else {
393                         /*   0..23 */
394                         j += 256; /* 256..279 << */
395                     }
396 
397                     if (j < 256) {
398                         addBuffer(j);
399                     } else if (j === 256) {
400                         /* EOF */
401                         break;
402                     } else {
403                         j -= 256 + 1; /* bytes + EOF */
404                         len = readBits(cplext[j]) + cplens[j];
405                         j = bitReverse[readBits(5)] >> 3;
406 
407                         if (cpdext[j] > 8) {
408                             dist = readBits(8);
409                             dist |= readBits(cpdext[j] - 8) << 8;
410                         } else {
411                             dist = readBits(cpdext[j]);
412                         }
413 
414                         dist += cpdist[j];
415 
416                         for (j = 0; j < len; j++) {
417                             c = buf32k[(bIdx - dist) & 0x7fff];
418                             addBuffer(c);
419                         }
420                     }
421                 } // while
422             } else if (type === 2) {
423                 // "static" just to preserve stack
424                 ll = new Array(288 + 32);
425 
426                 // Dynamic Huffman tables
427                 literalCodes = 257 + readBits(5);
428                 distCodes = 1 + readBits(5);
429                 lenCodes = 4 + readBits(4);
430 
431                 for (j = 0; j < 19; j++) {
432                     ll[j] = 0;
433                 }
434 
435                 // Get the decode tree code lengths
436 
437                 for (j = 0; j < lenCodes; j++) {
438                     ll[border[j]] = readBits(3);
439                 }
440                 len = distanceTree.length;
441 
442                 for (i = 0; i < len; i++) {
443                     distanceTree[i] = new HufNode();
444                 }
445 
446                 if (createTree(distanceTree, 19, ll, 0)) {
447                     flushBuffer();
448                     return 1;
449                 }
450 
451                 //read in literal and distance code lengths
452                 n = literalCodes + distCodes;
453                 i = 0;
454                 // z = -1;
455 
456                 while (i < n) {
457                     // z++;
458                     j = decodeValue(distanceTree);
459 
460                     // length of code in bits (0..15)
461                     if (j < 16) {
462                         ll[i++] = j;
463                         // repeat last length 3 to 6 times
464                     } else if (j === 16) {
465                         j = 3 + readBits(2);
466 
467                         if (i + j > n) {
468                             flushBuffer();
469                             return 1;
470                         }
471                         l = i ? ll[i - 1] : 0;
472 
473                         while (j--) {
474                             ll[i++] = l;
475                         }
476                     } else {
477                         // 3 to 10 zero length codes
478                         if (j === 17) {
479                             j = 3 + readBits(3);
480                             // j == 18: 11 to 138 zero length codes
481                         } else {
482                             j = 11 + readBits(7);
483                         }
484 
485                         if (i + j > n) {
486                             flushBuffer();
487                             return 1;
488                         }
489 
490                         while (j--) {
491                             ll[i++] = 0;
492                         }
493                     }
494                 }
495 
496                 // Can overwrite tree decode tree as it is not used anymore
497                 len = literalTree.length;
498                 for (i = 0; i < len; i++) {
499                     literalTree[i] = new HufNode();
500                 }
501 
502                 if (createTree(literalTree, literalCodes, ll, 0)) {
503                     flushBuffer();
504                     return 1;
505                 }
506 
507                 len = literalTree.length;
508 
509                 for (i = 0; i < len; i++) {
510                     distanceTree[i] = new HufNode();
511                 }
512 
513                 ll2 = [];
514 
515                 for (i = literalCodes; i < ll.length; i++) {
516                     ll2[i - literalCodes] = ll[i];
517                 }
518 
519                 if (createTree(distanceTree, distCodes, ll2, 0)) {
520                     flushBuffer();
521                     return 1;
522                 }
523 
524                 while (endless) {
525                     j = decodeValue(literalTree);
526 
527                     // In C64: if carry set
528                     if (j >= 256) {
529                         j -= 256;
530                         if (j === 0) {
531                             // EOF
532                             break;
533                         }
534 
535                         j -= 1;
536                         len = readBits(cplext[j]) + cplens[j];
537                         j = decodeValue(distanceTree);
538 
539                         if (cpdext[j] > 8) {
540                             dist = readBits(8);
541                             dist |= readBits(cpdext[j] - 8) << 8;
542                         } else {
543                             dist = readBits(cpdext[j]);
544                         }
545 
546                         dist += cpdist[j];
547 
548                         while (len--) {
549                             c = buf32k[(bIdx - dist) & 0x7fff];
550                             addBuffer(c);
551                         }
552                     } else {
553                         addBuffer(j);
554                     }
555                 }
556             }
557         } while (!last);
558 
559         flushBuffer();
560         byteAlign();
561 
562         return 0;
563     }
564 
565     /**
566      * nextFile:
567      * Extract the next file from the compressed archive.
568      * Calls skipdir() to proceed recursively.
569      *
570      * @return {Boolean}  false if the end of files' data section has baseElement
571      * reached. Then, then all recursive functions are stopped immediately.
572      *
573      */
574     function nextFile() {
575         /* eslint-disable no-unused-vars */
576         var i,
577             c,
578             extralen,
579             filelen,
580             size,
581             compSize,
582             crc,
583             method,
584             tmp = [];
585 
586         // Prevent problems on iOS7 with >>
587         try {
588             outputArr = [];
589             modeZIP = false;
590             tmp[0] = readByte();
591             tmp[1] = readByte();
592 
593             //GZIP
594             if (tmp[0] === 0x78 && tmp[1] === 0xda) {
595                 deflateLoop();
596                 unzipped[files] = [outputArr.join(""), "geonext.gxt"];
597                 files++;
598             }
599 
600             //GZIP
601             if (tmp[0] === 0x1f && tmp[1] === 0x8b) {
602                 skipdir();
603                 unzipped[files] = [outputArr.join(""), "file"];
604                 files++;
605             }
606 
607             //ZIP
608             if (tmp[0] === 0x50 && tmp[1] === 0x4b) {
609                 modeZIP = true;
610                 tmp[2] = readByte();
611                 tmp[3] = readByte();
612 
613                 if (tmp[2] === 0x03 && tmp[3] === 0x04) {
614                     //MODE_ZIP
615                     tmp[0] = readByte();
616                     tmp[1] = readByte();
617 
618                     gpflags = readByte();
619                     gpflags |= readByte() << 8;
620 
621                     method = readByte();
622                     method |= readByte() << 8;
623 
624                     readByte();
625                     readByte();
626                     readByte();
627                     readByte();
628 
629                     crc = readByte();
630                     crc |= readByte() << 8;
631                     crc |= readByte() << 16;
632                     crc |= readByte() << 24;
633 
634                     compSize = readByte();
635                     compSize |= readByte() << 8;
636                     compSize |= readByte() << 16;
637                     compSize |= readByte() << 24;
638 
639                     size = readByte();
640                     size |= readByte() << 8;
641                     size |= readByte() << 16;
642                     size |= readByte() << 24;
643 
644                     filelen = readByte();
645                     filelen |= readByte() << 8;
646 
647                     extralen = readByte();
648                     extralen |= readByte() << 8;
649 
650                     i = 0;
651                     nameBuf = [];
652 
653                     while (filelen--) {
654                         c = readByte();
655                         if ((c === "/") | (c === ":")) {
656                             i = 0;
657                         } else if (i < NAMEMAX - 1) {
658                             nameBuf[i++] = String.fromCharCode(c);
659                         }
660                     }
661 
662                     if (!fileout) {
663                         fileout = nameBuf;
664                     }
665 
666                     i = 0;
667                     while (i < extralen) {
668                         c = readByte();
669                         i++;
670                     }
671 
672                     // SIZE = 0;
673                     if (method === 8) {
674                         deflateLoop();
675                         unzipped[files] = new Array(2);
676                         unzipped[files][0] = outputArr.join("");
677                         unzipped[files][1] = nameBuf.join("");
678                         files++;
679                     }
680 
681                     if (skipdir()) {
682                         // We are beyond the files' data in the zip archive.
683                         // Let's get out immediately...
684                         return false;
685                     }
686                 }
687                 return true;
688             }
689         } catch (e) {
690             console.log("Probably problems on iOS7 with >>");
691             throw e;
692         }
693         return false;
694         /* eslint-enable no-unused-vars */
695     }
696 
697     /**
698      * Test if the end of the files' data part of the archive has baseElement
699      * reached. If not, uncompressing is resumed.
700      *
701      * @return {Boolean}  true if the end of the files' data sections have
702      * been reached.
703      *
704      * @private
705      */
706     function skipdir() {
707         /* eslint-disable no-unused-vars */
708         var crc, compSize, size, os, i, c,
709             tmp = [];
710 
711         if (gpflags & 8) {
712             tmp[0] = readByte();
713             tmp[1] = readByte();
714             tmp[2] = readByte();
715             tmp[3] = readByte();
716 
717             // signature for data descriptor record: 0x08074b50
718             // 12 bytes:
719             //  crc 4 bytes
720             //  compressed size 4 bytes
721             // uncompressed size 4 bytes
722             if (tmp[0] === 0x50 && tmp[1] === 0x4b && tmp[2] === 0x07 && tmp[3] === 0x08) {
723                 crc = readByte();
724                 crc |= readByte() << 8;
725                 crc |= readByte() << 16;
726                 crc |= readByte() << 24;
727             } else {
728                 crc = tmp[0] | (tmp[1] << 8) | (tmp[2] << 16) | (tmp[3] << 24);
729             }
730 
731             compSize = readByte();
732             compSize |= readByte() << 8;
733             compSize |= readByte() << 16;
734             compSize |= readByte() << 24;
735 
736             size = readByte();
737             size |= readByte() << 8;
738             size |= readByte() << 16;
739             size |= readByte() << 24;
740         }
741 
742         if (modeZIP) {
743             if (nextFile()) {
744                 // A file has been decompressed, we have to proceed
745                 return false;
746             }
747         }
748 
749         tmp[0] = readByte();
750         if (tmp[0] !== 8) {
751             // It seems, we are beyond the files' data in the zip archive.
752             // We'll skip the rest..
753             return true;
754         }
755 
756         // There is another file in the zip file. We proceed...
757         gpflags = readByte();
758 
759         readByte();
760         readByte();
761         readByte();
762         readByte();
763 
764         readByte();
765         os = readByte();
766 
767         if (gpflags & 4) {
768             tmp[0] = readByte();
769             tmp[2] = readByte();
770             len = tmp[0] + 256 * tmp[1];
771             for (i = 0; i < len; i++) {
772                 readByte();
773             }
774         }
775 
776         if (gpflags & 8) {
777             i = 0;
778             nameBuf = [];
779 
780             c = readByte();
781             while (c) {
782                 if (c === "7" || c === ":") {
783                     i = 0;
784                 }
785 
786                 if (i < NAMEMAX - 1) {
787                     nameBuf[i++] = c;
788                 }
789 
790                 c = readByte();
791             }
792         }
793 
794         if (gpflags & 16) {
795             c = readByte();
796             while (c) {
797                 c = readByte();
798             }
799         }
800 
801         if (gpflags & 2) {
802             readByte();
803             readByte();
804         }
805 
806         deflateLoop();
807 
808         crc = readByte();
809         crc |= readByte() << 8;
810         crc |= readByte() << 16;
811         crc |= readByte() << 24;
812 
813         size = readByte();
814         size |= readByte() << 8;
815         size |= readByte() << 16;
816         size |= readByte() << 24;
817 
818         if (modeZIP) {
819             if (nextFile()) {
820                 // A file has been decompressed, we have to proceed
821                 return false;
822             }
823         }
824 
825         // We are here in non-ZIP-files only,
826         // In that case the eturn value doesn't matter
827         return false;
828         /* eslint-enable no-unused-vars */
829 
830     }
831 
832     JXG.Util.Unzip.prototype.unzipFile = function (name) {
833         var i;
834 
835         this.unzip();
836 
837         for (i = 0; i < unzipped.length; i++) {
838             if (unzipped[i][1] === name) {
839                 return unzipped[i][0];
840             }
841         }
842 
843         return "";
844     };
845 
846     JXG.Util.Unzip.prototype.unzip = function () {
847         nextFile();
848         return unzipped;
849     };
850 };
851 
852 export default JXG.Util;
853