PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/zlib - zlib.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 334 444 75.2 %
Date: 2014-04-18 Functions: 23 25 92.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2013 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$ */
      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         445 : static voidpf php_zlib_alloc(voidpf opaque, uInt items, uInt size)
     250             : {
     251         445 :         return (voidpf)safe_emalloc(items, size, 0);
     252             : }
     253             : 
     254         445 : static void php_zlib_free(voidpf opaque, voidpf address)
     255             : {
     256         445 :         efree((void*)address);
     257         445 : }
     258             : /* }}} */
     259             : 
     260             : /* {{{ OnUpdate_zlib_output_compression */
     261       19351 : static PHP_INI_MH(OnUpdate_zlib_output_compression)
     262             : {
     263             :         int status, int_value;
     264             :         char *ini_value;
     265             : 
     266       19351 :         if (new_value == NULL) {
     267           0 :                 return FAILURE;
     268             :         }
     269             : 
     270       19351 :         if (!strncasecmp(new_value, "off", sizeof("off"))) {
     271           0 :                 new_value = "0";
     272           0 :                 new_value_length = sizeof("0");
     273       19351 :         } else if (!strncasecmp(new_value, "on", sizeof("on"))) {
     274           0 :                 new_value = "1";
     275           0 :                 new_value_length = sizeof("1");
     276             :         }
     277             : 
     278       19351 :         int_value = zend_atoi(new_value, new_value_length);
     279       19351 :         ini_value = zend_ini_string("output_handler", sizeof("output_handler"), 0);
     280             : 
     281       19351 :         if (ini_value && *ini_value && int_value) {
     282           0 :                 php_error_docref("ref.outcontrol" TSRMLS_CC, E_CORE_ERROR, "Cannot use both zlib.output_compression and output_handler together!!");
     283           0 :                 return FAILURE;
     284             :         }
     285             : 
     286       19351 :         if (stage == PHP_INI_STAGE_RUNTIME && SG(headers_sent) && !SG(request_info).no_headers) {
     287           0 :                 php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "Cannot change zlib.output_compression - headers already sent");
     288           0 :                 return FAILURE;
     289             :         }
     290             : 
     291       19351 :         status = OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
     292             : 
     293       19351 :         if (stage == PHP_INI_STAGE_RUNTIME && int_value) {
     294           1 :                 status = php_zlib_output_compression_start(TSRMLS_C);
     295             :         }
     296             : 
     297       19351 :         return status;
     298             : }
     299             : /* }}} */
     300             : 
     301             : /* {{{ OnUpdate_zlib_output_compression_level */
     302       19343 : static PHP_INI_MH(OnUpdate_zlib_output_compression_level)
     303             : {
     304       19343 :         OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
     305             : 
     306       19343 :         return SUCCESS;
     307             : }
     308             : /* }}} */
     309             : 
     310             : /* {{{ OnUpdate_zlib_output_handler */
     311       19341 : static PHP_INI_MH(OnUpdate_zlib_output_handler)
     312             : {
     313       19341 :         if (stage == PHP_INI_STAGE_RUNTIME && SG(headers_sent) && !SG(request_info).no_headers) {
     314           0 :                 php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "Cannot change zlib.output_handler - headers already sent");
     315           0 :                 return FAILURE;
     316             :         }
     317             : 
     318       19341 :         OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
     319             : 
     320       19341 :         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       19341 : static PHP_MINIT_FUNCTION(zlib)
     334             : {
     335       19341 :         php_register_url_stream_wrapper("compress.zlib", &php_stream_gzip_wrapper TSRMLS_CC);
     336       19341 :         php_stream_filter_register_factory("zlib.*", &php_zlib_filter_factory TSRMLS_CC);
     337             : 
     338       19341 :         REGISTER_LONG_CONSTANT("FORCE_GZIP", CODING_GZIP, CONST_CS | CONST_PERSISTENT);
     339       19341 :         REGISTER_LONG_CONSTANT("FORCE_DEFLATE", CODING_DEFLATE, CONST_CS | CONST_PERSISTENT);
     340             : 
     341       19341 :         REGISTER_INI_ENTRIES();
     342             : 
     343       19341 :         return SUCCESS;
     344             : }
     345             : /* }}} */
     346             : 
     347             : /* {{{ PHP_RINIT_FUNCTION
     348             :  */
     349       19327 : static PHP_RINIT_FUNCTION(zlib)
     350             : {
     351       19327 :         ZLIBG(ob_gzhandler_status) = 0;
     352       19327 :         ZLIBG(compression_coding) = 0;
     353             : 
     354       19327 :         php_zlib_output_compression_start(TSRMLS_C);
     355             : 
     356       19327 :         return SUCCESS;
     357             : }
     358             : /* }}} */
     359             : 
     360             : /* {{{ PHP_MSHUTDOWN_FUNCTION
     361             :  */
     362       19376 : static PHP_MSHUTDOWN_FUNCTION(zlib)
     363             : {
     364       19376 :         php_unregister_url_stream_wrapper("zlib" TSRMLS_CC);
     365       19376 :         php_stream_filter_unregister_factory("zlib.*" TSRMLS_CC);
     366             : 
     367       19376 :         UNREGISTER_INI_ENTRIES();
     368             : 
     369       19376 :         return SUCCESS;
     370             : }
     371             : /* }}} */
     372             : 
     373             : /* {{{ PHP_MINFO_FUNCTION
     374             :  */
     375         148 : static PHP_MINFO_FUNCTION(zlib)
     376             : {
     377         148 :         php_info_print_table_start();
     378         148 :         php_info_print_table_row(2, "ZLib Support", "enabled");
     379         148 :         php_info_print_table_row(2, "Stream Wrapper support", "compress.zlib://");
     380         148 :         php_info_print_table_row(2, "Stream Filter support", "zlib.inflate, zlib.deflate");
     381         148 :         php_info_print_table_row(2, "Compiled Version", ZLIB_VERSION);
     382         148 :         php_info_print_table_row(2, "Linked Version", (char *) zlibVersion());
     383         148 :         php_info_print_table_end();
     384             : 
     385         148 :         DISPLAY_INI_ENTRIES();
     386         148 : }
     387             : /* }}} */
     388             : 
     389             : /* {{{ proto array gzfile(string filename [, int use_include_path])
     390             :    Read und uncompress entire .gz-file into an array */
     391          74 : static PHP_FUNCTION(gzfile)
     392             : {
     393             :         char *filename;
     394             :         int filename_len;
     395          74 :         long flags = 0;
     396             :         char *slashed, buf[8192];
     397          74 :         register int i = 0;
     398          74 :         int use_include_path = 0;
     399             :         php_stream *stream;
     400             : 
     401          74 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &flags) == FAILURE) {
     402          25 :                 return;
     403             :         }
     404             : 
     405          49 :         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          49 :         stream = php_stream_gzopen(NULL, filename, "rb", use_include_path | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, NULL STREAMS_CC TSRMLS_CC);
     409          49 :         if (stream == NULL) {
     410             :                 /* Error reporting is already done by stream code */
     411          21 :                 RETURN_FALSE;
     412             :         }
     413             : 
     414             :         /* Initialize return array */
     415          28 :         array_init(return_value);
     416             : 
     417             :         /* Now loop through the file and do the magic quotes thing if needed */
     418          28 :         memset(buf,0,sizeof(buf));
     419             : 
     420         203 :         while (php_stream_gets(stream, buf, sizeof(buf) - 1) != NULL) {
     421         147 :                 if (PG(magic_quotes_runtime)) {
     422             :                         int len;
     423             : 
     424           6 :                         slashed = php_addslashes(buf, 0, &len, 0 TSRMLS_CC); /* 0 = don't free source string */
     425           6 :                         add_index_stringl(return_value, i++, slashed, len, 0);
     426             :                 } else {
     427         141 :                         add_index_string(return_value, i++, buf, 1);
     428             :                 }
     429             :         }
     430          28 :         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         208 : static PHP_FUNCTION(gzopen)
     437             : {
     438             :         char *filename, *mode;
     439             :         int filename_len, mode_len;
     440         208 :         long flags = 0;
     441             :         php_stream *stream;
     442         208 :         int use_include_path = 0;
     443             : 
     444         208 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &filename, &filename_len, &mode, &mode_len, &flags) == FAILURE) {
     445          27 :                 return;
     446             :         }
     447             : 
     448         181 :         use_include_path = flags ? USE_PATH : 0;
     449             : 
     450         181 :         stream = php_stream_gzopen(NULL, filename, mode, use_include_path | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, NULL STREAMS_CC TSRMLS_CC);
     451             : 
     452         181 :         if (!stream) {
     453          52 :                 RETURN_FALSE;
     454             :         }
     455         129 :         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          68 : static PHP_FUNCTION(readgzfile)
     465             : {
     466             :         char *filename;
     467             :         int filename_len;
     468          68 :         long flags = 0;
     469             :         php_stream *stream;
     470             :         int size;
     471          68 :         int use_include_path = 0;
     472             : 
     473          68 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &flags) == FAILURE) {
     474          23 :                 return;
     475             :         }
     476             : 
     477          45 :         use_include_path = flags ? USE_PATH : 0;
     478             : 
     479          45 :         stream = php_stream_gzopen(NULL, filename, "rb", use_include_path | ENFORCE_SAFE_MODE, NULL, NULL STREAMS_CC TSRMLS_CC);
     480          45 :         if (!stream) {
     481          20 :                 RETURN_FALSE;
     482             :         }
     483          25 :         size = php_stream_passthru(stream);
     484          25 :         php_stream_close(stream);
     485          25 :         RETURN_LONG(size);
     486             : }
     487             : /* }}} */
     488             : 
     489             : /* {{{ proto string gzcompress(string data [, int level])
     490             :    Gzip-compress a string */
     491          47 : static PHP_FUNCTION(gzcompress)
     492             : {
     493             :         int data_len, status;
     494          47 :         long level = Z_DEFAULT_COMPRESSION;
     495             :         unsigned long l2;
     496             :         char *data, *s2;
     497             : 
     498          47 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &level) == FAILURE) {
     499           5 :                 return;
     500             :         }
     501             : 
     502          42 :         if ((level < -1) || (level > 9)) {
     503           2 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level (%ld) must be within -1..9", level);
     504           2 :                 RETURN_FALSE;
     505             :         }
     506             : 
     507          40 :         l2 = data_len + (data_len / PHP_ZLIB_MODIFIER) + 15 + 1; /* room for \0 */
     508          40 :         s2 = (char *) emalloc(l2);
     509          40 :         if (!s2) {
     510           0 :                 RETURN_FALSE;
     511             :         }
     512             : 
     513          40 :         if (level >= 0) {
     514          24 :                 status = compress2(s2, &l2, data, data_len, level);
     515             :         } else {
     516          16 :                 status = compress(s2, &l2, data, data_len);
     517             :         }
     518             : 
     519          40 :         if (status == Z_OK) {
     520          40 :                 s2 = erealloc(s2, l2 + 1);
     521          40 :                 s2[l2] = '\0';
     522          40 :                 RETURN_STRINGL(s2, l2, 0);
     523             :         } else {
     524           0 :                 efree(s2);
     525           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
     526           0 :                 RETURN_FALSE;
     527             :         }
     528             : }
     529             : /* }}} */
     530             : 
     531             : /* {{{ proto string gzuncompress(string data [, int length])
     532             :    Unzip a gzip-compressed string */
     533          45 : static PHP_FUNCTION(gzuncompress)
     534             : {
     535             :         int data_len, status;
     536          45 :         unsigned int factor=1, maxfactor=16;
     537          45 :         long limit = 0;
     538          45 :         unsigned long plength=0, length;
     539          45 :         char *data, *s1=NULL, *s2=NULL;
     540             : 
     541          45 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &limit) == FAILURE) {
     542           5 :                 return;
     543             :         }
     544             : 
     545          40 :         if (limit < 0) {
     546           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "length (%ld) must be greater or equal zero", limit);
     547           1 :                 RETURN_FALSE;
     548             :         }
     549          39 :         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          47 :                 length = plength ? plength : (unsigned long)data_len * (1 << factor++);
     560          47 :                 s2 = (char *) erealloc(s1, length);
     561          47 :                 status = uncompress(s2, &length, data, data_len);
     562          47 :                 s1 = s2;
     563          47 :         } while ((status == Z_BUF_ERROR) && (!plength) && (factor < maxfactor));
     564             : 
     565          39 :         if (status == Z_OK) {
     566          33 :                 s2 = erealloc(s2, length + 1); /* space for \0 */
     567          33 :                 s2[ length ] = '\0';
     568          33 :                 RETURN_STRINGL(s2, length, 0);
     569             :         } else {
     570           6 :                 efree(s2);
     571           6 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
     572           6 :                 RETURN_FALSE;
     573             :         }
     574             : }
     575             : /* }}} */
     576             : 
     577             : /* {{{ proto string gzdeflate(string data [, int level])
     578             :    Gzip-compress a string */
     579          46 : static PHP_FUNCTION(gzdeflate)
     580             : {
     581             :         int data_len,status;
     582          46 :         long level = Z_DEFAULT_COMPRESSION;
     583             :         z_stream stream;
     584             :         char *data, *s2;
     585             : 
     586          46 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &level) == FAILURE) {
     587           5 :                 return;
     588             :         }
     589             : 
     590          41 :         if ((level < -1) || (level > 9)) {
     591           2 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level (%ld) must be within -1..9", level);
     592           2 :                 RETURN_FALSE;
     593             :         }
     594             : 
     595          39 :         stream.data_type = Z_ASCII;
     596          39 :         stream.zalloc = php_zlib_alloc;
     597          39 :         stream.zfree  = php_zlib_free;
     598          39 :         stream.opaque = (voidpf) Z_NULL;
     599             : 
     600          39 :         stream.next_in = (Bytef *) data;
     601          39 :         stream.avail_in = data_len;
     602             : 
     603          39 :         stream.avail_out = stream.avail_in + (stream.avail_in / PHP_ZLIB_MODIFIER) + 15 + 1; /* room for \0 */
     604             : 
     605          39 :         s2 = (char *) emalloc(stream.avail_out);
     606          39 :         if (!s2) {
     607           0 :                 RETURN_FALSE;
     608             :         }
     609             : 
     610          39 :         stream.next_out = s2;
     611             : 
     612             :         /* init with -MAX_WBITS disables the zlib internal headers */
     613          39 :         status = deflateInit2(&stream, level, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, 0);
     614          39 :         if (status == Z_OK) {
     615          39 :                 status = deflate(&stream, Z_FINISH);
     616          39 :                 if (status != Z_STREAM_END) {
     617           0 :                         deflateEnd(&stream);
     618           0 :                         if (status == Z_OK) {
     619           0 :                                 status = Z_BUF_ERROR;
     620             :                         }
     621             :                 } else {
     622          39 :                         status = deflateEnd(&stream);
     623             :                 }
     624             :         }
     625             : 
     626          39 :         if (status == Z_OK) {
     627          39 :                 s2 = erealloc(s2,stream.total_out + 1); /* resize to buffer to the "right" size */
     628          39 :                 s2[ stream.total_out ] = '\0';
     629          39 :                 RETURN_STRINGL(s2, stream.total_out, 0);
     630             :         } else {
     631           0 :                 efree(s2);
     632           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
     633           0 :                 RETURN_FALSE;
     634             :         }
     635             : }
     636             : /* }}} */
     637             : 
     638             : /* {{{ proto string gzinflate(string data [, int length])
     639             :    Unzip a gzip-compressed string */
     640          52 : static PHP_FUNCTION(gzinflate)
     641             : {
     642             :         int data_len, status;
     643          52 :         unsigned int factor=1, maxfactor=16;
     644          52 :         long limit = 0;
     645          52 :         unsigned long plength=0, length;
     646          52 :         char *data, *s1=NULL, *s2=NULL;
     647             :         z_stream stream;
     648             : 
     649          52 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &limit) == FAILURE) {
     650           5 :                 return;
     651             :         }
     652             : 
     653          47 :         if (!data_len) {
     654           1 :                 RETURN_FALSE;
     655             :         }
     656             : 
     657          46 :         if (limit < 0) {
     658           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "length (%ld) must be greater or equal zero", limit);
     659           1 :                 RETURN_FALSE;
     660             :         }
     661          45 :         plength = limit;
     662             : 
     663          45 :         stream.zalloc = php_zlib_alloc;
     664          45 :         stream.zfree = php_zlib_free;
     665          45 :         stream.opaque = Z_NULL;
     666          45 :         stream.avail_in = data_len + 1; /* there is room for \0 */
     667          45 :         stream.next_in = (Bytef *) data;
     668          45 :         stream.total_out = 0;
     669             : 
     670             :         /* init with -MAX_WBITS disables the zlib internal headers */
     671          45 :         status = inflateInit2(&stream, -MAX_WBITS);
     672          45 :         if (status != Z_OK) {
     673           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
     674           0 :                 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          56 :                 length = plength ? plength : (unsigned long)data_len * (1 << factor++);
     686          56 :                 s2 = (char *) erealloc(s1, length);
     687             : 
     688          56 :                 if (!s2) {
     689           0 :                         if (s1) {
     690           0 :                                 efree(s1);
     691             :                         }
     692           0 :                         inflateEnd(&stream);
     693           0 :                         RETURN_FALSE;
     694             :                 }
     695          56 :                 s1 = s2;
     696             : 
     697          56 :                 stream.next_out = (Bytef *) &s2[stream.total_out];
     698          56 :                 stream.avail_out = length - stream.total_out;
     699          56 :                 status = inflate(&stream, Z_NO_FLUSH);
     700             : 
     701          56 :         } while ((Z_BUF_ERROR == status || (Z_OK == status && stream.avail_in)) && !plength && factor < maxfactor);
     702             : 
     703          45 :         inflateEnd(&stream);
     704             : 
     705          45 :         if ((plength && Z_OK == status) || factor >= maxfactor) {
     706           1 :                 status = Z_MEM_ERROR;
     707             :         }
     708             : 
     709          45 :         if (Z_STREAM_END == status || Z_OK == status) {
     710          39 :                 s2 = erealloc(s2, stream.total_out + 1); /* room for \0 */
     711          39 :                 s2[ stream.total_out ] = '\0';
     712          39 :                 RETURN_STRINGL(s2, stream.total_out, 0);
     713             :         } else {
     714           6 :                 efree(s2);
     715           6 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
     716           6 :                 RETURN_FALSE;
     717             :         }
     718             : }
     719             : /* }}} */
     720             : 
     721             : /* {{{ proto string zlib_get_coding_type(void)
     722             :    Returns the coding type used for output compression */
     723           0 : static PHP_FUNCTION(zlib_get_coding_type)
     724             : {
     725           0 :         switch (ZLIBG(compression_coding)) {
     726             :                 case CODING_GZIP:
     727           0 :                         RETURN_STRINGL("gzip", sizeof("gzip") - 1, 1);
     728             : 
     729             :                 case CODING_DEFLATE:
     730           0 :                         RETURN_STRINGL("deflate", sizeof("deflate") - 1, 1);
     731             :         }
     732             : 
     733           0 :         RETURN_FALSE;
     734             : }
     735             : 
     736             : /* {{{ php_do_deflate
     737             :  */
     738           3 : 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           3 :         int start_offset = ((do_start && ZLIBG(compression_coding) == CODING_GZIP) ? 10 : 0);
     744           3 :         int end_offset = (do_end ? 8 : 0);
     745             : 
     746           3 :         outlen = (uint) (str_length + (str_length / PHP_ZLIB_MODIFIER) + 12 + 1); /* leave some room for a trailing \0 */
     747           3 :         if ((outlen + start_offset + end_offset) > *p_buffer_len) {
     748           0 :                 buffer = (Bytef *) emalloc(outlen + start_offset + end_offset);
     749             :         } else {
     750           3 :                 buffer = *p_buffer;
     751             :         }
     752             : 
     753           3 :         ZLIBG(stream).next_out = buffer + start_offset;
     754           3 :         ZLIBG(stream).avail_out = outlen;
     755             : 
     756           3 :         err = deflate(&ZLIBG(stream), Z_SYNC_FLUSH);
     757           6 :         while (err == Z_OK && !ZLIBG(stream).avail_out) {
     758           0 :                 prev_outlen = outlen;
     759           0 :                 outlen *= 3;
     760           0 :                 if ((outlen + start_offset + end_offset) > *p_buffer_len) {
     761           0 :                         buffer = erealloc(buffer, outlen + start_offset + end_offset);
     762             :                 }
     763             : 
     764           0 :                 ZLIBG(stream).next_out = buffer + start_offset + prev_outlen;
     765           0 :                 ZLIBG(stream).avail_out = prev_outlen * 2;
     766             : 
     767           0 :                 err = deflate(&ZLIBG(stream), Z_SYNC_FLUSH);
     768             :         }
     769             : 
     770           3 :         if (do_end) {
     771           3 :                 err = deflate(&ZLIBG(stream), Z_FINISH);
     772           3 :                 buffer[outlen + start_offset - ZLIBG(stream).avail_out] = '\0';
     773             :         }
     774             : 
     775           3 :         *p_buffer = buffer;
     776           3 :         *p_buffer_len = outlen - ZLIBG(stream).avail_out;
     777             : 
     778           3 :         return err;
     779             : }
     780             : /* }}} */
     781             : 
     782             : /* {{{ php_deflate_string
     783             :  */
     784           3 : 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           3 :         if (do_start) {
     789           3 :                 ZLIBG(stream).zalloc = php_zlib_alloc;
     790           3 :                 ZLIBG(stream).zfree = php_zlib_free;
     791           3 :                 ZLIBG(stream).opaque = Z_NULL;
     792             : 
     793           3 :                 switch (ZLIBG(compression_coding)) {
     794             :                         case CODING_GZIP:
     795             :                                 /* windowBits is passed < 0 to suppress zlib header & trailer */
     796           3 :                                 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           0 :                                         return FAILURE;
     799             :                                 }
     800             : 
     801           3 :                                 ZLIBG(crc) = crc32(0L, Z_NULL, 0);
     802           3 :                                 break;
     803             : 
     804             :                         case CODING_DEFLATE:
     805           0 :                                 if (deflateInit(&ZLIBG(stream), ZLIBG(output_compression_level)) != Z_OK) {
     806             :                                         /* TODO: print out error */
     807           0 :                                         return FAILURE;
     808             :                                 }
     809             :                                 break;
     810             :                 }
     811             :         }
     812             : 
     813           3 :         ZLIBG(stream).next_in = (Bytef *) str;
     814           3 :         ZLIBG(stream).avail_in = (uInt) str_length;
     815             : 
     816           3 :         if (ZLIBG(compression_coding) == CODING_GZIP) {
     817           3 :                 ZLIBG(crc) = crc32(ZLIBG(crc), (const Bytef *) str, str_length);
     818             :         }
     819             : 
     820           3 :         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           3 :         if (do_start && ZLIBG(compression_coding) == CODING_GZIP) {
     824             :                 /* Write a very simple .gz header: */
     825           3 :                 (*newstr)[0] = gz_magic[0];
     826           3 :                 (*newstr)[1] = gz_magic[1];
     827           3 :                 (*newstr)[2] = Z_DEFLATED;
     828           3 :                 (*newstr)[3] = (*newstr)[4] = (*newstr)[5] = (*newstr)[6] = (*newstr)[7] = (*newstr)[8] = 0;
     829           3 :                 (*newstr)[9] = OS_CODE;
     830           3 :                 *new_length += 10;
     831             :         }
     832           3 :         if (do_end) {
     833           3 :                 if (ZLIBG(compression_coding) == CODING_GZIP) {
     834           3 :                         char *trailer = (*newstr) + (*new_length);
     835             : 
     836             :                         /* write crc & stream.total_in in LSB order */
     837           3 :                         trailer[0] = (char) ZLIBG(crc) & 0xFF;
     838           3 :                         trailer[1] = (char) (ZLIBG(crc) >> 8) & 0xFF;
     839           3 :                         trailer[2] = (char) (ZLIBG(crc) >> 16) & 0xFF;
     840           3 :                         trailer[3] = (char) (ZLIBG(crc) >> 24) & 0xFF;
     841           3 :                         trailer[4] = (char) ZLIBG(stream).total_in & 0xFF;
     842           3 :                         trailer[5] = (char) (ZLIBG(stream).total_in >> 8) & 0xFF;
     843           3 :                         trailer[6] = (char) (ZLIBG(stream).total_in >> 16) & 0xFF;
     844           3 :                         trailer[7] = (char) (ZLIBG(stream).total_in >> 24) & 0xFF;
     845           3 :                         trailer[8] = '\0';
     846           3 :                         *new_length += 8;
     847             :                 }
     848           3 :                 deflateEnd(&ZLIBG(stream));
     849             :         }
     850             : 
     851           3 :         return SUCCESS;
     852             : }
     853             : /* }}} */
     854             : 
     855             : /* {{{ proto string gzencode(string data [, int level [, int encoding_mode]])
     856             :    GZ encode a string */
     857          52 : static PHP_FUNCTION(gzencode)
     858             : {
     859             :         char *data, *s2;
     860             :         int data_len;
     861          52 :         long level = Z_DEFAULT_COMPRESSION, coding = CODING_GZIP;
     862             :         int status;
     863             :         z_stream stream;
     864             : 
     865          52 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &data, &data_len, &level, &coding) == FAILURE) {
     866           8 :                 return;
     867             :         }
     868             : 
     869          44 :         if ((level < -1) || (level > 9)) {
     870           3 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level(%ld) must be within -1..9", level);
     871           3 :                 RETURN_FALSE;
     872             :         }
     873             : 
     874          41 :         if ((coding != CODING_GZIP) && (coding != CODING_DEFLATE)) {
     875           4 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "encoding mode must be FORCE_GZIP or FORCE_DEFLATE");
     876           4 :                 RETURN_FALSE;
     877             :         }
     878             : 
     879          37 :         stream.zalloc = php_zlib_alloc;
     880          37 :         stream.zfree = php_zlib_free;
     881          37 :         stream.opaque = Z_NULL;
     882             : 
     883          37 :         stream.next_in = (Bytef *) data;
     884          37 :         stream.avail_in = data_len;
     885             : 
     886          37 :         stream.avail_out = stream.avail_in + (stream.avail_in / PHP_ZLIB_MODIFIER) + 15 + 1; /* room for \0 */
     887          37 :         s2 = (char *) emalloc(stream.avail_out + GZIP_HEADER_LENGTH + (coding == CODING_GZIP ? GZIP_FOOTER_LENGTH : 0));
     888             : 
     889             :         /* add gzip file header */
     890          37 :         s2[0] = gz_magic[0];
     891          37 :         s2[1] = gz_magic[1];
     892          37 :         s2[2] = Z_DEFLATED;
     893          37 :         s2[3] = s2[4] = s2[5] = s2[6] = s2[7] = s2[8] = 0; /* time set to 0 */
     894          37 :         s2[9] = OS_CODE;
     895             : 
     896          37 :         stream.next_out = &(s2[GZIP_HEADER_LENGTH]);
     897             : 
     898          37 :         switch (coding) {
     899             :                 case CODING_GZIP:
     900             :                         /* windowBits is passed < 0 to suppress zlib header & trailer */
     901          34 :                         if ((status = deflateInit2(&stream, level, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) != Z_OK) {
     902           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
     903           0 :                                 RETURN_FALSE;
     904             :                         }
     905             : 
     906          34 :                         break;
     907             :                 case CODING_DEFLATE:
     908           3 :                         if ((status = deflateInit(&stream, level)) != Z_OK) {
     909           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
     910           0 :                                 RETURN_FALSE;
     911             :                         }
     912             :                         break;
     913             :         }
     914             : 
     915          37 :         status = deflate(&stream, Z_FINISH);
     916          37 :         if (status != Z_STREAM_END) {
     917           0 :                 deflateEnd(&stream);
     918           0 :                 if (status == Z_OK) {
     919           0 :                         status = Z_BUF_ERROR;
     920             :                 }
     921             :         } else {
     922          37 :                 status = deflateEnd(&stream);
     923             :         }
     924             : 
     925          37 :         if (status == Z_OK) {
     926             :                 /* resize to buffer to the "right" size */
     927          37 :                 s2 = erealloc(s2, stream.total_out + GZIP_HEADER_LENGTH + (coding == CODING_GZIP ? GZIP_FOOTER_LENGTH : 0) + 1);
     928             : 
     929          37 :                 if (coding == CODING_GZIP) {
     930          34 :                         char *trailer = s2 + (stream.total_out + GZIP_HEADER_LENGTH);
     931          34 :                         uLong crc = crc32(0L, Z_NULL, 0);
     932             : 
     933          34 :                         crc = crc32(crc, (const Bytef *) data, data_len);
     934             : 
     935             :                         /* write crc & stream.total_in in LSB order */
     936          34 :                         trailer[0] = (char) crc & 0xFF;
     937          34 :                         trailer[1] = (char) (crc >> 8) & 0xFF;
     938          34 :                         trailer[2] = (char) (crc >> 16) & 0xFF;
     939          34 :                         trailer[3] = (char) (crc >> 24) & 0xFF;
     940          34 :                         trailer[4] = (char) stream.total_in & 0xFF;
     941          34 :                         trailer[5] = (char) (stream.total_in >> 8) & 0xFF;
     942          34 :                         trailer[6] = (char) (stream.total_in >> 16) & 0xFF;
     943          34 :                         trailer[7] = (char) (stream.total_in >> 24) & 0xFF;
     944          34 :                         trailer[8] = '\0';
     945             :                 } else {
     946           3 :                         s2[stream.total_out + GZIP_HEADER_LENGTH + (coding == CODING_GZIP ? GZIP_FOOTER_LENGTH : 0)] = '\0';
     947             :                 }
     948          37 :                 RETURN_STRINGL(s2, stream.total_out + GZIP_HEADER_LENGTH + (coding == CODING_GZIP ? GZIP_FOOTER_LENGTH : 0), 0);
     949             :         } else {
     950           0 :                 efree(s2);
     951           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
     952           0 :                 RETURN_FALSE;
     953             :         }
     954             : }
     955             : /* }}} */
     956             : 
     957             : /* {{{ php_ob_gzhandler_check
     958             :  */
     959           1 : int php_ob_gzhandler_check(TSRMLS_D)
     960             : {
     961             :         /* check for wrong usages */
     962           1 :         if (OG(ob_nesting_level > 0)) {
     963           1 :                 if (php_ob_handler_used("ob_gzhandler" TSRMLS_CC)) {
     964           0 :                         php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used twice");
     965           0 :                         return FAILURE;
     966             :                 }
     967           1 :                 if (php_ob_handler_used("mb_output_handler" TSRMLS_CC)) {
     968           0 :                         php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used after 'mb_output_handler'");
     969           0 :                         return FAILURE;
     970             :                 }
     971           1 :                 if (php_ob_handler_used("URL-Rewriter" TSRMLS_CC)) {
     972           0 :                         php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used after 'URL-Rewriter'");
     973           0 :                         return FAILURE;
     974             :                 }
     975           1 :                 if (php_ob_init_conflict("ob_gzhandler", "zlib output compression" TSRMLS_CC)) {
     976           1 :                         return FAILURE;
     977             :                 }
     978             :         }
     979             : 
     980           0 :         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           0 : static PHP_FUNCTION(ob_gzhandler)
     988             : {
     989             :         char *string;
     990             :         int string_len;
     991             :         long mode;
     992             :         zval **a_encoding;
     993           0 :         zend_bool return_original = 0;
     994             :         zend_bool do_start, do_end;
     995             : 
     996           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &string, &string_len, &mode) == FAILURE) {
     997           0 :                 return;
     998             :         }
     999             : 
    1000           0 :         if (ZLIBG(ob_gzhandler_status) == -1) {
    1001           0 :                 RETURN_FALSE;
    1002             :         }
    1003             : 
    1004           0 :         zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
    1005             : 
    1006           0 :         if (!PG(http_globals)[TRACK_VARS_SERVER]
    1007           0 :                 || zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING"), (void **) &a_encoding) == FAILURE
    1008             :         ) {
    1009           0 :                 ZLIBG(ob_gzhandler_status) = -1;
    1010           0 :                 RETURN_FALSE;
    1011             :         }
    1012             : 
    1013           0 :         convert_to_string_ex(a_encoding);
    1014           0 :         if (php_memnstr(Z_STRVAL_PP(a_encoding), "gzip", 4, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) {
    1015           0 :                 ZLIBG(compression_coding) = CODING_GZIP;
    1016           0 :         } else if (php_memnstr(Z_STRVAL_PP(a_encoding), "deflate", 7, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) {
    1017           0 :                 ZLIBG(compression_coding) = CODING_DEFLATE;
    1018             :         } else {
    1019           0 :                 ZLIBG(ob_gzhandler_status) = -1;
    1020           0 :                 RETURN_FALSE;
    1021             :         }
    1022             : 
    1023           0 :         do_start = ((mode & PHP_OUTPUT_HANDLER_START) ? 1 : 0);
    1024           0 :         do_end = ((mode & PHP_OUTPUT_HANDLER_END) ? 1 : 0);
    1025           0 :         Z_STRVAL_P(return_value) = NULL;
    1026           0 :         Z_STRLEN_P(return_value) = 0;
    1027             : 
    1028           0 :         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           0 :                 Z_TYPE_P(return_value) = IS_STRING;
    1030           0 :                 if (do_start) {
    1031           0 :                         switch (ZLIBG(compression_coding)) {
    1032             :                                 case CODING_GZIP:
    1033           0 :                                         if (sapi_add_header("Content-Encoding: gzip", sizeof("Content-Encoding: gzip") - 1, 1) == FAILURE) {
    1034           0 :                                                 return_original = 1;
    1035             :                                         }
    1036           0 :                                         if (sapi_add_header_ex("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1, 0 TSRMLS_CC)==FAILURE) {
    1037           0 :                                                 return_original = 1;
    1038             :                                         }
    1039           0 :                                         break;
    1040             :                                 case CODING_DEFLATE:
    1041           0 :                                         if (sapi_add_header("Content-Encoding: deflate", sizeof("Content-Encoding: deflate") - 1, 1) == FAILURE) {
    1042           0 :                                                 return_original = 1;
    1043             :                                         }
    1044           0 :                                         if (sapi_add_header_ex("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1, 0 TSRMLS_CC)==FAILURE) {
    1045           0 :                                                 return_original = 1;
    1046             :                                         }
    1047           0 :                                         break;
    1048             :                                 default:
    1049           0 :                                         return_original = 1;
    1050             :                                         break;
    1051             :                         }
    1052             :                 }
    1053             : 
    1054           0 :                 if (return_original) {
    1055           0 :                         zval_dtor(return_value);
    1056             :                 }
    1057             : 
    1058             :         } else {
    1059           0 :                 return_original = 1;
    1060             :         }
    1061             : 
    1062           0 :         if (return_original) {
    1063             :                 /* return the original string */
    1064           0 :                 RETURN_STRINGL(string, string_len, 1);
    1065             :         }
    1066             : }
    1067             : /* }}} */
    1068             : 
    1069             : /* {{{ php_gzip_output_handler
    1070             :  */
    1071           4 : 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           4 :         if (!ZLIBG(output_compression) || SG(sapi_headers).http_response_code == 204 || SG(sapi_headers).http_response_code == 304) {
    1076           0 :                 *handled_output = NULL;
    1077             :         } else {
    1078           4 :                 do_start = (mode & PHP_OUTPUT_HANDLER_START ? 1 : 0);
    1079           4 :                 do_end = (mode & PHP_OUTPUT_HANDLER_END ? 1 : 0);
    1080             : 
    1081           4 :                 if (do_start) {
    1082           7 :                         if (!SG(headers_sent) && !SG(request_info).no_headers) {
    1083           3 :                                 switch (ZLIBG(compression_coding)) {
    1084             :                                         case CODING_GZIP:
    1085           3 :                                                 sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1 TSRMLS_CC);
    1086           3 :                                                 break;
    1087             :                                         case CODING_DEFLATE:
    1088           0 :                                                 sapi_add_header_ex(ZEND_STRL("Content-Encoding: deflate"), 1, 1 TSRMLS_CC);
    1089             :                                                 break;
    1090             :                                 }
    1091           3 :                                 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           1 :                                 ZLIBG(output_compression) = 0;
    1095           1 :                                 *handled_output = NULL;
    1096           1 :                                 return;
    1097             :                         }
    1098             :                 }
    1099             : 
    1100           3 :                 if (php_deflate_string(output, output_len, handled_output, handled_output_len, do_start, do_end TSRMLS_CC) != SUCCESS) {
    1101           0 :                         zend_error(E_ERROR, "Compression failed");
    1102             :                 }
    1103             :         }
    1104             : }
    1105             : /* }}} */
    1106             : 
    1107             : /* {{{ php_enable_output_compression
    1108             :  */
    1109           7 : static int php_enable_output_compression(int buffer_size TSRMLS_DC)
    1110             : {
    1111             :         zval **a_encoding;
    1112             : 
    1113           7 :         zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
    1114             : 
    1115          14 :         if (!PG(http_globals)[TRACK_VARS_SERVER]
    1116           7 :                 || zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING"), (void **) &a_encoding) == FAILURE
    1117             :         ) {
    1118           3 :                 return FAILURE;
    1119             :         }
    1120             : 
    1121           4 :         convert_to_string_ex(a_encoding);
    1122             : 
    1123           4 :         if (php_memnstr(Z_STRVAL_PP(a_encoding), "gzip", 4, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) {
    1124           4 :                 ZLIBG(compression_coding) = CODING_GZIP;
    1125           0 :         } else if (php_memnstr(Z_STRVAL_PP(a_encoding), "deflate", 7, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) {
    1126           0 :                 ZLIBG(compression_coding) = CODING_DEFLATE;
    1127             :         } else {
    1128           0 :                 return FAILURE;
    1129             :         }
    1130             : 
    1131           4 :         php_ob_set_internal_handler(php_gzip_output_handler, (uint)buffer_size, "zlib output compression", 0 TSRMLS_CC);
    1132             : 
    1133           4 :         if (ZLIBG(output_handler) && strlen(ZLIBG(output_handler))) {
    1134           0 :                 php_start_ob_buffer_named(ZLIBG(output_handler), 0, 1 TSRMLS_CC);
    1135             :         }
    1136           4 :         return SUCCESS;
    1137             : }
    1138             : /* }}} */
    1139             : 
    1140             : /* {{{ php_zlib_output_compression_start() */
    1141       19328 : static int php_zlib_output_compression_start(TSRMLS_D)
    1142             : {
    1143       19328 :         switch (ZLIBG(output_compression)) {
    1144             :                 case 0:
    1145       19321 :                         break;
    1146             :                 case 1:
    1147           6 :                         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           7 :                         if (ZLIBG(compression_coding) == 0) {
    1152           7 :                                 return php_enable_output_compression(ZLIBG(output_compression) TSRMLS_CC);
    1153             :                         }
    1154             :         }
    1155       19321 :         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             :  */

Generated by: LCOV version 1.10

Generated at Fri, 18 Apr 2014 07:01:38 +0000 (2 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.