1 29 30 package com.caucho.quercus.lib.zlib; 31 32 import com.caucho.quercus.QuercusModuleException; 33 import com.caucho.quercus.annotation.NotNull; 34 import com.caucho.quercus.annotation.Optional; 35 import com.caucho.quercus.annotation.ReturnNullAsFalse; 36 import com.caucho.quercus.env.*; 37 import com.caucho.quercus.lib.file.BinaryInput; 38 import com.caucho.quercus.lib.file.BinaryOutput; 39 import com.caucho.quercus.lib.file.BinaryStream; 40 import com.caucho.quercus.lib.file.FileModule; 41 import com.caucho.quercus.module.AbstractQuercusModule; 42 import com.caucho.util.L10N; 43 import com.caucho.vfs.StreamImplOutputStream; 44 import com.caucho.vfs.TempBuffer; 45 import com.caucho.vfs.TempStream; 46 import com.caucho.vfs.WriteStream; 47 48 import java.io.IOException ; 49 import java.io.InputStream ; 50 import java.util.logging.Level ; 51 import java.util.logging.Logger ; 52 import java.util.zip.Adler32 ; 53 import java.util.zip.Deflater ; 54 import java.util.zip.Inflater ; 55 import java.util.zip.InflaterInputStream ; 56 57 60 public class ZlibModule extends AbstractQuercusModule { 61 private static final Logger log 62 = Logger.getLogger(ZlibModule.class.getName()); 63 private static final L10N L = new L10N(ZlibModule.class); 64 65 public static final int FORCE_GZIP = 0x1; 66 public static final int FORCE_DEFLATE = 0x2; 67 68 public String []getLoadedExtensions() 69 { 70 return new String [] { "zlib" }; 71 } 72 73 81 @ReturnNullAsFalse 82 public static BinaryStream gzopen(Env env, 83 String fileName, 84 String mode, 85 @Optional("false") boolean useIncludePath) 86 { 87 String filemode = getFileMode(mode); 88 int compressionLevel = getCompressionLevel(mode); 89 int compressionStrategy = getCompressionStrategy(mode); 90 91 Object val = FileModule.fopen(env, fileName, mode, useIncludePath, null); 92 93 if (val == null) 94 return null; 95 96 try { 97 int ch = filemode.charAt(0); 98 99 if (ch == 'r') { 100 BinaryInput is = (BinaryInput) val; 101 return new ZlibInputStream(is); 102 } 103 else if (ch == 'w') { 104 return new ZlibOutputStream(((BinaryOutput) val).getOutputStream(), 105 compressionLevel, 106 compressionStrategy); 107 } 108 else if (ch == 'a') { 109 return new ZlibOutputStream(((BinaryOutput) val).getOutputStream(), 110 compressionLevel, 111 compressionStrategy); 112 } 113 else if (ch == 'x') { 114 return new ZlibOutputStream(((BinaryOutput) val).getOutputStream(), 115 compressionLevel, 116 compressionStrategy); 117 } 118 } 119 catch (IOException e) { 120 log.log(Level.FINE, e.getMessage(), e); 121 env.warning(L.l(e.getMessage())); 122 } 123 124 return null; 125 } 126 127 134 @ReturnNullAsFalse 135 public static ArrayValue gzfile(Env env, 136 String fileName, 137 @Optional boolean useIncludePath) 138 { 139 BinaryInput is = (BinaryInput) gzopen(env, fileName, "r", useIncludePath); 140 141 if (is == null) 142 return null; 143 144 try { 145 ArrayValue result = new ArrayValueImpl(); 146 147 StringValue line; 148 while ((line = is.readLine(Integer.MAX_VALUE)) != null && 149 line.length() > 0) 150 result.put(line); 151 152 return result; 153 } catch (IOException e) { 154 throw new QuercusModuleException(e); 155 } finally { 156 is.close(); 157 } 158 } 159 160 170 public static Value readgzfile(Env env, 171 String fileName, 172 @Optional boolean useIncludePath) 173 { 174 BinaryInput is = (BinaryInput) gzopen(env, fileName, "r", useIncludePath); 175 176 if (is == null) 177 return BooleanValue.FALSE; 178 179 try { 180 return LongValue.create(env.getOut().writeStream(is.getInputStream())); 181 } catch (IOException e) { 182 throw new QuercusModuleException(e); 183 } finally { 184 is.close(); 185 } 186 } 187 188 191 public static int gzwrite(@NotNull BinaryOutput os, 192 InputStream is, 193 @Optional("0x7fffffff") int length) 194 { 195 if (os == null) 196 return 0; 197 198 try { 199 return os.write(is, length); 200 } catch (IOException e) { 201 throw new QuercusModuleException(e); 202 } 203 } 204 205 213 public int gzputs(Env env, 214 @NotNull BinaryOutput os, 215 InputStream is, 216 @Optional("0x7ffffff") int length) 217 { 218 if (os == null) 219 return 0; 220 221 try { 222 return os.write(is, length); 223 } catch (IOException e) { 224 throw new QuercusModuleException(e); 225 } 226 } 227 228 231 public boolean gzclose(@NotNull BinaryStream os) 232 { 233 if (os == null) 234 return false; 235 236 os.close(); 237 238 return true; 239 } 240 241 244 public boolean gzeof(@NotNull BinaryStream binaryStream) 245 { 246 if (binaryStream == null) 247 return true; 248 249 return binaryStream.isEOF(); 250 } 251 252 255 public static Value gzgetc(@NotNull BinaryInput is) 256 { 257 if (is == null) 258 return BooleanValue.FALSE; 259 260 try { 261 int ch = is.read(); 262 263 if (ch < 0) 264 return BooleanValue.FALSE; 265 else 266 return new BinaryBuilderValue(new byte[] { (byte) ch }); 267 } catch (IOException e) { 268 throw new QuercusModuleException(e); 269 } 270 } 271 272 275 @ReturnNullAsFalse 276 public BinaryValue gzread(@NotNull BinaryInput is, int length) 277 { 278 if (is == null) 279 return null; 280 281 try { 282 return is.read(length); 283 } catch (IOException e) { 284 throw new QuercusModuleException(e); 285 } 286 } 287 288 291 public static Value gzgets(Env env, 292 @NotNull BinaryInput is, 293 int length) 294 { 295 return FileModule.fgets(env, is, length); 296 } 297 298 301 public static Value gzgetss(Env env, 302 @NotNull BinaryInput is, 303 int length, 304 @Optional String allowedTags) 305 { 306 return FileModule.fgetss(env, is, length, allowedTags); 307 } 308 309 312 public boolean gzrewind(@NotNull BinaryStream binaryStream) 313 { 314 if (binaryStream == null) 315 return false; 316 317 return binaryStream.setPosition(0); 318 } 319 320 325 public int gzseek(@NotNull BinaryStream binaryStream, long offset) 326 { 327 if (binaryStream == null) 328 return -1; 329 if (binaryStream.setPosition(offset) == false) 330 return -1; 331 if (binaryStream.getPosition() != offset) 332 return -1; 333 334 return 0; 335 } 336 337 341 public Value gztell(@NotNull BinaryStream binaryStream) 342 { 343 if (binaryStream == null) 344 return BooleanValue.FALSE; 345 return new LongValue(binaryStream.getPosition()); 346 } 347 348 351 public Value gzpassthru(Env env, @NotNull BinaryInput is) 352 { 353 WriteStream out = env.getOut(); 354 TempBuffer tempBuf = TempBuffer.allocate(); 355 byte[] buffer = tempBuf.getBuffer(); 356 357 int length = 0; 358 try { 359 int sublen = is.read(buffer, 0, buffer.length); 360 while (sublen > 0) { 361 out.write(buffer, 0, sublen); 362 length += sublen; 363 sublen = is.read(buffer, 0, buffer.length); 364 } 365 366 return new LongValue(length); 367 368 } catch (IOException e) { 369 log.log(Level.FINE, e.toString(), e); 370 371 return BooleanValue.FALSE; 372 373 } finally { 374 TempBuffer.free(tempBuf); 375 } 376 } 377 378 382 public Value zlib_get_coding_type(Env env) 383 { 384 String ini = env.getIniString("zlib.output_compression"); 385 386 if (ini == null || ini == "") 387 return BooleanValue.FALSE; 388 389 if (! ini.equalsIgnoreCase("on")) { 391 int ch = ini.charAt(0); 392 393 if (ch < '0' || ch > '9') 394 return BooleanValue.FALSE; 395 } 396 397 ServerArrayValue sav = new ServerArrayValue(env); 398 Value val = sav.get(new StringValueImpl("HTTP_ACCEPT_ENCODING")); 399 400 if (!val.isset()) 401 return BooleanValue.FALSE; 402 403 String s = val.toString(); 404 if (s.contains("gzip")) 405 return new StringValueImpl("gzip"); 406 else if(s.contains("deflate")) 407 return new StringValueImpl("deflate"); 408 else 409 return BooleanValue.FALSE; 410 } 411 412 419 public Value gzcompress(InputStream data, 420 @Optional("6") int level) 421 { 422 TempBuffer tempBuf = TempBuffer.allocate(); 423 byte []buffer = tempBuf.getBuffer(); 424 425 try { 426 Deflater deflater = new Deflater (level, true); 427 Adler32 crc = new Adler32 (); 428 429 boolean isFinished = false; 430 TempStream out = new TempStream(); 431 432 buffer[0] = (byte) 0x78; 433 434 if (level <= 1) 435 buffer[1] = (byte) 0x01; 436 else if (level < 6) 437 buffer[1] = (byte) 0x5e; 438 else if (level == 6) 439 buffer[1] = (byte) 0x9c; 440 else 441 buffer[1] = (byte) 0xda; 442 443 out.write(buffer, 0, 2, false); 444 445 int len; 446 while (! isFinished) { 447 while (! isFinished && deflater.needsInput()) { 448 len = data.read(buffer, 0, buffer.length); 449 450 if (len > 0) { 451 crc.update(buffer, 0, len); 452 deflater.setInput(buffer, 0, len); 453 } 454 else { 455 isFinished = true; 456 deflater.finish(); 457 } 458 } 459 460 while ((len = deflater.deflate(buffer, 0, buffer.length)) > 0) { 461 out.write(buffer, 0, len, false); 462 } 463 } 464 465 long value = crc.getValue(); 466 467 buffer[0] = (byte) (value >> 24); 468 buffer[1] = (byte) (value >> 16); 469 buffer[2] = (byte) (value >> 8); 470 buffer[3] = (byte) (value >> 0); 471 472 out.write(buffer, 0, 4, true); 473 474 return new TempBufferStringValue(out.getHead()); 475 } catch (Exception e) { 476 throw QuercusModuleException.create(e); 477 } finally { 478 TempBuffer.free(tempBuf); 479 } 480 } 481 482 488 public Value gzuncompress(InputStream is, 489 @Optional("0") long length) 490 { 491 TempBuffer tempBuf = TempBuffer.allocate(); 492 byte []buffer = tempBuf.getBuffer(); 493 494 try { 495 if (length == 0) 496 length = Long.MAX_VALUE; 497 498 InflaterInputStream in = new InflaterInputStream (is); 499 TempStream out = new TempStream(); 500 501 502 503 int len; 504 while ((len = in.read(buffer, 0, buffer.length)) >= 0) { 505 out.write(buffer, 0, len, false); 506 } 507 508 in.close(); 509 510 return new TempBufferStringValue(out.getHead()); 511 } catch (Exception e) { 512 throw QuercusModuleException.create(e); 513 } finally { 514 TempBuffer.free(tempBuf); 515 } 516 } 517 518 private int _dbg; 519 520 525 public Value gzdeflate(InputStream data, 526 @Optional("6") int level) 527 { 528 TempBuffer tempBuf = TempBuffer.allocate(); 529 byte []buffer = tempBuf.getBuffer(); 530 531 try { 532 Deflater deflater = new Deflater (level, true); 533 534 boolean isFinished = false; 535 TempStream out = new TempStream(); 536 537 int len; 538 while (! isFinished) { 539 if (! isFinished && deflater.needsInput()) { 540 len = data.read(buffer, 0, buffer.length); 541 542 if (len > 0) 543 deflater.setInput(buffer, 0, len); 544 else { 545 isFinished = true; 546 deflater.finish(); 547 } 548 } 549 550 while ((len = deflater.deflate(buffer, 0, buffer.length)) > 0) { 551 out.write(buffer, 0, len, false); 552 } 553 } 554 deflater.end(); 555 556 return new TempBufferStringValue(out.getHead()); 557 558 } catch (Exception e) { 559 throw QuercusModuleException.create(e); 560 } finally { 561 TempBuffer.free(tempBuf); 562 } 563 } 564 565 571 public Value gzinflate(Env env, 572 InputStream data, 573 @Optional("0") long length) 574 { 575 TempBuffer tempBuf = TempBuffer.allocate(); 576 byte []buffer = tempBuf.getBuffer(); 577 578 try { 579 Inflater inflater = new Inflater (true); 580 581 boolean isFinished = false; 582 TempStream out = new TempStream(); 583 584 int len; 585 while (! isFinished) { 586 if (! isFinished && inflater.needsInput()) { 587 len = data.read(buffer, 0, buffer.length); 588 589 if (len > 0) { 590 inflater.setInput(buffer, 0, len); 591 } 592 else 593 isFinished = true; 594 } 595 596 while ((len = inflater.inflate(buffer, 0, buffer.length)) > 0) { 597 out.write(buffer, 0, len, false); 598 } 599 } 600 601 inflater.end(); 602 603 return new TempBufferStringValue(out.getHead()); 604 } catch (Exception e) { 605 env.warning(e); 606 return BooleanValue.FALSE; 607 } finally { 608 TempBuffer.free(tempBuf); 609 } 610 } 611 612 623 public Value gzencode(InputStream is, 624 @Optional("6") int level, 625 @Optional("1") int encodingMode) 626 { 627 TempBuffer tempBuf = TempBuffer.allocate(); 628 byte[] buffer = tempBuf.getBuffer(); 629 630 TempStream ts = new TempStream(); 631 StreamImplOutputStream out = new StreamImplOutputStream(ts); 632 633 try { 634 ZlibOutputStream gzOut; 635 636 gzOut = new ZlibOutputStream(out, level, 637 Deflater.DEFAULT_STRATEGY, 638 encodingMode); 639 640 int len; 641 while ((len = is.read(buffer, 0, buffer.length)) > 0) { 642 gzOut.write(buffer, 0, len); 643 } 644 gzOut.close(); 645 return new TempBufferStringValue(ts.getHead()); 646 647 } catch(IOException e) { 648 throw QuercusModuleException.create(e); 649 } finally { 650 TempBuffer.free(tempBuf); 651 } 652 } 653 654 662 private static String getFileMode(String input) 663 { 664 String modifier = ""; 665 String filemode = input.substring(0, 1); 666 667 for (int i = 1; i < input.length(); i++ ) 668 { 669 char ch = input.charAt(i); 670 switch (ch) { 671 case 'r': 672 filemode = "r"; 673 break; 674 case 'w': 675 filemode = "w"; 676 break; 677 case 'a': 678 filemode = "a"; 679 break; 680 case 'b': 681 modifier = "b"; 682 break; 683 case 't': 684 modifier = "t"; 685 break; 686 } 687 } 688 return filemode + modifier; 689 } 690 691 695 private static int getCompressionLevel(String input) 696 { 697 for (int i = input.length() - 1; i >= 0; i--) { 698 char ch = input.charAt(i); 699 700 if (ch >= '0' && ch <= '9') 701 return ch - '0'; 702 } 703 704 return Deflater.DEFAULT_COMPRESSION; 705 } 706 707 711 private static int getCompressionStrategy(String input) 712 { 713 for (int i = input.length() - 1; i >= 0; i--) { 714 char ch = input.charAt(i); 715 716 switch (ch) { 717 case 'f': 718 return Deflater.FILTERED; 719 720 case 'h': 721 return Deflater.HUFFMAN_ONLY; 722 } 723 } 724 725 return Deflater.DEFAULT_STRATEGY; 726 } 727 } 728 | Popular Tags |