Annotation of embedaddon/php/ext/zlib/zlib.c, revision 1.1.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>