Annotation of embedaddon/php/ext/zlib/zlib.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2012 The PHP Group |
! 6: +----------------------------------------------------------------------+
! 7: | This source file is subject to version 3.01 of the PHP license, |
! 8: | that is bundled with this package in the file LICENSE, and is |
! 9: | available through the world-wide-web at the following url: |
! 10: | http://www.php.net/license/3_01.txt |
! 11: | If you did not receive a copy of the PHP license and are unable to |
! 12: | obtain it through the world-wide-web, please send a note to |
! 13: | license@php.net so we can mail you a copy immediately. |
! 14: +----------------------------------------------------------------------+
! 15: | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
! 16: | Stefan Röhrich <sr@linux.de> |
! 17: | Zeev Suraski <zeev@zend.com> |
! 18: | Jade Nicoletti <nicoletti@nns.ch> |
! 19: +----------------------------------------------------------------------+
! 20: */
! 21:
! 22: /* $Id: zlib.c 321634 2012-01-01 13:15:04Z felipe $ */
! 23:
! 24: #ifdef HAVE_CONFIG_H
! 25: #include "config.h"
! 26: #endif
! 27:
! 28: #include "php.h"
! 29: #include "SAPI.h"
! 30: #include "php_ini.h"
! 31:
! 32: #include <stdlib.h>
! 33: #include <errno.h>
! 34: #include <sys/types.h>
! 35: #include <sys/stat.h>
! 36: #include <fcntl.h>
! 37:
! 38: #ifdef PHP_WIN32
! 39: # define O_RDONLY _O_RDONLY
! 40: # include "win32/param.h"
! 41: #else
! 42: # include <sys/param.h>
! 43: /* #include <sys/uio.h> */
! 44: #endif
! 45:
! 46: #include "ext/standard/head.h"
! 47: #include "safe_mode.h"
! 48: #include "ext/standard/php_standard.h"
! 49: #include "ext/standard/info.h"
! 50: #include "php_zlib.h"
! 51: #include "fopen_wrappers.h"
! 52:
! 53: #if HAVE_PWD_H
! 54: # ifdef PHP_WIN32
! 55: # include "win32/pwd.h"
! 56: # else
! 57: # include <pwd.h>
! 58: # endif
! 59: #endif
! 60:
! 61: #if defined(HAVE_UNISTD_H) && defined(PHP_WIN32)
! 62: # undef HAVE_UNISTD_H
! 63: #endif
! 64:
! 65: #ifdef COMPILE_DL_ZLIB
! 66: # ifndef PUTS
! 67: # define PUTS(a) php_printf("%s",a)
! 68: # endif
! 69: # ifndef PUTC
! 70: # define PUTC(a) PUTS(a)
! 71: # endif
! 72: # ifndef PHPWRITE
! 73: # define PHPWRITE(a,n) php_write((a),(n) TSRMLS_CC)
! 74: # endif
! 75: #endif
! 76:
! 77: /* Win32 needs some more memory */
! 78: #ifdef PHP_WIN32
! 79: # define PHP_ZLIB_MODIFIER 100
! 80: #else
! 81: # define PHP_ZLIB_MODIFIER 1000
! 82: #endif
! 83:
! 84: #define OS_CODE 0x03 /* FIXME */
! 85: #define GZIP_HEADER_LENGTH 10
! 86: #define GZIP_FOOTER_LENGTH 8
! 87:
! 88: /* True globals, no need for thread safety */
! 89: static const int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
! 90:
! 91: static int php_zlib_output_compression_start(TSRMLS_D);
! 92:
! 93: static PHP_MINIT_FUNCTION(zlib);
! 94: static PHP_MSHUTDOWN_FUNCTION(zlib);
! 95: static PHP_RINIT_FUNCTION(zlib);
! 96: static PHP_MINFO_FUNCTION(zlib);
! 97: static PHP_FUNCTION(gzopen);
! 98: static PHP_FUNCTION(readgzfile);
! 99: static PHP_FUNCTION(gzfile);
! 100: static PHP_FUNCTION(gzcompress);
! 101: static PHP_FUNCTION(gzuncompress);
! 102: static PHP_FUNCTION(gzdeflate);
! 103: static PHP_FUNCTION(gzinflate);
! 104: static PHP_FUNCTION(gzencode);
! 105: static PHP_FUNCTION(ob_gzhandler);
! 106: static PHP_FUNCTION(zlib_get_coding_type);
! 107:
! 108: /* {{{ arginfo */
! 109: ZEND_BEGIN_ARG_INFO_EX(arginfo_gzfile, 0, 0, 1)
! 110: ZEND_ARG_INFO(0, filename)
! 111: ZEND_ARG_INFO(0, use_include_path)
! 112: ZEND_END_ARG_INFO()
! 113:
! 114: ZEND_BEGIN_ARG_INFO_EX(arginfo_gzopen, 0, 0, 2)
! 115: ZEND_ARG_INFO(0, filename)
! 116: ZEND_ARG_INFO(0, mode)
! 117: ZEND_ARG_INFO(0, use_include_path)
! 118: ZEND_END_ARG_INFO()
! 119:
! 120: ZEND_BEGIN_ARG_INFO_EX(arginfo_readgzfile, 0, 0, 1)
! 121: ZEND_ARG_INFO(0, filename)
! 122: ZEND_ARG_INFO(0, use_include_path)
! 123: ZEND_END_ARG_INFO()
! 124:
! 125: ZEND_BEGIN_ARG_INFO_EX(arginfo_gzcompress, 0, 0, 1)
! 126: ZEND_ARG_INFO(0, data)
! 127: ZEND_ARG_INFO(0, level)
! 128: ZEND_END_ARG_INFO()
! 129:
! 130: ZEND_BEGIN_ARG_INFO_EX(arginfo_gzuncompress, 0, 0, 1)
! 131: ZEND_ARG_INFO(0, data)
! 132: ZEND_ARG_INFO(0, length)
! 133: ZEND_END_ARG_INFO()
! 134:
! 135: ZEND_BEGIN_ARG_INFO_EX(arginfo_gzdeflate, 0, 0, 1)
! 136: ZEND_ARG_INFO(0, data)
! 137: ZEND_ARG_INFO(0, level)
! 138: ZEND_END_ARG_INFO()
! 139:
! 140: ZEND_BEGIN_ARG_INFO_EX(arginfo_gzinflate, 0, 0, 1)
! 141: ZEND_ARG_INFO(0, data)
! 142: ZEND_ARG_INFO(0, length)
! 143: ZEND_END_ARG_INFO()
! 144:
! 145: ZEND_BEGIN_ARG_INFO(arginfo_zlib_get_coding_type, 0)
! 146: ZEND_END_ARG_INFO()
! 147:
! 148: ZEND_BEGIN_ARG_INFO_EX(arginfo_gzencode, 0, 0, 1)
! 149: ZEND_ARG_INFO(0, data)
! 150: ZEND_ARG_INFO(0, level)
! 151: ZEND_ARG_INFO(0, encoding_mode)
! 152: ZEND_END_ARG_INFO()
! 153:
! 154: ZEND_BEGIN_ARG_INFO_EX(arginfo_ob_gzhandler, 0, 0, 2)
! 155: ZEND_ARG_INFO(0, str)
! 156: ZEND_ARG_INFO(0, mode)
! 157: ZEND_END_ARG_INFO()
! 158:
! 159: ZEND_BEGIN_ARG_INFO_EX(arginfo_gzputs, 0, 0, 2)
! 160: ZEND_ARG_INFO(0, fp)
! 161: ZEND_ARG_INFO(0, str)
! 162: ZEND_ARG_INFO(0, length)
! 163: ZEND_END_ARG_INFO()
! 164:
! 165: ZEND_BEGIN_ARG_INFO(arginfo_gzpassthru, 0)
! 166: ZEND_ARG_INFO(0, fp)
! 167: ZEND_END_ARG_INFO()
! 168:
! 169: ZEND_BEGIN_ARG_INFO_EX(arginfo_gzseek, 0, 0, 2)
! 170: ZEND_ARG_INFO(0, fp)
! 171: ZEND_ARG_INFO(0, offset)
! 172: ZEND_ARG_INFO(0, whence)
! 173: ZEND_END_ARG_INFO()
! 174:
! 175: ZEND_BEGIN_ARG_INFO(arginfo_gzread, 0)
! 176: ZEND_ARG_INFO(0, fp)
! 177: ZEND_ARG_INFO(0, length)
! 178: ZEND_END_ARG_INFO()
! 179:
! 180: ZEND_BEGIN_ARG_INFO_EX(arginfo_gzgetss, 0, 0, 1)
! 181: ZEND_ARG_INFO(0, fp)
! 182: ZEND_ARG_INFO(0, length)
! 183: ZEND_ARG_INFO(0, allowable_tags)
! 184: ZEND_END_ARG_INFO()
! 185:
! 186: ZEND_BEGIN_ARG_INFO_EX(arginfo_gzgets, 0, 0, 1)
! 187: ZEND_ARG_INFO(0, fp)
! 188: ZEND_ARG_INFO(0, length)
! 189: ZEND_END_ARG_INFO()
! 190: /* }}} */
! 191:
! 192: /* {{{ php_zlib_functions[]
! 193: */
! 194: static const zend_function_entry php_zlib_functions[] = {
! 195: PHP_FE(readgzfile, arginfo_readgzfile)
! 196: PHP_FALIAS(gzrewind, rewind, arginfo_gzpassthru)
! 197: PHP_FALIAS(gzclose, fclose, arginfo_gzpassthru)
! 198: PHP_FALIAS(gzeof, feof, arginfo_gzpassthru)
! 199: PHP_FALIAS(gzgetc, fgetc, arginfo_gzpassthru)
! 200: PHP_FALIAS(gzgets, fgets, arginfo_gzgets)
! 201: PHP_FALIAS(gzgetss, fgetss, arginfo_gzgetss)
! 202: PHP_FALIAS(gzread, fread, arginfo_gzread)
! 203: PHP_FE(gzopen, arginfo_gzopen)
! 204: PHP_FALIAS(gzpassthru, fpassthru, arginfo_gzpassthru)
! 205: PHP_FALIAS(gzseek, fseek, arginfo_gzseek)
! 206: PHP_FALIAS(gztell, ftell, arginfo_gzpassthru)
! 207: PHP_FALIAS(gzwrite, fwrite, arginfo_gzputs)
! 208: PHP_FALIAS(gzputs, fwrite, arginfo_gzputs)
! 209: PHP_FE(gzfile, arginfo_gzfile)
! 210: PHP_FE(gzcompress, arginfo_gzcompress)
! 211: PHP_FE(gzuncompress, arginfo_gzuncompress)
! 212: PHP_FE(gzdeflate, arginfo_gzdeflate)
! 213: PHP_FE(gzinflate, arginfo_gzinflate)
! 214: PHP_FE(gzencode, arginfo_gzencode)
! 215: PHP_FE(ob_gzhandler, arginfo_ob_gzhandler)
! 216: PHP_FE(zlib_get_coding_type, arginfo_zlib_get_coding_type)
! 217: PHP_FE_END
! 218: };
! 219: /* }}} */
! 220:
! 221: ZEND_DECLARE_MODULE_GLOBALS(zlib)
! 222:
! 223: /* {{{ php_zlib_module_entry
! 224: */
! 225: zend_module_entry php_zlib_module_entry = {
! 226: STANDARD_MODULE_HEADER,
! 227: "zlib",
! 228: php_zlib_functions,
! 229: PHP_MINIT(zlib),
! 230: PHP_MSHUTDOWN(zlib),
! 231: PHP_RINIT(zlib),
! 232: NULL,
! 233: PHP_MINFO(zlib),
! 234: "1.1",
! 235: PHP_MODULE_GLOBALS(zlib),
! 236: NULL,
! 237: NULL,
! 238: NULL,
! 239: STANDARD_MODULE_PROPERTIES_EX
! 240: };
! 241: /* }}} */
! 242:
! 243: #ifdef COMPILE_DL_ZLIB
! 244: ZEND_GET_MODULE(php_zlib)
! 245: #endif
! 246:
! 247: /* {{{ Memory management wrappers */
! 248:
! 249: static voidpf php_zlib_alloc(voidpf opaque, uInt items, uInt size)
! 250: {
! 251: return (voidpf)safe_emalloc(items, size, 0);
! 252: }
! 253:
! 254: static void php_zlib_free(voidpf opaque, voidpf address)
! 255: {
! 256: efree((void*)address);
! 257: }
! 258: /* }}} */
! 259:
! 260: /* {{{ OnUpdate_zlib_output_compression */
! 261: static PHP_INI_MH(OnUpdate_zlib_output_compression)
! 262: {
! 263: int status, int_value;
! 264: char *ini_value;
! 265:
! 266: if (new_value == NULL) {
! 267: return FAILURE;
! 268: }
! 269:
! 270: if (!strncasecmp(new_value, "off", sizeof("off"))) {
! 271: new_value = "0";
! 272: new_value_length = sizeof("0");
! 273: } else if (!strncasecmp(new_value, "on", sizeof("on"))) {
! 274: new_value = "1";
! 275: new_value_length = sizeof("1");
! 276: }
! 277:
! 278: int_value = zend_atoi(new_value, new_value_length);
! 279: ini_value = zend_ini_string("output_handler", sizeof("output_handler"), 0);
! 280:
! 281: if (ini_value && *ini_value && int_value) {
! 282: php_error_docref("ref.outcontrol" TSRMLS_CC, E_CORE_ERROR, "Cannot use both zlib.output_compression and output_handler together!!");
! 283: return FAILURE;
! 284: }
! 285:
! 286: if (stage == PHP_INI_STAGE_RUNTIME && SG(headers_sent) && !SG(request_info).no_headers) {
! 287: php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "Cannot change zlib.output_compression - headers already sent");
! 288: return FAILURE;
! 289: }
! 290:
! 291: status = OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
! 292:
! 293: if (stage == PHP_INI_STAGE_RUNTIME && int_value) {
! 294: status = php_zlib_output_compression_start(TSRMLS_C);
! 295: }
! 296:
! 297: return status;
! 298: }
! 299: /* }}} */
! 300:
! 301: /* {{{ OnUpdate_zlib_output_compression_level */
! 302: static PHP_INI_MH(OnUpdate_zlib_output_compression_level)
! 303: {
! 304: OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
! 305:
! 306: return SUCCESS;
! 307: }
! 308: /* }}} */
! 309:
! 310: /* {{{ OnUpdate_zlib_output_handler */
! 311: static PHP_INI_MH(OnUpdate_zlib_output_handler)
! 312: {
! 313: if (stage == PHP_INI_STAGE_RUNTIME && SG(headers_sent) && !SG(request_info).no_headers) {
! 314: php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "Cannot change zlib.output_handler - headers already sent");
! 315: return FAILURE;
! 316: }
! 317:
! 318: OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
! 319:
! 320: return SUCCESS;
! 321: }
! 322: /* }}} */
! 323:
! 324:
! 325: PHP_INI_BEGIN()
! 326: STD_PHP_INI_BOOLEAN("zlib.output_compression", "0", PHP_INI_ALL, OnUpdate_zlib_output_compression, output_compression, zend_zlib_globals, zlib_globals)
! 327: STD_PHP_INI_ENTRY("zlib.output_compression_level", "-1", PHP_INI_ALL, OnUpdate_zlib_output_compression_level, output_compression_level, zend_zlib_globals, zlib_globals)
! 328: STD_PHP_INI_ENTRY("zlib.output_handler", "", PHP_INI_ALL, OnUpdate_zlib_output_handler, output_handler, zend_zlib_globals, zlib_globals)
! 329: PHP_INI_END()
! 330:
! 331: /* {{{ PHP_MINIT_FUNCTION
! 332: */
! 333: static PHP_MINIT_FUNCTION(zlib)
! 334: {
! 335: php_register_url_stream_wrapper("compress.zlib", &php_stream_gzip_wrapper TSRMLS_CC);
! 336: php_stream_filter_register_factory("zlib.*", &php_zlib_filter_factory TSRMLS_CC);
! 337:
! 338: REGISTER_LONG_CONSTANT("FORCE_GZIP", CODING_GZIP, CONST_CS | CONST_PERSISTENT);
! 339: REGISTER_LONG_CONSTANT("FORCE_DEFLATE", CODING_DEFLATE, CONST_CS | CONST_PERSISTENT);
! 340:
! 341: REGISTER_INI_ENTRIES();
! 342:
! 343: return SUCCESS;
! 344: }
! 345: /* }}} */
! 346:
! 347: /* {{{ PHP_RINIT_FUNCTION
! 348: */
! 349: static PHP_RINIT_FUNCTION(zlib)
! 350: {
! 351: ZLIBG(ob_gzhandler_status) = 0;
! 352: ZLIBG(compression_coding) = 0;
! 353:
! 354: php_zlib_output_compression_start(TSRMLS_C);
! 355:
! 356: return SUCCESS;
! 357: }
! 358: /* }}} */
! 359:
! 360: /* {{{ PHP_MSHUTDOWN_FUNCTION
! 361: */
! 362: static PHP_MSHUTDOWN_FUNCTION(zlib)
! 363: {
! 364: php_unregister_url_stream_wrapper("zlib" TSRMLS_CC);
! 365: php_stream_filter_unregister_factory("zlib.*" TSRMLS_CC);
! 366:
! 367: UNREGISTER_INI_ENTRIES();
! 368:
! 369: return SUCCESS;
! 370: }
! 371: /* }}} */
! 372:
! 373: /* {{{ PHP_MINFO_FUNCTION
! 374: */
! 375: static PHP_MINFO_FUNCTION(zlib)
! 376: {
! 377: php_info_print_table_start();
! 378: php_info_print_table_row(2, "ZLib Support", "enabled");
! 379: php_info_print_table_row(2, "Stream Wrapper support", "compress.zlib://");
! 380: php_info_print_table_row(2, "Stream Filter support", "zlib.inflate, zlib.deflate");
! 381: php_info_print_table_row(2, "Compiled Version", ZLIB_VERSION);
! 382: php_info_print_table_row(2, "Linked Version", (char *) zlibVersion());
! 383: php_info_print_table_end();
! 384:
! 385: DISPLAY_INI_ENTRIES();
! 386: }
! 387: /* }}} */
! 388:
! 389: /* {{{ proto array gzfile(string filename [, int use_include_path])
! 390: Read und uncompress entire .gz-file into an array */
! 391: static PHP_FUNCTION(gzfile)
! 392: {
! 393: char *filename;
! 394: int filename_len;
! 395: long flags = 0;
! 396: char *slashed, buf[8192];
! 397: register int i = 0;
! 398: int use_include_path = 0;
! 399: php_stream *stream;
! 400:
! 401: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &flags) == FAILURE) {
! 402: return;
! 403: }
! 404:
! 405: use_include_path = flags ? USE_PATH : 0;
! 406:
! 407: /* using a stream here is a bit more efficient (resource wise) than php_gzopen_wrapper */
! 408: stream = php_stream_gzopen(NULL, filename, "rb", use_include_path | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, NULL STREAMS_CC TSRMLS_CC);
! 409: if (stream == NULL) {
! 410: /* Error reporting is already done by stream code */
! 411: RETURN_FALSE;
! 412: }
! 413:
! 414: /* Initialize return array */
! 415: array_init(return_value);
! 416:
! 417: /* Now loop through the file and do the magic quotes thing if needed */
! 418: memset(buf,0,sizeof(buf));
! 419:
! 420: while (php_stream_gets(stream, buf, sizeof(buf) - 1) != NULL) {
! 421: if (PG(magic_quotes_runtime)) {
! 422: int len;
! 423:
! 424: slashed = php_addslashes(buf, 0, &len, 0 TSRMLS_CC); /* 0 = don't free source string */
! 425: add_index_stringl(return_value, i++, slashed, len, 0);
! 426: } else {
! 427: add_index_string(return_value, i++, buf, 1);
! 428: }
! 429: }
! 430: php_stream_close(stream);
! 431: }
! 432: /* }}} */
! 433:
! 434: /* {{{ proto resource gzopen(string filename, string mode [, int use_include_path])
! 435: Open a .gz-file and return a .gz-file pointer */
! 436: static PHP_FUNCTION(gzopen)
! 437: {
! 438: char *filename, *mode;
! 439: int filename_len, mode_len;
! 440: long flags = 0;
! 441: php_stream *stream;
! 442: int use_include_path = 0;
! 443:
! 444: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &filename, &filename_len, &mode, &mode_len, &flags) == FAILURE) {
! 445: return;
! 446: }
! 447:
! 448: use_include_path = flags ? USE_PATH : 0;
! 449:
! 450: stream = php_stream_gzopen(NULL, filename, mode, use_include_path | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, NULL STREAMS_CC TSRMLS_CC);
! 451:
! 452: if (!stream) {
! 453: RETURN_FALSE;
! 454: }
! 455: php_stream_to_zval(stream, return_value);
! 456: }
! 457: /* }}} */
! 458:
! 459: /*
! 460: * Read a file and write the ouput to stdout
! 461: */
! 462: /* {{{ proto int readgzfile(string filename [, int use_include_path])
! 463: Output a .gz-file */
! 464: static PHP_FUNCTION(readgzfile)
! 465: {
! 466: char *filename;
! 467: int filename_len;
! 468: long flags = 0;
! 469: php_stream *stream;
! 470: int size;
! 471: int use_include_path = 0;
! 472:
! 473: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &flags) == FAILURE) {
! 474: return;
! 475: }
! 476:
! 477: use_include_path = flags ? USE_PATH : 0;
! 478:
! 479: stream = php_stream_gzopen(NULL, filename, "rb", use_include_path | ENFORCE_SAFE_MODE, NULL, NULL STREAMS_CC TSRMLS_CC);
! 480: if (!stream) {
! 481: RETURN_FALSE;
! 482: }
! 483: size = php_stream_passthru(stream);
! 484: php_stream_close(stream);
! 485: RETURN_LONG(size);
! 486: }
! 487: /* }}} */
! 488:
! 489: /* {{{ proto string gzcompress(string data [, int level])
! 490: Gzip-compress a string */
! 491: static PHP_FUNCTION(gzcompress)
! 492: {
! 493: int data_len, status;
! 494: long level = Z_DEFAULT_COMPRESSION;
! 495: unsigned long l2;
! 496: char *data, *s2;
! 497:
! 498: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &level) == FAILURE) {
! 499: return;
! 500: }
! 501:
! 502: if ((level < -1) || (level > 9)) {
! 503: php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level (%ld) must be within -1..9", level);
! 504: RETURN_FALSE;
! 505: }
! 506:
! 507: l2 = data_len + (data_len / PHP_ZLIB_MODIFIER) + 15 + 1; /* room for \0 */
! 508: s2 = (char *) emalloc(l2);
! 509: if (!s2) {
! 510: RETURN_FALSE;
! 511: }
! 512:
! 513: if (level >= 0) {
! 514: status = compress2(s2, &l2, data, data_len, level);
! 515: } else {
! 516: status = compress(s2, &l2, data, data_len);
! 517: }
! 518:
! 519: if (status == Z_OK) {
! 520: s2 = erealloc(s2, l2 + 1);
! 521: s2[l2] = '\0';
! 522: RETURN_STRINGL(s2, l2, 0);
! 523: } else {
! 524: efree(s2);
! 525: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
! 526: RETURN_FALSE;
! 527: }
! 528: }
! 529: /* }}} */
! 530:
! 531: /* {{{ proto string gzuncompress(string data [, int length])
! 532: Unzip a gzip-compressed string */
! 533: static PHP_FUNCTION(gzuncompress)
! 534: {
! 535: int data_len, status;
! 536: unsigned int factor=1, maxfactor=16;
! 537: long limit = 0;
! 538: unsigned long plength=0, length;
! 539: char *data, *s1=NULL, *s2=NULL;
! 540:
! 541: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &limit) == FAILURE) {
! 542: return;
! 543: }
! 544:
! 545: if (limit < 0) {
! 546: php_error_docref(NULL TSRMLS_CC, E_WARNING, "length (%ld) must be greater or equal zero", limit);
! 547: RETURN_FALSE;
! 548: }
! 549: plength = limit;
! 550:
! 551: /*
! 552: zlib::uncompress() wants to know the output data length
! 553: if none was given as a parameter
! 554: we try from input length * 2 up to input length * 2^15
! 555: doubling it whenever it wasn't big enough
! 556: that should be eneugh for all real life cases
! 557: */
! 558: do {
! 559: length = plength ? plength : (unsigned long)data_len * (1 << factor++);
! 560: s2 = (char *) erealloc(s1, length);
! 561: status = uncompress(s2, &length, data, data_len);
! 562: s1 = s2;
! 563: } while ((status == Z_BUF_ERROR) && (!plength) && (factor < maxfactor));
! 564:
! 565: if (status == Z_OK) {
! 566: s2 = erealloc(s2, length + 1); /* space for \0 */
! 567: s2[ length ] = '\0';
! 568: RETURN_STRINGL(s2, length, 0);
! 569: } else {
! 570: efree(s2);
! 571: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
! 572: RETURN_FALSE;
! 573: }
! 574: }
! 575: /* }}} */
! 576:
! 577: /* {{{ proto string gzdeflate(string data [, int level])
! 578: Gzip-compress a string */
! 579: static PHP_FUNCTION(gzdeflate)
! 580: {
! 581: int data_len,status;
! 582: long level = Z_DEFAULT_COMPRESSION;
! 583: z_stream stream;
! 584: char *data, *s2;
! 585:
! 586: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &level) == FAILURE) {
! 587: return;
! 588: }
! 589:
! 590: if ((level < -1) || (level > 9)) {
! 591: php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level (%ld) must be within -1..9", level);
! 592: RETURN_FALSE;
! 593: }
! 594:
! 595: stream.data_type = Z_ASCII;
! 596: stream.zalloc = php_zlib_alloc;
! 597: stream.zfree = php_zlib_free;
! 598: stream.opaque = (voidpf) Z_NULL;
! 599:
! 600: stream.next_in = (Bytef *) data;
! 601: stream.avail_in = data_len;
! 602:
! 603: stream.avail_out = stream.avail_in + (stream.avail_in / PHP_ZLIB_MODIFIER) + 15 + 1; /* room for \0 */
! 604:
! 605: s2 = (char *) emalloc(stream.avail_out);
! 606: if (!s2) {
! 607: RETURN_FALSE;
! 608: }
! 609:
! 610: stream.next_out = s2;
! 611:
! 612: /* init with -MAX_WBITS disables the zlib internal headers */
! 613: status = deflateInit2(&stream, level, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, 0);
! 614: if (status == Z_OK) {
! 615: status = deflate(&stream, Z_FINISH);
! 616: if (status != Z_STREAM_END) {
! 617: deflateEnd(&stream);
! 618: if (status == Z_OK) {
! 619: status = Z_BUF_ERROR;
! 620: }
! 621: } else {
! 622: status = deflateEnd(&stream);
! 623: }
! 624: }
! 625:
! 626: if (status == Z_OK) {
! 627: s2 = erealloc(s2,stream.total_out + 1); /* resize to buffer to the "right" size */
! 628: s2[ stream.total_out ] = '\0';
! 629: RETURN_STRINGL(s2, stream.total_out, 0);
! 630: } else {
! 631: efree(s2);
! 632: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
! 633: RETURN_FALSE;
! 634: }
! 635: }
! 636: /* }}} */
! 637:
! 638: /* {{{ proto string gzinflate(string data [, int length])
! 639: Unzip a gzip-compressed string */
! 640: static PHP_FUNCTION(gzinflate)
! 641: {
! 642: int data_len, status;
! 643: unsigned int factor=1, maxfactor=16;
! 644: long limit = 0;
! 645: unsigned long plength=0, length;
! 646: char *data, *s1=NULL, *s2=NULL;
! 647: z_stream stream;
! 648:
! 649: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &limit) == FAILURE) {
! 650: return;
! 651: }
! 652:
! 653: if (!data_len) {
! 654: RETURN_FALSE;
! 655: }
! 656:
! 657: if (limit < 0) {
! 658: php_error_docref(NULL TSRMLS_CC, E_WARNING, "length (%ld) must be greater or equal zero", limit);
! 659: RETURN_FALSE;
! 660: }
! 661: plength = limit;
! 662:
! 663: stream.zalloc = php_zlib_alloc;
! 664: stream.zfree = php_zlib_free;
! 665: stream.opaque = Z_NULL;
! 666: stream.avail_in = data_len + 1; /* there is room for \0 */
! 667: stream.next_in = (Bytef *) data;
! 668: stream.total_out = 0;
! 669:
! 670: /* init with -MAX_WBITS disables the zlib internal headers */
! 671: status = inflateInit2(&stream, -MAX_WBITS);
! 672: if (status != Z_OK) {
! 673: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
! 674: RETURN_FALSE;
! 675: }
! 676:
! 677: /*
! 678: stream.avail_out wants to know the output data length
! 679: if none was given as a parameter
! 680: we try from input length * 2 up to input length * 2^15
! 681: doubling it whenever it wasn't big enough
! 682: that should be enaugh for all real life cases
! 683: */
! 684: do {
! 685: length = plength ? plength : (unsigned long)data_len * (1 << factor++);
! 686: s2 = (char *) erealloc(s1, length);
! 687:
! 688: if (!s2) {
! 689: if (s1) {
! 690: efree(s1);
! 691: }
! 692: inflateEnd(&stream);
! 693: RETURN_FALSE;
! 694: }
! 695: s1 = s2;
! 696:
! 697: stream.next_out = (Bytef *) &s2[stream.total_out];
! 698: stream.avail_out = length - stream.total_out;
! 699: status = inflate(&stream, Z_NO_FLUSH);
! 700:
! 701: } while ((Z_BUF_ERROR == status || (Z_OK == status && stream.avail_in)) && !plength && factor < maxfactor);
! 702:
! 703: inflateEnd(&stream);
! 704:
! 705: if ((plength && Z_OK == status) || factor >= maxfactor) {
! 706: status = Z_MEM_ERROR;
! 707: }
! 708:
! 709: if (Z_STREAM_END == status || Z_OK == status) {
! 710: s2 = erealloc(s2, stream.total_out + 1); /* room for \0 */
! 711: s2[ stream.total_out ] = '\0';
! 712: RETURN_STRINGL(s2, stream.total_out, 0);
! 713: } else {
! 714: efree(s2);
! 715: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
! 716: RETURN_FALSE;
! 717: }
! 718: }
! 719: /* }}} */
! 720:
! 721: /* {{{ proto string zlib_get_coding_type(void)
! 722: Returns the coding type used for output compression */
! 723: static PHP_FUNCTION(zlib_get_coding_type)
! 724: {
! 725: switch (ZLIBG(compression_coding)) {
! 726: case CODING_GZIP:
! 727: RETURN_STRINGL("gzip", sizeof("gzip") - 1, 1);
! 728:
! 729: case CODING_DEFLATE:
! 730: RETURN_STRINGL("deflate", sizeof("deflate") - 1, 1);
! 731: }
! 732:
! 733: RETURN_FALSE;
! 734: }
! 735:
! 736: /* {{{ php_do_deflate
! 737: */
! 738: static int php_do_deflate(uint str_length, Bytef **p_buffer, uint *p_buffer_len, zend_bool do_start, zend_bool do_end TSRMLS_DC)
! 739: {
! 740: Bytef *buffer;
! 741: uInt prev_outlen, outlen;
! 742: int err;
! 743: int start_offset = ((do_start && ZLIBG(compression_coding) == CODING_GZIP) ? 10 : 0);
! 744: int end_offset = (do_end ? 8 : 0);
! 745:
! 746: outlen = (uint) (str_length + (str_length / PHP_ZLIB_MODIFIER) + 12 + 1); /* leave some room for a trailing \0 */
! 747: if ((outlen + start_offset + end_offset) > *p_buffer_len) {
! 748: buffer = (Bytef *) emalloc(outlen + start_offset + end_offset);
! 749: } else {
! 750: buffer = *p_buffer;
! 751: }
! 752:
! 753: ZLIBG(stream).next_out = buffer + start_offset;
! 754: ZLIBG(stream).avail_out = outlen;
! 755:
! 756: err = deflate(&ZLIBG(stream), Z_SYNC_FLUSH);
! 757: while (err == Z_OK && !ZLIBG(stream).avail_out) {
! 758: prev_outlen = outlen;
! 759: outlen *= 3;
! 760: if ((outlen + start_offset + end_offset) > *p_buffer_len) {
! 761: buffer = erealloc(buffer, outlen + start_offset + end_offset);
! 762: }
! 763:
! 764: ZLIBG(stream).next_out = buffer + start_offset + prev_outlen;
! 765: ZLIBG(stream).avail_out = prev_outlen * 2;
! 766:
! 767: err = deflate(&ZLIBG(stream), Z_SYNC_FLUSH);
! 768: }
! 769:
! 770: if (do_end) {
! 771: err = deflate(&ZLIBG(stream), Z_FINISH);
! 772: buffer[outlen + start_offset - ZLIBG(stream).avail_out] = '\0';
! 773: }
! 774:
! 775: *p_buffer = buffer;
! 776: *p_buffer_len = outlen - ZLIBG(stream).avail_out;
! 777:
! 778: return err;
! 779: }
! 780: /* }}} */
! 781:
! 782: /* {{{ php_deflate_string
! 783: */
! 784: static int php_deflate_string(const char *str, uint str_length, char **newstr, uint *new_length, zend_bool do_start, zend_bool do_end TSRMLS_DC)
! 785: {
! 786: int err;
! 787:
! 788: if (do_start) {
! 789: ZLIBG(stream).zalloc = php_zlib_alloc;
! 790: ZLIBG(stream).zfree = php_zlib_free;
! 791: ZLIBG(stream).opaque = Z_NULL;
! 792:
! 793: switch (ZLIBG(compression_coding)) {
! 794: case CODING_GZIP:
! 795: /* windowBits is passed < 0 to suppress zlib header & trailer */
! 796: if (deflateInit2(&ZLIBG(stream), ZLIBG(output_compression_level), Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) {
! 797: /* TODO: print out error */
! 798: return FAILURE;
! 799: }
! 800:
! 801: ZLIBG(crc) = crc32(0L, Z_NULL, 0);
! 802: break;
! 803:
! 804: case CODING_DEFLATE:
! 805: if (deflateInit(&ZLIBG(stream), ZLIBG(output_compression_level)) != Z_OK) {
! 806: /* TODO: print out error */
! 807: return FAILURE;
! 808: }
! 809: break;
! 810: }
! 811: }
! 812:
! 813: ZLIBG(stream).next_in = (Bytef *) str;
! 814: ZLIBG(stream).avail_in = (uInt) str_length;
! 815:
! 816: if (ZLIBG(compression_coding) == CODING_GZIP) {
! 817: ZLIBG(crc) = crc32(ZLIBG(crc), (const Bytef *) str, str_length);
! 818: }
! 819:
! 820: err = php_do_deflate(str_length, (Bytef **) newstr, new_length, do_start, do_end TSRMLS_CC);
! 821: /* TODO: error handling (err may be Z_STREAM_ERROR, Z_BUF_ERROR, ?) */
! 822:
! 823: if (do_start && ZLIBG(compression_coding) == CODING_GZIP) {
! 824: /* Write a very simple .gz header: */
! 825: (*newstr)[0] = gz_magic[0];
! 826: (*newstr)[1] = gz_magic[1];
! 827: (*newstr)[2] = Z_DEFLATED;
! 828: (*newstr)[3] = (*newstr)[4] = (*newstr)[5] = (*newstr)[6] = (*newstr)[7] = (*newstr)[8] = 0;
! 829: (*newstr)[9] = OS_CODE;
! 830: *new_length += 10;
! 831: }
! 832: if (do_end) {
! 833: if (ZLIBG(compression_coding) == CODING_GZIP) {
! 834: char *trailer = (*newstr) + (*new_length);
! 835:
! 836: /* write crc & stream.total_in in LSB order */
! 837: trailer[0] = (char) ZLIBG(crc) & 0xFF;
! 838: trailer[1] = (char) (ZLIBG(crc) >> 8) & 0xFF;
! 839: trailer[2] = (char) (ZLIBG(crc) >> 16) & 0xFF;
! 840: trailer[3] = (char) (ZLIBG(crc) >> 24) & 0xFF;
! 841: trailer[4] = (char) ZLIBG(stream).total_in & 0xFF;
! 842: trailer[5] = (char) (ZLIBG(stream).total_in >> 8) & 0xFF;
! 843: trailer[6] = (char) (ZLIBG(stream).total_in >> 16) & 0xFF;
! 844: trailer[7] = (char) (ZLIBG(stream).total_in >> 24) & 0xFF;
! 845: trailer[8] = '\0';
! 846: *new_length += 8;
! 847: }
! 848: deflateEnd(&ZLIBG(stream));
! 849: }
! 850:
! 851: return SUCCESS;
! 852: }
! 853: /* }}} */
! 854:
! 855: /* {{{ proto string gzencode(string data [, int level [, int encoding_mode]])
! 856: GZ encode a string */
! 857: static PHP_FUNCTION(gzencode)
! 858: {
! 859: char *data, *s2;
! 860: int data_len;
! 861: long level = Z_DEFAULT_COMPRESSION, coding = CODING_GZIP;
! 862: int status;
! 863: z_stream stream;
! 864:
! 865: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &data, &data_len, &level, &coding) == FAILURE) {
! 866: return;
! 867: }
! 868:
! 869: if ((level < -1) || (level > 9)) {
! 870: php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level(%ld) must be within -1..9", level);
! 871: RETURN_FALSE;
! 872: }
! 873:
! 874: if ((coding != CODING_GZIP) && (coding != CODING_DEFLATE)) {
! 875: php_error_docref(NULL TSRMLS_CC, E_WARNING, "encoding mode must be FORCE_GZIP or FORCE_DEFLATE");
! 876: RETURN_FALSE;
! 877: }
! 878:
! 879: stream.zalloc = php_zlib_alloc;
! 880: stream.zfree = php_zlib_free;
! 881: stream.opaque = Z_NULL;
! 882:
! 883: stream.next_in = (Bytef *) data;
! 884: stream.avail_in = data_len;
! 885:
! 886: stream.avail_out = stream.avail_in + (stream.avail_in / PHP_ZLIB_MODIFIER) + 15 + 1; /* room for \0 */
! 887: s2 = (char *) emalloc(stream.avail_out + GZIP_HEADER_LENGTH + (coding == CODING_GZIP ? GZIP_FOOTER_LENGTH : 0));
! 888:
! 889: /* add gzip file header */
! 890: s2[0] = gz_magic[0];
! 891: s2[1] = gz_magic[1];
! 892: s2[2] = Z_DEFLATED;
! 893: s2[3] = s2[4] = s2[5] = s2[6] = s2[7] = s2[8] = 0; /* time set to 0 */
! 894: s2[9] = OS_CODE;
! 895:
! 896: stream.next_out = &(s2[GZIP_HEADER_LENGTH]);
! 897:
! 898: switch (coding) {
! 899: case CODING_GZIP:
! 900: /* windowBits is passed < 0 to suppress zlib header & trailer */
! 901: if ((status = deflateInit2(&stream, level, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) != Z_OK) {
! 902: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
! 903: RETURN_FALSE;
! 904: }
! 905:
! 906: break;
! 907: case CODING_DEFLATE:
! 908: if ((status = deflateInit(&stream, level)) != Z_OK) {
! 909: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
! 910: RETURN_FALSE;
! 911: }
! 912: break;
! 913: }
! 914:
! 915: status = deflate(&stream, Z_FINISH);
! 916: if (status != Z_STREAM_END) {
! 917: deflateEnd(&stream);
! 918: if (status == Z_OK) {
! 919: status = Z_BUF_ERROR;
! 920: }
! 921: } else {
! 922: status = deflateEnd(&stream);
! 923: }
! 924:
! 925: if (status == Z_OK) {
! 926: /* resize to buffer to the "right" size */
! 927: s2 = erealloc(s2, stream.total_out + GZIP_HEADER_LENGTH + (coding == CODING_GZIP ? GZIP_FOOTER_LENGTH : 0) + 1);
! 928:
! 929: if (coding == CODING_GZIP) {
! 930: char *trailer = s2 + (stream.total_out + GZIP_HEADER_LENGTH);
! 931: uLong crc = crc32(0L, Z_NULL, 0);
! 932:
! 933: crc = crc32(crc, (const Bytef *) data, data_len);
! 934:
! 935: /* write crc & stream.total_in in LSB order */
! 936: trailer[0] = (char) crc & 0xFF;
! 937: trailer[1] = (char) (crc >> 8) & 0xFF;
! 938: trailer[2] = (char) (crc >> 16) & 0xFF;
! 939: trailer[3] = (char) (crc >> 24) & 0xFF;
! 940: trailer[4] = (char) stream.total_in & 0xFF;
! 941: trailer[5] = (char) (stream.total_in >> 8) & 0xFF;
! 942: trailer[6] = (char) (stream.total_in >> 16) & 0xFF;
! 943: trailer[7] = (char) (stream.total_in >> 24) & 0xFF;
! 944: trailer[8] = '\0';
! 945: } else {
! 946: s2[stream.total_out + GZIP_HEADER_LENGTH + (coding == CODING_GZIP ? GZIP_FOOTER_LENGTH : 0)] = '\0';
! 947: }
! 948: RETURN_STRINGL(s2, stream.total_out + GZIP_HEADER_LENGTH + (coding == CODING_GZIP ? GZIP_FOOTER_LENGTH : 0), 0);
! 949: } else {
! 950: efree(s2);
! 951: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
! 952: RETURN_FALSE;
! 953: }
! 954: }
! 955: /* }}} */
! 956:
! 957: /* {{{ php_ob_gzhandler_check
! 958: */
! 959: int php_ob_gzhandler_check(TSRMLS_D)
! 960: {
! 961: /* check for wrong usages */
! 962: if (OG(ob_nesting_level > 0)) {
! 963: if (php_ob_handler_used("ob_gzhandler" TSRMLS_CC)) {
! 964: php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used twice");
! 965: return FAILURE;
! 966: }
! 967: if (php_ob_handler_used("mb_output_handler" TSRMLS_CC)) {
! 968: php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used after 'mb_output_handler'");
! 969: return FAILURE;
! 970: }
! 971: if (php_ob_handler_used("URL-Rewriter" TSRMLS_CC)) {
! 972: php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used after 'URL-Rewriter'");
! 973: return FAILURE;
! 974: }
! 975: if (php_ob_init_conflict("ob_gzhandler", "zlib output compression" TSRMLS_CC)) {
! 976: return FAILURE;
! 977: }
! 978: }
! 979:
! 980: return SUCCESS;
! 981: }
! 982:
! 983: /* }}} */
! 984:
! 985: /* {{{ proto string ob_gzhandler(string str, int mode)
! 986: Encode str based on accept-encoding setting - designed to be called from ob_start() */
! 987: static PHP_FUNCTION(ob_gzhandler)
! 988: {
! 989: char *string;
! 990: int string_len;
! 991: long mode;
! 992: zval **a_encoding;
! 993: zend_bool return_original = 0;
! 994: zend_bool do_start, do_end;
! 995:
! 996: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &string, &string_len, &mode) == FAILURE) {
! 997: return;
! 998: }
! 999:
! 1000: if (ZLIBG(ob_gzhandler_status) == -1) {
! 1001: RETURN_FALSE;
! 1002: }
! 1003:
! 1004: zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
! 1005:
! 1006: if (!PG(http_globals)[TRACK_VARS_SERVER]
! 1007: || zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING"), (void **) &a_encoding) == FAILURE
! 1008: ) {
! 1009: ZLIBG(ob_gzhandler_status) = -1;
! 1010: RETURN_FALSE;
! 1011: }
! 1012:
! 1013: convert_to_string_ex(a_encoding);
! 1014: if (php_memnstr(Z_STRVAL_PP(a_encoding), "gzip", 4, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) {
! 1015: ZLIBG(compression_coding) = CODING_GZIP;
! 1016: } else if (php_memnstr(Z_STRVAL_PP(a_encoding), "deflate", 7, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) {
! 1017: ZLIBG(compression_coding) = CODING_DEFLATE;
! 1018: } else {
! 1019: ZLIBG(ob_gzhandler_status) = -1;
! 1020: RETURN_FALSE;
! 1021: }
! 1022:
! 1023: do_start = ((mode & PHP_OUTPUT_HANDLER_START) ? 1 : 0);
! 1024: do_end = ((mode & PHP_OUTPUT_HANDLER_END) ? 1 : 0);
! 1025: Z_STRVAL_P(return_value) = NULL;
! 1026: Z_STRLEN_P(return_value) = 0;
! 1027:
! 1028: if (php_deflate_string(string, string_len, &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value), do_start, do_end TSRMLS_CC) == SUCCESS) {
! 1029: Z_TYPE_P(return_value) = IS_STRING;
! 1030: if (do_start) {
! 1031: switch (ZLIBG(compression_coding)) {
! 1032: case CODING_GZIP:
! 1033: if (sapi_add_header("Content-Encoding: gzip", sizeof("Content-Encoding: gzip") - 1, 1) == FAILURE) {
! 1034: return_original = 1;
! 1035: }
! 1036: if (sapi_add_header_ex("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1, 0 TSRMLS_CC)==FAILURE) {
! 1037: return_original = 1;
! 1038: }
! 1039: break;
! 1040: case CODING_DEFLATE:
! 1041: if (sapi_add_header("Content-Encoding: deflate", sizeof("Content-Encoding: deflate") - 1, 1) == FAILURE) {
! 1042: return_original = 1;
! 1043: }
! 1044: if (sapi_add_header_ex("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1, 0 TSRMLS_CC)==FAILURE) {
! 1045: return_original = 1;
! 1046: }
! 1047: break;
! 1048: default:
! 1049: return_original = 1;
! 1050: break;
! 1051: }
! 1052: }
! 1053:
! 1054: if (return_original) {
! 1055: zval_dtor(return_value);
! 1056: }
! 1057:
! 1058: } else {
! 1059: return_original = 1;
! 1060: }
! 1061:
! 1062: if (return_original) {
! 1063: /* return the original string */
! 1064: RETURN_STRINGL(string, string_len, 1);
! 1065: }
! 1066: }
! 1067: /* }}} */
! 1068:
! 1069: /* {{{ php_gzip_output_handler
! 1070: */
! 1071: static void php_gzip_output_handler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
! 1072: {
! 1073: zend_bool do_start, do_end;
! 1074:
! 1075: if (!ZLIBG(output_compression) || SG(sapi_headers).http_response_code == 204 || SG(sapi_headers).http_response_code == 304) {
! 1076: *handled_output = NULL;
! 1077: } else {
! 1078: do_start = (mode & PHP_OUTPUT_HANDLER_START ? 1 : 0);
! 1079: do_end = (mode & PHP_OUTPUT_HANDLER_END ? 1 : 0);
! 1080:
! 1081: if (do_start) {
! 1082: if (!SG(headers_sent) && !SG(request_info).no_headers) {
! 1083: switch (ZLIBG(compression_coding)) {
! 1084: case CODING_GZIP:
! 1085: sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1 TSRMLS_CC);
! 1086: break;
! 1087: case CODING_DEFLATE:
! 1088: sapi_add_header_ex(ZEND_STRL("Content-Encoding: deflate"), 1, 1 TSRMLS_CC);
! 1089: break;
! 1090: }
! 1091: sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 0 TSRMLS_CC);
! 1092: } else {
! 1093: /* Disable compression if headers can not be set (Fix for bug #49816) */
! 1094: ZLIBG(output_compression) = 0;
! 1095: *handled_output = NULL;
! 1096: return;
! 1097: }
! 1098: }
! 1099:
! 1100: if (php_deflate_string(output, output_len, handled_output, handled_output_len, do_start, do_end TSRMLS_CC) != SUCCESS) {
! 1101: zend_error(E_ERROR, "Compression failed");
! 1102: }
! 1103: }
! 1104: }
! 1105: /* }}} */
! 1106:
! 1107: /* {{{ php_enable_output_compression
! 1108: */
! 1109: static int php_enable_output_compression(int buffer_size TSRMLS_DC)
! 1110: {
! 1111: zval **a_encoding;
! 1112:
! 1113: zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
! 1114:
! 1115: if (!PG(http_globals)[TRACK_VARS_SERVER]
! 1116: || zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING"), (void **) &a_encoding) == FAILURE
! 1117: ) {
! 1118: return FAILURE;
! 1119: }
! 1120:
! 1121: convert_to_string_ex(a_encoding);
! 1122:
! 1123: if (php_memnstr(Z_STRVAL_PP(a_encoding), "gzip", 4, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) {
! 1124: ZLIBG(compression_coding) = CODING_GZIP;
! 1125: } else if (php_memnstr(Z_STRVAL_PP(a_encoding), "deflate", 7, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) {
! 1126: ZLIBG(compression_coding) = CODING_DEFLATE;
! 1127: } else {
! 1128: return FAILURE;
! 1129: }
! 1130:
! 1131: php_ob_set_internal_handler(php_gzip_output_handler, (uint)buffer_size, "zlib output compression", 0 TSRMLS_CC);
! 1132:
! 1133: if (ZLIBG(output_handler) && strlen(ZLIBG(output_handler))) {
! 1134: php_start_ob_buffer_named(ZLIBG(output_handler), 0, 1 TSRMLS_CC);
! 1135: }
! 1136: return SUCCESS;
! 1137: }
! 1138: /* }}} */
! 1139:
! 1140: /* {{{ php_zlib_output_compression_start() */
! 1141: static int php_zlib_output_compression_start(TSRMLS_D)
! 1142: {
! 1143: switch (ZLIBG(output_compression)) {
! 1144: case 0:
! 1145: break;
! 1146: case 1:
! 1147: ZLIBG(output_compression) = 4096;
! 1148: /* break omitted intentionally */
! 1149: default:
! 1150: /* ZLIBG(compression_coding) should be 0 when zlib compression hasn't been started yet.. */
! 1151: if (ZLIBG(compression_coding) == 0) {
! 1152: return php_enable_output_compression(ZLIBG(output_compression) TSRMLS_CC);
! 1153: }
! 1154: }
! 1155: return SUCCESS;
! 1156: }
! 1157: /* }}} */
! 1158:
! 1159: /*
! 1160: * Local variables:
! 1161: * tab-width: 4
! 1162: * c-basic-offset: 4
! 1163: * End:
! 1164: * vim600: sw=4 ts=4 fdm=marker
! 1165: * vim<600: sw=4 ts=4
! 1166: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>