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