      1 /*
      2     Copyright 2008-2024
      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.js";
     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