1 /* 2 Copyright 2008-2012 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. 11 12 Dual licensed under the Apache License Version 2.0, or LGPL Version 3 licenses. 13 14 You should have received a copy of the GNU Lesser General Public License 15 along with JSXCompressor. If not, see <http://www.gnu.org/licenses/>. 16 17 You should have received a copy of the Apache License along with JSXCompressor. 18 If not, see <http://www.apache.org/licenses/>. 19 20 */ 21 22 /** 23 * @fileoverview Utilities for uncompressing and base64 decoding 24 */ 25 26 /** 27 * @class Util class 28 * Class for gunzipping, unzipping and base64 decoding of files. 29 * It is used for reading GEONExT, Geogebra and Intergeo files. 30 * 31 * Only Huffman codes are decoded in gunzip. 32 * The code is based on the source code for gunzip.c by Pasi Ojala 33 * @see <a href="http://www.cs.tut.fi/~albert/Dev/gunzip/gunzip.c">http://www.cs.tut.fi/~albert/Dev/gunzip/gunzip.c</a> 34 * @see <a href="http://www.cs.tut.fi/~albert">http://www.cs.tut.fi/~albert</a> 35 */ 36 JXG.Util = {}; 37 38 /** 39 * Unzip zip files 40 */ 41 JXG.Util.Unzip = function (barray){ 42 var outputArr = [], 43 output = "", 44 debug = false, 45 gpflags, 46 files = 0, 47 unzipped = [], 48 crc, 49 buf32k = new Array(32768), 50 bIdx = 0, 51 modeZIP=false, 52 53 CRC, SIZE, 54 55 bitReverse = [ 56 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 57 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 58 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 59 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 60 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 61 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 62 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 63 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 64 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 65 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 66 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 67 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 68 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 69 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 70 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 71 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 72 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 73 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 74 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 75 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 76 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 77 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 78 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 79 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 80 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 81 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 82 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 83 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 84 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 85 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 86 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 87 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff 88 ], 89 90 cplens = [ 91 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 92 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 93 ], 94 95 cplext = [ 96 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 97 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99 98 ], /* 99==invalid */ 99 100 cpdist = [ 101 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0007, 0x0009, 0x000d, 102 0x0011, 0x0019, 0x0021, 0x0031, 0x0041, 0x0061, 0x0081, 0x00c1, 103 0x0101, 0x0181, 0x0201, 0x0301, 0x0401, 0x0601, 0x0801, 0x0c01, 104 0x1001, 0x1801, 0x2001, 0x3001, 0x4001, 0x6001 105 ], 106 107 cpdext = [ 108 0, 0, 0, 0, 1, 1, 2, 2, 109 3, 3, 4, 4, 5, 5, 6, 6, 110 7, 7, 8, 8, 9, 9, 10, 10, 111 11, 11, 12, 12, 13, 13 112 ], 113 114 border = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15], 115 116 bA = barray, 117 118 bytepos=0, 119 bitpos=0, 120 bb = 1, 121 bits=0, 122 123 NAMEMAX = 256, 124 125 nameBuf = [], 126 127 fileout; 128 129 function readByte(){ 130 bits+=8; 131 if (bytepos<bA.length){ 132 //if (debug) 133 // document.write(bytepos+": "+bA[bytepos]+"<br>"); 134 return bA[bytepos++]; 135 } else 136 return -1; 137 }; 138 139 function byteAlign(){ 140 bb = 1; 141 }; 142 143 function readBit(){ 144 var carry; 145 bits++; 146 carry = (bb & 1); 147 bb >>= 1; 148 if (bb==0){ 149 bb = readByte(); 150 carry = (bb & 1); 151 bb = (bb>>1) | 0x80; 152 } 153 return carry; 154 }; 155 156 function readBits(a) { 157 var res = 0, 158 i = a; 159 160 while(i--) { 161 res = (res<<1) | readBit(); 162 } 163 if(a) { 164 res = bitReverse[res]>>(8-a); 165 } 166 return res; 167 }; 168 169 function flushBuffer(){ 170 //document.write('FLUSHBUFFER:'+buf32k); 171 bIdx = 0; 172 }; 173 function addBuffer(a){ 174 SIZE++; 175 //CRC=updcrc(a,crc); 176 buf32k[bIdx++] = a; 177 outputArr.push(String.fromCharCode(a)); 178 //output+=String.fromCharCode(a); 179 if(bIdx==0x8000){ 180 //document.write('ADDBUFFER:'+buf32k); 181 bIdx=0; 182 } 183 }; 184 185 function HufNode() { 186 this.b0=0; 187 this.b1=0; 188 this.jump = null; 189 this.jumppos = -1; 190 }; 191 192 var LITERALS = 288; 193 194 var literalTree = new Array(LITERALS); 195 var distanceTree = new Array(32); 196 var treepos=0; 197 var Places = null; 198 var Places2 = null; 199 200 var impDistanceTree = new Array(64); 201 var impLengthTree = new Array(64); 202 203 var len = 0; 204 var fpos = new Array(17); 205 fpos[0]=0; 206 var flens; 207 var fmax; 208 209 function IsPat() { 210 while (1) { 211 if (fpos[len] >= fmax) 212 return -1; 213 if (flens[fpos[len]] == len) 214 return fpos[len]++; 215 fpos[len]++; 216 } 217 }; 218 219 function Rec() { 220 var curplace = Places[treepos]; 221 var tmp; 222 if (debug) 223 document.write("<br>len:"+len+" treepos:"+treepos); 224 if(len==17) { //war 17 225 return -1; 226 } 227 treepos++; 228 len++; 229 230 tmp = IsPat(); 231 if (debug) 232 document.write("<br>IsPat "+tmp); 233 if(tmp >= 0) { 234 curplace.b0 = tmp; /* leaf cell for 0-bit */ 235 if (debug) 236 document.write("<br>b0 "+curplace.b0); 237 } else { 238 /* Not a Leaf cell */ 239 curplace.b0 = 0x8000; 240 if (debug) 241 document.write("<br>b0 "+curplace.b0); 242 if(Rec()) 243 return -1; 244 } 245 tmp = IsPat(); 246 if(tmp >= 0) { 247 curplace.b1 = tmp; /* leaf cell for 1-bit */ 248 if (debug) 249 document.write("<br>b1 "+curplace.b1); 250 curplace.jump = null; /* Just for the display routine */ 251 } else { 252 /* Not a Leaf cell */ 253 curplace.b1 = 0x8000; 254 if (debug) 255 document.write("<br>b1 "+curplace.b1); 256 curplace.jump = Places[treepos]; 257 curplace.jumppos = treepos; 258 if(Rec()) 259 return -1; 260 } 261 len--; 262 return 0; 263 }; 264 265 function CreateTree(currentTree, numval, lengths, show) { 266 var i; 267 /* Create the Huffman decode tree/table */ 268 //document.write("<br>createtree<br>"); 269 if (debug) 270 document.write("currentTree "+currentTree+" numval "+numval+" lengths "+lengths+" show "+show); 271 Places = currentTree; 272 treepos=0; 273 flens = lengths; 274 fmax = numval; 275 for (i=0;i<17;i++) 276 fpos[i] = 0; 277 len = 0; 278 if(Rec()) { 279 //fprintf(stderr, "invalid huffman tree\n"); 280 if (debug) 281 alert("invalid huffman tree\n"); 282 return -1; 283 } 284 if (debug){ 285 document.write('<br>Tree: '+Places.length); 286 for (var a=0;a<32;a++){ 287 document.write("Places["+a+"].b0="+Places[a].b0+"<br>"); 288 document.write("Places["+a+"].b1="+Places[a].b1+"<br>"); 289 } 290 } 291 292 /*if(show) { 293 var tmp; 294 for(tmp=currentTree;tmp<Places;tmp++) { 295 fprintf(stdout, "0x%03x 0x%03x (0x%04x)",tmp-currentTree, tmp->jump?tmp->jump-currentTree:0,(tmp->jump?tmp->jump-currentTree:0)*6+0xcf0); 296 if(!(tmp.b0 & 0x8000)) { 297 //fprintf(stdout, " 0x%03x (%c)", tmp->b0,(tmp->b0<256 && isprint(tmp->b0))?tmp->b0:'�'); 298 } 299 if(!(tmp.b1 & 0x8000)) { 300 if((tmp.b0 & 0x8000)) 301 fprintf(stdout, " "); 302 fprintf(stdout, " 0x%03x (%c)", tmp->b1,(tmp->b1<256 && isprint(tmp->b1))?tmp->b1:'�'); 303 } 304 fprintf(stdout, "\n"); 305 } 306 }*/ 307 return 0; 308 }; 309 310 function DecodeValue(currentTree) { 311 var len, i, 312 xtreepos=0, 313 X = currentTree[xtreepos], 314 b; 315 316 /* decode one symbol of the data */ 317 while(1) { 318 b=readBit(); 319 if (debug) 320 document.write("b="+b); 321 if(b) { 322 if(!(X.b1 & 0x8000)){ 323 if (debug) 324 document.write("ret1"); 325 return X.b1; /* If leaf node, return data */ 326 } 327 X = X.jump; 328 len = currentTree.length; 329 for (i=0;i<len;i++){ 330 if (currentTree[i]===X){ 331 xtreepos=i; 332 break; 333 } 334 } 335 //xtreepos++; 336 } else { 337 if(!(X.b0 & 0x8000)){ 338 if (debug) 339 document.write("ret2"); 340 return X.b0; /* If leaf node, return data */ 341 } 342 //X++; //?????????????????? 343 xtreepos++; 344 X = currentTree[xtreepos]; 345 } 346 } 347 if (debug) 348 document.write("ret3"); 349 return -1; 350 }; 351 352 function DeflateLoop() { 353 var last, c, type, i, len; 354 355 do { 356 /*if((last = readBit())){ 357 fprintf(errfp, "Last Block: "); 358 } else { 359 fprintf(errfp, "Not Last Block: "); 360 }*/ 361 last = readBit(); 362 type = readBits(2); 363 switch(type) { 364 case 0: 365 if (debug) 366 alert("Stored\n"); 367 break; 368 case 1: 369 if (debug) 370 alert("Fixed Huffman codes\n"); 371 break; 372 case 2: 373 if (debug) 374 alert("Dynamic Huffman codes\n"); 375 break; 376 case 3: 377 if (debug) 378 alert("Reserved block type!!\n"); 379 break; 380 default: 381 if (debug) 382 alert("Unexpected value %d!\n", type); 383 break; 384 } 385 386 if(type==0) { 387 var blockLen, cSum; 388 389 // Stored 390 byteAlign(); 391 blockLen = readByte(); 392 blockLen |= (readByte()<<8); 393 394 cSum = readByte(); 395 cSum |= (readByte()<<8); 396 397 if(((blockLen ^ ~cSum) & 0xffff)) { 398 document.write("BlockLen checksum mismatch\n"); 399 } 400 while(blockLen--) { 401 c = readByte(); 402 addBuffer(c); 403 } 404 } else if(type==1) { 405 var j; 406 407 /* Fixed Huffman tables -- fixed decode routine */ 408 while(1) { 409 /* 410 256 0000000 0 411 : : : 412 279 0010111 23 413 0 00110000 48 414 : : : 415 143 10111111 191 416 280 11000000 192 417 : : : 418 287 11000111 199 419 144 110010000 400 420 : : : 421 255 111111111 511 422 423 Note the bit order! 424 */ 425 426 j = (bitReverse[readBits(7)]>>1); 427 if(j > 23) { 428 j = (j<<1) | readBit(); /* 48..255 */ 429 430 if(j > 199) { /* 200..255 */ 431 j -= 128; /* 72..127 */ 432 j = (j<<1) | readBit(); /* 144..255 << */ 433 } else { /* 48..199 */ 434 j -= 48; /* 0..151 */ 435 if(j > 143) { 436 j = j+136; /* 280..287 << */ 437 /* 0..143 << */ 438 } 439 } 440 } else { /* 0..23 */ 441 j += 256; /* 256..279 << */ 442 } 443 if(j < 256) { 444 addBuffer(j); 445 //document.write("out:"+String.fromCharCode(j)); 446 /*fprintf(errfp, "@%d %02x\n", SIZE, j);*/ 447 } else if(j == 256) { 448 /* EOF */ 449 break; 450 } else { 451 var len, dist; 452 453 j -= 256 + 1; /* bytes + EOF */ 454 len = readBits(cplext[j]) + cplens[j]; 455 456 j = bitReverse[readBits(5)]>>3; 457 if(cpdext[j] > 8) { 458 dist = readBits(8); 459 dist |= (readBits(cpdext[j]-8)<<8); 460 } else { 461 dist = readBits(cpdext[j]); 462 } 463 dist += cpdist[j]; 464 465 /*fprintf(errfp, "@%d (l%02x,d%04x)\n", SIZE, len, dist);*/ 466 for(j=0;j<len;j++) { 467 var c = buf32k[(bIdx - dist) & 0x7fff]; 468 addBuffer(c); 469 } 470 } 471 } // while 472 } else if(type==2) { 473 var j, n, literalCodes, distCodes, lenCodes; 474 var ll = new Array(288+32); // "static" just to preserve stack 475 476 // Dynamic Huffman tables 477 478 literalCodes = 257 + readBits(5); 479 distCodes = 1 + readBits(5); 480 lenCodes = 4 + readBits(4); 481 //document.write("<br>param: "+literalCodes+" "+distCodes+" "+lenCodes+"<br>"); 482 for(j=0; j<19; j++) { 483 ll[j] = 0; 484 } 485 486 // Get the decode tree code lengths 487 488 //document.write("<br>"); 489 for(j=0; j<lenCodes; j++) { 490 ll[border[j]] = readBits(3); 491 //document.write(ll[border[j]]+" "); 492 } 493 //fprintf(errfp, "\n"); 494 //document.write('<br>ll:'+ll); 495 len = distanceTree.length; 496 for (i=0; i<len; i++) 497 distanceTree[i]=new HufNode(); 498 if(CreateTree(distanceTree, 19, ll, 0)) { 499 flushBuffer(); 500 return 1; 501 } 502 if (debug){ 503 document.write("<br>distanceTree"); 504 for(var a=0;a<distanceTree.length;a++){ 505 document.write("<br>"+distanceTree[a].b0+" "+distanceTree[a].b1+" "+distanceTree[a].jump+" "+distanceTree[a].jumppos); 506 /*if (distanceTree[a].jumppos!=-1) 507 document.write(" "+distanceTree[a].jump.b0+" "+distanceTree[a].jump.b1); 508 */ 509 } 510 } 511 //document.write('<BR>tree created'); 512 513 //read in literal and distance code lengths 514 n = literalCodes + distCodes; 515 i = 0; 516 var z=-1; 517 if (debug) 518 document.write("<br>n="+n+" bits: "+bits+"<br>"); 519 while(i < n) { 520 z++; 521 j = DecodeValue(distanceTree); 522 if (debug) 523 document.write("<br>"+z+" i:"+i+" decode: "+j+" bits "+bits+"<br>"); 524 if(j<16) { // length of code in bits (0..15) 525 ll[i++] = j; 526 } else if(j==16) { // repeat last length 3 to 6 times 527 var l; 528 j = 3 + readBits(2); 529 if(i+j > n) { 530 flushBuffer(); 531 return 1; 532 } 533 l = i ? ll[i-1] : 0; 534 while(j--) { 535 ll[i++] = l; 536 } 537 } else { 538 if(j==17) { // 3 to 10 zero length codes 539 j = 3 + readBits(3); 540 } else { // j == 18: 11 to 138 zero length codes 541 j = 11 + readBits(7); 542 } 543 if(i+j > n) { 544 flushBuffer(); 545 return 1; 546 } 547 while(j--) { 548 ll[i++] = 0; 549 } 550 } 551 } 552 /*for(j=0; j<literalCodes+distCodes; j++) { 553 //fprintf(errfp, "%d ", ll[j]); 554 if ((j&7)==7) 555 fprintf(errfp, "\n"); 556 } 557 fprintf(errfp, "\n");*/ 558 // Can overwrite tree decode tree as it is not used anymore 559 len = literalTree.length; 560 for (i=0; i<len; i++) 561 literalTree[i]=new HufNode(); 562 if(CreateTree(literalTree, literalCodes, ll, 0)) { 563 flushBuffer(); 564 return 1; 565 } 566 len = literalTree.length; 567 for (i=0; i<len; i++) 568 distanceTree[i]=new HufNode(); 569 var ll2 = new Array(); 570 for (i=literalCodes; i <ll.length; i++){ 571 ll2[i-literalCodes]=ll[i]; 572 } 573 if(CreateTree(distanceTree, distCodes, ll2, 0)) { 574 flushBuffer(); 575 return 1; 576 } 577 if (debug) 578 document.write("<br>literalTree"); 579 while(1) { 580 j = DecodeValue(literalTree); 581 if(j >= 256) { // In C64: if carry set 582 var len, dist; 583 j -= 256; 584 if(j == 0) { 585 // EOF 586 break; 587 } 588 j--; 589 len = readBits(cplext[j]) + cplens[j]; 590 591 j = DecodeValue(distanceTree); 592 if(cpdext[j] > 8) { 593 dist = readBits(8); 594 dist |= (readBits(cpdext[j]-8)<<8); 595 } else { 596 dist = readBits(cpdext[j]); 597 } 598 dist += cpdist[j]; 599 while(len--) { 600 var c = buf32k[(bIdx - dist) & 0x7fff]; 601 addBuffer(c); 602 } 603 } else { 604 addBuffer(j); 605 } 606 } 607 } 608 } while(!last); 609 flushBuffer(); 610 611 byteAlign(); 612 return 0; 613 }; 614 615 JXG.Util.Unzip.prototype.unzipFile = function(name) { 616 var i; 617 this.unzip(); 618 //alert(unzipped[0][1]); 619 for (i=0;i<unzipped.length;i++){ 620 if(unzipped[i][1]==name) { 621 return unzipped[i][0]; 622 } 623 } 624 625 }; 626 627 628 JXG.Util.Unzip.prototype.unzip = function() { 629 //convertToByteArray(input); 630 if (debug) 631 alert(bA); 632 /*for (i=0;i<bA.length*8;i++){ 633 document.write(readBit()); 634 if ((i+1)%8==0) 635 document.write(" "); 636 }*/ 637 /*for (i=0;i<bA.length;i++){ 638 document.write(readByte()+" "); 639 if ((i+1)%8==0) 640 document.write(" "); 641 } 642 for (i=0;i<bA.length;i++){ 643 document.write(bA[i]+" "); 644 if ((i+1)%16==0) 645 document.write("<br>"); 646 } 647 */ 648 //alert(bA); 649 nextFile(); 650 return unzipped; 651 }; 652 653 function nextFile(){ 654 if (debug) 655 alert("NEXTFILE"); 656 outputArr = []; 657 var tmp = []; 658 modeZIP = false; 659 tmp[0] = readByte(); 660 tmp[1] = readByte(); 661 if (debug) 662 alert("type: "+tmp[0]+" "+tmp[1]); 663 if (tmp[0] == parseInt("78",16) && tmp[1] == parseInt("da",16)){ //GZIP 664 if (debug) 665 alert("GEONExT-GZIP"); 666 DeflateLoop(); 667 if (debug) 668 alert(outputArr.join('')); 669 unzipped[files] = new Array(2); 670 unzipped[files][0] = outputArr.join(''); 671 unzipped[files][1] = "geonext.gxt"; 672 files++; 673 } 674 if (tmp[0] == parseInt("1f",16) && tmp[1] == parseInt("8b",16)){ //GZIP 675 if (debug) 676 alert("GZIP"); 677 //DeflateLoop(); 678 skipdir(); 679 if (debug) 680 alert(outputArr.join('')); 681 unzipped[files] = new Array(2); 682 unzipped[files][0] = outputArr.join(''); 683 unzipped[files][1] = "file"; 684 files++; 685 } 686 if (tmp[0] == parseInt("50",16) && tmp[1] == parseInt("4b",16)){ //ZIP 687 modeZIP = true; 688 tmp[2] = readByte(); 689 tmp[3] = readByte(); 690 if (tmp[2] == parseInt("3",16) && tmp[3] == parseInt("4",16)){ 691 //MODE_ZIP 692 tmp[0] = readByte(); 693 tmp[1] = readByte(); 694 if (debug) 695 alert("ZIP-Version: "+tmp[1]+" "+tmp[0]/10+"."+tmp[0]%10); 696 697 gpflags = readByte(); 698 gpflags |= (readByte()<<8); 699 if (debug) 700 alert("gpflags: "+gpflags); 701 702 var method = readByte(); 703 method |= (readByte()<<8); 704 if (debug) 705 alert("method: "+method); 706 707 readByte(); 708 readByte(); 709 readByte(); 710 readByte(); 711 712 var crc = readByte(); 713 crc |= (readByte()<<8); 714 crc |= (readByte()<<16); 715 crc |= (readByte()<<24); 716 717 var compSize = readByte(); 718 compSize |= (readByte()<<8); 719 compSize |= (readByte()<<16); 720 compSize |= (readByte()<<24); 721 722 var size = readByte(); 723 size |= (readByte()<<8); 724 size |= (readByte()<<16); 725 size |= (readByte()<<24); 726 727 if (debug) 728 alert("local CRC: "+crc+"\nlocal Size: "+size+"\nlocal CompSize: "+compSize); 729 730 var filelen = readByte(); 731 filelen |= (readByte()<<8); 732 733 var extralen = readByte(); 734 extralen |= (readByte()<<8); 735 736 if (debug) 737 alert("filelen "+filelen); 738 i = 0; 739 nameBuf = []; 740 while (filelen--){ 741 var c = readByte(); 742 if (c == "/" | c ==":"){ 743 i = 0; 744 } else if (i < NAMEMAX-1) 745 nameBuf[i++] = String.fromCharCode(c); 746 } 747 if (debug) 748 alert("nameBuf: "+nameBuf); 749 750 //nameBuf[i] = "\0"; 751 if (!fileout) 752 fileout = nameBuf; 753 754 var i = 0; 755 while (i < extralen){ 756 c = readByte(); 757 i++; 758 } 759 760 CRC = 0xffffffff; 761 SIZE = 0; 762 763 if (size = 0 && fileOut.charAt(fileout.length-1)=="/"){ 764 //skipdir 765 if (debug) 766 alert("skipdir"); 767 } 768 if (method == 8){ 769 DeflateLoop(); 770 if (debug) 771 alert(outputArr.join('')); 772 unzipped[files] = new Array(2); 773 unzipped[files][0] = outputArr.join(''); 774 unzipped[files][1] = nameBuf.join(''); 775 files++; 776 //return outputArr.join(''); 777 } 778 skipdir(); 779 } 780 } 781 }; 782 783 function skipdir(){ 784 var crc, 785 tmp = [], 786 compSize, size, os, i, c; 787 788 if ((gpflags & 8)) { 789 tmp[0] = readByte(); 790 tmp[1] = readByte(); 791 tmp[2] = readByte(); 792 tmp[3] = readByte(); 793 794 if (tmp[0] == parseInt("50",16) && 795 tmp[1] == parseInt("4b",16) && 796 tmp[2] == parseInt("07",16) && 797 tmp[3] == parseInt("08",16)) 798 { 799 crc = readByte(); 800 crc |= (readByte()<<8); 801 crc |= (readByte()<<16); 802 crc |= (readByte()<<24); 803 } else { 804 crc = tmp[0] | (tmp[1]<<8) | (tmp[2]<<16) | (tmp[3]<<24); 805 } 806 807 compSize = readByte(); 808 compSize |= (readByte()<<8); 809 compSize |= (readByte()<<16); 810 compSize |= (readByte()<<24); 811 812 size = readByte(); 813 size |= (readByte()<<8); 814 size |= (readByte()<<16); 815 size |= (readByte()<<24); 816 817 if (debug) 818 alert("CRC:"); 819 } 820 821 if (modeZIP) 822 nextFile(); 823 824 tmp[0] = readByte(); 825 if (tmp[0] != 8) { 826 if (debug) 827 alert("Unknown compression method!"); 828 return 0; 829 } 830 831 gpflags = readByte(); 832 if (debug){ 833 if ((gpflags & ~(parseInt("1f",16)))) 834 alert("Unknown flags set!"); 835 } 836 837 readByte(); 838 readByte(); 839 readByte(); 840 readByte(); 841 842 readByte(); 843 os = readByte(); 844 845 if ((gpflags & 4)){ 846 tmp[0] = readByte(); 847 tmp[2] = readByte(); 848 len = tmp[0] + 256*tmp[1]; 849 if (debug) 850 alert("Extra field size: "+len); 851 for (i=0;i<len;i++) 852 readByte(); 853 } 854 855 if ((gpflags & 8)){ 856 i=0; 857 nameBuf=[]; 858 while (c=readByte()){ 859 if(c == "7" || c == ":") 860 i=0; 861 if (i<NAMEMAX-1) 862 nameBuf[i++] = c; 863 } 864 //nameBuf[i] = "\0"; 865 if (debug) 866 alert("original file name: "+nameBuf); 867 } 868 869 if ((gpflags & 16)){ 870 while (c=readByte()){ 871 //FILE COMMENT 872 } 873 } 874 875 if ((gpflags & 2)){ 876 readByte(); 877 readByte(); 878 } 879 880 DeflateLoop(); 881 882 crc = readByte(); 883 crc |= (readByte()<<8); 884 crc |= (readByte()<<16); 885 crc |= (readByte()<<24); 886 887 size = readByte(); 888 size |= (readByte()<<8); 889 size |= (readByte()<<16); 890 size |= (readByte()<<24); 891 892 if (modeZIP) 893 nextFile(); 894 895 }; 896 897 }; 898 899 /** 900 * Base64 encoding / decoding 901 * @see <a href="http://www.webtoolkit.info/">http://www.webtoolkit.info/</A> 902 */ 903 JXG.Util.Base64 = { 904 905 // private property 906 _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", 907 908 // public method for encoding 909 encode : function (input) { 910 var output = [], 911 chr1, chr2, chr3, enc1, enc2, enc3, enc4, 912 i = 0; 913 914 input = JXG.Util.Base64._utf8_encode(input); 915 916 while (i < input.length) { 917 918 chr1 = input.charCodeAt(i++); 919 chr2 = input.charCodeAt(i++); 920 chr3 = input.charCodeAt(i++); 921 922 enc1 = chr1 >> 2; 923 enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); 924 enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); 925 enc4 = chr3 & 63; 926 927 if (isNaN(chr2)) { 928 enc3 = enc4 = 64; 929 } else if (isNaN(chr3)) { 930 enc4 = 64; 931 } 932 933 output.push([this._keyStr.charAt(enc1), 934 this._keyStr.charAt(enc2), 935 this._keyStr.charAt(enc3), 936 this._keyStr.charAt(enc4)].join('')); 937 } 938 939 return output.join(''); 940 }, 941 942 // public method for decoding 943 decode : function (input, utf8) { 944 var output = [], 945 chr1, chr2, chr3, 946 enc1, enc2, enc3, enc4, 947 i = 0; 948 949 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); 950 951 while (i < input.length) { 952 953 enc1 = this._keyStr.indexOf(input.charAt(i++)); 954 enc2 = this._keyStr.indexOf(input.charAt(i++)); 955 enc3 = this._keyStr.indexOf(input.charAt(i++)); 956 enc4 = this._keyStr.indexOf(input.charAt(i++)); 957 958 chr1 = (enc1 << 2) | (enc2 >> 4); 959 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); 960 chr3 = ((enc3 & 3) << 6) | enc4; 961 962 output.push(String.fromCharCode(chr1)); 963 964 if (enc3 != 64) { 965 output.push(String.fromCharCode(chr2)); 966 } 967 if (enc4 != 64) { 968 output.push(String.fromCharCode(chr3)); 969 } 970 } 971 972 output = output.join(''); 973 974 if (utf8) { 975 output = JXG.Util.Base64._utf8_decode(output); 976 } 977 return output; 978 979 }, 980 981 // private method for UTF-8 encoding 982 _utf8_encode : function (string) { 983 string = string.replace(/\r\n/g,"\n"); 984 var utftext = ""; 985 986 for (var n = 0; n < string.length; n++) { 987 988 var c = string.charCodeAt(n); 989 990 if (c < 128) { 991 utftext += String.fromCharCode(c); 992 } 993 else if((c > 127) && (c < 2048)) { 994 utftext += String.fromCharCode((c >> 6) | 192); 995 utftext += String.fromCharCode((c & 63) | 128); 996 } 997 else { 998 utftext += String.fromCharCode((c >> 12) | 224); 999 utftext += String.fromCharCode(((c >> 6) & 63) | 128); 1000 utftext += String.fromCharCode((c & 63) | 128); 1001 } 1002 1003 } 1004 1005 return utftext; 1006 }, 1007 1008 // private method for UTF-8 decoding 1009 _utf8_decode : function (utftext) { 1010 var string = [], 1011 i = 0, 1012 c = 0, c2 = 0, c3 = 0; 1013 1014 while ( i < utftext.length ) { 1015 c = utftext.charCodeAt(i); 1016 if (c < 128) { 1017 string.push(String.fromCharCode(c)); 1018 i++; 1019 } 1020 else if((c > 191) && (c < 224)) { 1021 c2 = utftext.charCodeAt(i+1); 1022 string.push(String.fromCharCode(((c & 31) << 6) | (c2 & 63))); 1023 i += 2; 1024 } 1025 else { 1026 c2 = utftext.charCodeAt(i+1); 1027 c3 = utftext.charCodeAt(i+2); 1028 string.push(String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63))); 1029 i += 3; 1030 } 1031 } 1032 return string.join(''); 1033 }, 1034 1035 _destrip: function (stripped, wrap){ 1036 var lines = [], lineno, i, 1037 destripped = []; 1038 1039 if (wrap==null) 1040 wrap = 76; 1041 1042 stripped.replace(/ /g, ""); 1043 lineno = stripped.length / wrap; 1044 for (i = 0; i < lineno; i++) 1045 lines[i]=stripped.substr(i * wrap, wrap); 1046 if (lineno != stripped.length / wrap) 1047 lines[lines.length]=stripped.substr(lineno * wrap, stripped.length-(lineno * wrap)); 1048 1049 for (i = 0; i < lines.length; i++) 1050 destripped.push(lines[i]); 1051 return destripped.join('\n'); 1052 }, 1053 1054 decodeAsArray: function (input){ 1055 var dec = this.decode(input), 1056 ar = [], i; 1057 for (i=0;i<dec.length;i++){ 1058 ar[i]=dec.charCodeAt(i); 1059 } 1060 return ar; 1061 }, 1062 1063 decodeGEONExT : function (input) { 1064 return decodeAsArray(destrip(input),false); 1065 } 1066 }; 1067 1068 /** 1069 * @private 1070 */ 1071 JXG.Util.asciiCharCodeAt = function(str,i){ 1072 var c = str.charCodeAt(i); 1073 if (c>255){ 1074 switch (c) { 1075 case 8364: c=128; 1076 break; 1077 case 8218: c=130; 1078 break; 1079 case 402: c=131; 1080 break; 1081 case 8222: c=132; 1082 break; 1083 case 8230: c=133; 1084 break; 1085 case 8224: c=134; 1086 break; 1087 case 8225: c=135; 1088 break; 1089 case 710: c=136; 1090 break; 1091 case 8240: c=137; 1092 break; 1093 case 352: c=138; 1094 break; 1095 case 8249: c=139; 1096 break; 1097 case 338: c=140; 1098 break; 1099 case 381: c=142; 1100 break; 1101 case 8216: c=145; 1102 break; 1103 case 8217: c=146; 1104 break; 1105 case 8220: c=147; 1106 break; 1107 case 8221: c=148; 1108 break; 1109 case 8226: c=149; 1110 break; 1111 case 8211: c=150; 1112 break; 1113 case 8212: c=151; 1114 break; 1115 case 732: c=152; 1116 break; 1117 case 8482: c=153; 1118 break; 1119 case 353: c=154; 1120 break; 1121 case 8250: c=155; 1122 break; 1123 case 339: c=156; 1124 break; 1125 case 382: c=158; 1126 break; 1127 case 376: c=159; 1128 break; 1129 default: 1130 break; 1131 } 1132 } 1133 return c; 1134 }; 1135 1136 /** 1137 * Decoding string into utf-8 1138 * @param {String} string to decode 1139 * @return {String} utf8 decoded string 1140 */ 1141 JXG.Util.utf8Decode = function(utftext) { 1142 var string = []; 1143 var i = 0; 1144 var c = 0, c1 = 0, c2 = 0, c3; 1145 if (!JXG.exists(utftext)) return ''; 1146 1147 while ( i < utftext.length ) { 1148 c = utftext.charCodeAt(i); 1149 1150 if (c < 128) { 1151 string.push(String.fromCharCode(c)); 1152 i++; 1153 } else if((c > 191) && (c < 224)) { 1154 c2 = utftext.charCodeAt(i+1); 1155 string.push(String.fromCharCode(((c & 31) << 6) | (c2 & 63))); 1156 i += 2; 1157 } else { 1158 c2 = utftext.charCodeAt(i+1); 1159 c3 = utftext.charCodeAt(i+2); 1160 string.push(String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63))); 1161 i += 3; 1162 } 1163 }; 1164 return string.join(''); 1165 }; 1166 1167 /** 1168 * Generate a random uuid. 1169 * http://www.broofa.com 1170 * mailto:robert@broofa.com 1171 * 1172 * Copyright (c) 2010 Robert Kieffer 1173 * Dual licensed under the MIT and GPL licenses. 1174 * 1175 * EXAMPLES: 1176 * >>> Math.uuid() 1177 * "92329D39-6F5C-4520-ABFC-AAB64544E172" 1178 */ 1179 JXG.Util.genUUID = function() { 1180 // Private array of chars to use 1181 var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''), 1182 uuid = new Array(36), rnd=0, r; 1183 1184 for (var i = 0; i < 36; i++) { 1185 if (i==8 || i==13 || i==18 || i==23) { 1186 uuid[i] = '-'; 1187 } else if (i==14) { 1188 uuid[i] = '4'; 1189 } else { 1190 if (rnd <= 0x02) rnd = 0x2000000 + (Math.random()*0x1000000)|0; 1191 r = rnd & 0xf; 1192 rnd = rnd >> 4; 1193 uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]; 1194 } 1195 } 1196 1197 return uuid.join(''); 1198 }; 1199