stas Mon, 26 Dec 2011 08:29:11 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=321406
Log: fix bug #60326 - restore ob_gzhandler Bug: https://bugs.php.net/60326 (error getting bug information) Changed paths: U php/php-src/branches/PHP_5_4/ext/zlib/php_zlib.h U php/php-src/branches/PHP_5_4/ext/zlib/zlib.c U php/php-src/trunk/ext/zlib/php_zlib.h U php/php-src/trunk/ext/zlib/zlib.c
Modified: php/php-src/branches/PHP_5_4/ext/zlib/php_zlib.h =================================================================== --- php/php-src/branches/PHP_5_4/ext/zlib/php_zlib.h 2011-12-26 05:08:09 UTC (rev 321405) +++ php/php-src/branches/PHP_5_4/ext/zlib/php_zlib.h 2011-12-26 08:29:11 UTC (rev 321406) @@ -13,7 +13,7 @@ | lice...@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf <ras...@lerdorf.on.ca> | - | Stefan Röhrich <s...@linux.de> | + | Stefan R�hrich <s...@linux.de> | | Michael Wallner <m...@php.net> | +----------------------------------------------------------------------+ */ @@ -34,14 +34,6 @@ #define PHP_ZLIB_OUTPUT_HANDLER_NAME "zlib output compression" #define PHP_ZLIB_BUFFER_SIZE_GUESS(in_len) (((size_t) ((double) in_len * (double) 1.015)) + 10 + 8 + 4 + 1) -ZEND_BEGIN_MODULE_GLOBALS(zlib) - /* variables for transparent gzip encoding */ - int compression_coding; - long output_compression; - long output_compression_level; - char *output_handler; -ZEND_END_MODULE_GLOBALS(zlib); - typedef struct _php_zlib_buffer { char *data; char *aptr; @@ -55,6 +47,15 @@ php_zlib_buffer buffer; } php_zlib_context; +ZEND_BEGIN_MODULE_GLOBALS(zlib) + /* variables for transparent gzip encoding */ + int compression_coding; + long output_compression; + long output_compression_level; + char *output_handler; + php_zlib_context *ob_gzhandler; +ZEND_END_MODULE_GLOBALS(zlib); + php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); extern php_stream_ops php_stream_gzio_ops; extern php_stream_wrapper php_stream_gzip_wrapper; Modified: php/php-src/branches/PHP_5_4/ext/zlib/zlib.c =================================================================== --- php/php-src/branches/PHP_5_4/ext/zlib/zlib.c 2011-12-26 05:08:09 UTC (rev 321405) +++ php/php-src/branches/PHP_5_4/ext/zlib/zlib.c 2011-12-26 08:29:11 UTC (rev 321406) @@ -13,7 +13,7 @@ | lice...@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf <ras...@lerdorf.on.ca> | - | Stefan Röhrich <s...@linux.de> | + | Stefan Röhrich <s...@linux.de> | | Zeev Suraski <z...@zend.com> | | Jade Nicoletti <nicole...@nns.ch> | | Michael Wallner <m...@php.net> | @@ -84,30 +84,12 @@ } /* }}} */ -/* {{{ php_zlib_output_handler() */ -static int php_zlib_output_handler(void **handler_context, php_output_context *output_context) +/* {{{ php_zlib_output_handler_ex() */ +static int php_zlib_output_handler_ex(php_zlib_context *ctx, php_output_context *output_context) { - php_zlib_context *ctx = *(php_zlib_context **) handler_context; int flags = Z_SYNC_FLUSH; PHP_OUTPUT_TSRMLS(output_context); - if (!php_zlib_output_encoding(TSRMLS_C)) { - /* "Vary: Accept-Encoding" header sent along uncompressed content breaks caching in MSIE, - so let's just send it with successfully compressed content or unless the complete - buffer gets discarded, see http://bugs.php.net/40325; - - Test as follows: - +Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";' - +Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";' - -Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();' - -Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();' - */ - if (output_context->op != (PHP_OUTPUT_HANDLER_START|PHP_OUTPUT_HANDLER_CLEAN|PHP_OUTPUT_HANDLER_FINAL)) { - sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 1 TSRMLS_CC); - } - return FAILURE; - } - if (output_context->op & PHP_OUTPUT_HANDLER_START) { /* start up */ if (Z_OK != deflateInit2(&ctx->Z, ZLIBG(output_compression_level), Z_DEFLATED, ZLIBG(compression_coding), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) { @@ -179,38 +161,86 @@ return FAILURE; } - php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS, &flags TSRMLS_CC); - if (!(flags & PHP_OUTPUT_HANDLER_STARTED)) { - if (SG(headers_sent) || !ZLIBG(output_compression)) { - deflateEnd(&ctx->Z); - return FAILURE; - } - switch (ZLIBG(compression_coding)) { - case PHP_ZLIB_ENCODING_GZIP: - sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1 TSRMLS_CC); - break; - case PHP_ZLIB_ENCODING_DEFLATE: - sapi_add_header_ex(ZEND_STRL("Content-Encoding: deflate"), 1, 1 TSRMLS_CC); - break; - default: + if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) { + deflateEnd(&ctx->Z); + } + } + + return SUCCESS; +} +/* }}} */ + +/* {{{ php_zlib_output_handler() */ +static int php_zlib_output_handler(void **handler_context, php_output_context *output_context) +{ + php_zlib_context *ctx = *(php_zlib_context **) handler_context; + PHP_OUTPUT_TSRMLS(output_context); + + if (!php_zlib_output_encoding(TSRMLS_C)) { + /* "Vary: Accept-Encoding" header sent along uncompressed content breaks caching in MSIE, + so let's just send it with successfully compressed content or unless the complete + buffer gets discarded, see http://bugs.php.net/40325; + + Test as follows: + +Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";' + +Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";' + -Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();' + -Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();' + */ + if (output_context->op != (PHP_OUTPUT_HANDLER_START|PHP_OUTPUT_HANDLER_CLEAN|PHP_OUTPUT_HANDLER_FINAL)) { + sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 1 TSRMLS_CC); + } + return FAILURE; + } + + if (SUCCESS != php_zlib_output_handler_ex(ctx, output_context)) { + return FAILURE; + } + + if (!(output_context->op & PHP_OUTPUT_HANDLER_CLEAN)) { + int flags; + + if (SUCCESS == php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS, &flags TSRMLS_CC)) { + /* only run this once */ + if (!(flags & PHP_OUTPUT_HANDLER_STARTED)) { + if (SG(headers_sent) || !ZLIBG(output_compression)) { deflateEnd(&ctx->Z); return FAILURE; + } + switch (ZLIBG(compression_coding)) { + case PHP_ZLIB_ENCODING_GZIP: + sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1 TSRMLS_CC); + break; + case PHP_ZLIB_ENCODING_DEFLATE: + sapi_add_header_ex(ZEND_STRL("Content-Encoding: deflate"), 1, 1 TSRMLS_CC); + break; + default: + deflateEnd(&ctx->Z); + return FAILURE; + } + sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 1 TSRMLS_CC); + php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL TSRMLS_CC); } - sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 1 TSRMLS_CC); - php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL TSRMLS_CC); } + } - if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) { - deflateEnd(&ctx->Z); - } - } return SUCCESS; } /* }}} */ -/* {{{ php_zlib_output_handler_dtor() */ -static void php_zlib_output_handler_dtor(void *opaq TSRMLS_DC) +/* {{{ php_zlib_output_handler_context_init() */ +static php_zlib_context *php_zlib_output_handler_context_init(TSRMLS_D) { + php_zlib_context *ctx = (php_zlib_context *) ecalloc(1, sizeof(php_zlib_context)); + ctx->Z.zalloc = php_zlib_alloc; + ctx->Z.zfree = php_zlib_free; + return ctx; +} +/* }}} */ + +/* {{{ php_zlib_output_handler_context_dtor() */ +static void php_zlib_output_handler_context_dtor(void *opaq TSRMLS_DC) +{ php_zlib_context *ctx = (php_zlib_context *) opaq; if (ctx) { @@ -226,17 +256,13 @@ static php_output_handler *php_zlib_output_handler_init(const char *handler_name, size_t handler_name_len, size_t chunk_size, int flags TSRMLS_DC) { php_output_handler *h = NULL; - php_zlib_context *ctx; if (!ZLIBG(output_compression)) { ZLIBG(output_compression) = chunk_size ? chunk_size : PHP_OUTPUT_HANDLER_DEFAULT_SIZE; } if ((h = php_output_handler_create_internal(handler_name, handler_name_len, php_zlib_output_handler, chunk_size, flags TSRMLS_CC))) { - ctx = (php_zlib_context *) ecalloc(1, sizeof(php_zlib_context)); - ctx->Z.zalloc = php_zlib_alloc; - ctx->Z.zfree = php_zlib_free; - php_output_handler_set_context(h, ctx, php_zlib_output_handler_dtor TSRMLS_CC); + php_output_handler_set_context(h, php_zlib_output_handler_context_init(TSRMLS_C), php_zlib_output_handler_context_dtor TSRMLS_CC); } return h; @@ -401,6 +427,85 @@ } /* }}} */ +/* {{{ php_zlib_cleanup_ob_gzhandler_mess() */ +static void php_zlib_cleanup_ob_gzhandler_mess(TSRMLS_D) +{ + if (ZLIBG(ob_gzhandler)) { + deflateEnd(&(ZLIBG(ob_gzhandler)->Z)); + php_zlib_output_handler_context_dtor(ZLIBG(ob_gzhandler)); + ZLIBG(ob_gzhandler) = NULL; + } +} +/* }}} */ + +/* {{{ proto string ob_gzhandler(string data, int flags) + Legacy hack */ +static PHP_FUNCTION(ob_gzhandler) +{ + char *in_str; + int in_len; + long flags = 0; + php_output_context ctx = {0}; + int encoding, rv; + + /* + * NOTE that the real ob_gzhandler is an alias to "zlib output compression". + * This is a really bad hack, because + * - we have to initialize a php_zlib_context on demand + * - we have to clean it up in RSHUTDOWN + * - OG(running) is not set or set to any other output handler + * - we have to mess around with php_output_context */ + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &in_str, &in_len, &flags)) { + RETURN_FALSE; + } + + if (!(encoding = php_zlib_output_encoding(TSRMLS_C))) { + RETURN_FALSE; + } + + if (flags & PHP_OUTPUT_HANDLER_START) { + switch (encoding) { + case PHP_ZLIB_ENCODING_GZIP: + sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1 TSRMLS_CC); + break; + case PHP_ZLIB_ENCODING_DEFLATE: + sapi_add_header_ex(ZEND_STRL("Content-Encoding: deflate"), 1, 1 TSRMLS_CC); + break; + } + sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 1 TSRMLS_CC); + } + + if (!ZLIBG(ob_gzhandler)) { + ZLIBG(ob_gzhandler) = php_zlib_output_handler_context_init(TSRMLS_C); + } + + TSRMLS_SET_CTX(ctx.tsrm_ls); + ctx.op = flags; + ctx.in.data = in_str; + ctx.in.used = in_len; + + rv = php_zlib_output_handler_ex(ZLIBG(ob_gzhandler), &ctx); + + if (SUCCESS != rv) { + if (ctx.out.data && ctx.out.free) { + efree(ctx.out.data); + } + php_zlib_cleanup_ob_gzhandler_mess(TSRMLS_C); + RETURN_FALSE; + } + + if (ctx.out.data) { + RETVAL_STRINGL(ctx.out.data, ctx.out.used, 1); + if (ctx.out.free) { + efree(ctx.out.data); + } + } else { + RETVAL_EMPTY_STRING(); + } +} +/* }}} */ + /* {{{ proto string zlib_get_coding_type(void) Returns the coding type used for output compression */ static PHP_FUNCTION(zlib_get_coding_type) @@ -615,6 +720,11 @@ #endif /* {{{ arginfo */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_ob_gzhandler, 0, 0, 2) + ZEND_ARG_INFO(0, data) + ZEND_ARG_INFO(0, flags) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(arginfo_zlib_get_coding_type, 0) ZEND_END_ARG_INFO() @@ -737,6 +847,7 @@ PHP_FE(zlib_encode, arginfo_zlib_encode) PHP_FE(zlib_decode, arginfo_zlib_decode) PHP_FE(zlib_get_coding_type, arginfo_zlib_get_coding_type) + PHP_FE(ob_gzhandler, arginfo_ob_gzhandler) PHP_FE_END }; /* }}} */ @@ -859,6 +970,8 @@ { ZLIBG(output_compression) = 0; + php_zlib_cleanup_ob_gzhandler_mess(TSRMLS_C); + return SUCCESS; } Modified: php/php-src/trunk/ext/zlib/php_zlib.h =================================================================== --- php/php-src/trunk/ext/zlib/php_zlib.h 2011-12-26 05:08:09 UTC (rev 321405) +++ php/php-src/trunk/ext/zlib/php_zlib.h 2011-12-26 08:29:11 UTC (rev 321406) @@ -13,7 +13,7 @@ | lice...@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf <ras...@lerdorf.on.ca> | - | Stefan Röhrich <s...@linux.de> | + | Stefan R�hrich <s...@linux.de> | | Michael Wallner <m...@php.net> | +----------------------------------------------------------------------+ */ @@ -34,14 +34,6 @@ #define PHP_ZLIB_OUTPUT_HANDLER_NAME "zlib output compression" #define PHP_ZLIB_BUFFER_SIZE_GUESS(in_len) (((size_t) ((double) in_len * (double) 1.015)) + 10 + 8 + 4 + 1) -ZEND_BEGIN_MODULE_GLOBALS(zlib) - /* variables for transparent gzip encoding */ - int compression_coding; - long output_compression; - long output_compression_level; - char *output_handler; -ZEND_END_MODULE_GLOBALS(zlib); - typedef struct _php_zlib_buffer { char *data; char *aptr; @@ -55,6 +47,15 @@ php_zlib_buffer buffer; } php_zlib_context; +ZEND_BEGIN_MODULE_GLOBALS(zlib) + /* variables for transparent gzip encoding */ + int compression_coding; + long output_compression; + long output_compression_level; + char *output_handler; + php_zlib_context *ob_gzhandler; +ZEND_END_MODULE_GLOBALS(zlib); + php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); extern php_stream_ops php_stream_gzio_ops; extern php_stream_wrapper php_stream_gzip_wrapper; Modified: php/php-src/trunk/ext/zlib/zlib.c =================================================================== --- php/php-src/trunk/ext/zlib/zlib.c 2011-12-26 05:08:09 UTC (rev 321405) +++ php/php-src/trunk/ext/zlib/zlib.c 2011-12-26 08:29:11 UTC (rev 321406) @@ -13,7 +13,7 @@ | lice...@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf <ras...@lerdorf.on.ca> | - | Stefan Röhrich <s...@linux.de> | + | Stefan R�hrich <s...@linux.de> | | Zeev Suraski <z...@zend.com> | | Jade Nicoletti <nicole...@nns.ch> | | Michael Wallner <m...@php.net> | @@ -84,30 +84,12 @@ } /* }}} */ -/* {{{ php_zlib_output_handler() */ -static int php_zlib_output_handler(void **handler_context, php_output_context *output_context) +/* {{{ php_zlib_output_handler_ex() */ +static int php_zlib_output_handler_ex(php_zlib_context *ctx, php_output_context *output_context) { - php_zlib_context *ctx = *(php_zlib_context **) handler_context; int flags = Z_SYNC_FLUSH; PHP_OUTPUT_TSRMLS(output_context); - if (!php_zlib_output_encoding(TSRMLS_C)) { - /* "Vary: Accept-Encoding" header sent along uncompressed content breaks caching in MSIE, - so let's just send it with successfully compressed content or unless the complete - buffer gets discarded, see http://bugs.php.net/40325; - - Test as follows: - +Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";' - +Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";' - -Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();' - -Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();' - */ - if (output_context->op != (PHP_OUTPUT_HANDLER_START|PHP_OUTPUT_HANDLER_CLEAN|PHP_OUTPUT_HANDLER_FINAL)) { - sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 1 TSRMLS_CC); - } - return FAILURE; - } - if (output_context->op & PHP_OUTPUT_HANDLER_START) { /* start up */ if (Z_OK != deflateInit2(&ctx->Z, ZLIBG(output_compression_level), Z_DEFLATED, ZLIBG(compression_coding), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) { @@ -179,38 +161,86 @@ return FAILURE; } - php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS, &flags TSRMLS_CC); - if (!(flags & PHP_OUTPUT_HANDLER_STARTED)) { - if (SG(headers_sent) || !ZLIBG(output_compression)) { - deflateEnd(&ctx->Z); - return FAILURE; - } - switch (ZLIBG(compression_coding)) { - case PHP_ZLIB_ENCODING_GZIP: - sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1 TSRMLS_CC); - break; - case PHP_ZLIB_ENCODING_DEFLATE: - sapi_add_header_ex(ZEND_STRL("Content-Encoding: deflate"), 1, 1 TSRMLS_CC); - break; - default: + if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) { + deflateEnd(&ctx->Z); + } + } + + return SUCCESS; +} +/* }}} */ + +/* {{{ php_zlib_output_handler() */ +static int php_zlib_output_handler(void **handler_context, php_output_context *output_context) +{ + php_zlib_context *ctx = *(php_zlib_context **) handler_context; + PHP_OUTPUT_TSRMLS(output_context); + + if (!php_zlib_output_encoding(TSRMLS_C)) { + /* "Vary: Accept-Encoding" header sent along uncompressed content breaks caching in MSIE, + so let's just send it with successfully compressed content or unless the complete + buffer gets discarded, see http://bugs.php.net/40325; + + Test as follows: + +Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";' + +Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";' + -Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();' + -Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();' + */ + if (output_context->op != (PHP_OUTPUT_HANDLER_START|PHP_OUTPUT_HANDLER_CLEAN|PHP_OUTPUT_HANDLER_FINAL)) { + sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 1 TSRMLS_CC); + } + return FAILURE; + } + + if (SUCCESS != php_zlib_output_handler_ex(ctx, output_context)) { + return FAILURE; + } + + if (!(output_context->op & PHP_OUTPUT_HANDLER_CLEAN)) { + int flags; + + if (SUCCESS == php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS, &flags TSRMLS_CC)) { + /* only run this once */ + if (!(flags & PHP_OUTPUT_HANDLER_STARTED)) { + if (SG(headers_sent) || !ZLIBG(output_compression)) { deflateEnd(&ctx->Z); return FAILURE; + } + switch (ZLIBG(compression_coding)) { + case PHP_ZLIB_ENCODING_GZIP: + sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1 TSRMLS_CC); + break; + case PHP_ZLIB_ENCODING_DEFLATE: + sapi_add_header_ex(ZEND_STRL("Content-Encoding: deflate"), 1, 1 TSRMLS_CC); + break; + default: + deflateEnd(&ctx->Z); + return FAILURE; + } + sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 1 TSRMLS_CC); + php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL TSRMLS_CC); } - sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 1 TSRMLS_CC); - php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL TSRMLS_CC); } + } - if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) { - deflateEnd(&ctx->Z); - } - } return SUCCESS; } /* }}} */ -/* {{{ php_zlib_output_handler_dtor() */ -static void php_zlib_output_handler_dtor(void *opaq TSRMLS_DC) +/* {{{ php_zlib_output_handler_context_init() */ +static php_zlib_context *php_zlib_output_handler_context_init(TSRMLS_D) { + php_zlib_context *ctx = (php_zlib_context *) ecalloc(1, sizeof(php_zlib_context)); + ctx->Z.zalloc = php_zlib_alloc; + ctx->Z.zfree = php_zlib_free; + return ctx; +} +/* }}} */ + +/* {{{ php_zlib_output_handler_context_dtor() */ +static void php_zlib_output_handler_context_dtor(void *opaq TSRMLS_DC) +{ php_zlib_context *ctx = (php_zlib_context *) opaq; if (ctx) { @@ -226,17 +256,13 @@ static php_output_handler *php_zlib_output_handler_init(const char *handler_name, size_t handler_name_len, size_t chunk_size, int flags TSRMLS_DC) { php_output_handler *h = NULL; - php_zlib_context *ctx; if (!ZLIBG(output_compression)) { ZLIBG(output_compression) = chunk_size ? chunk_size : PHP_OUTPUT_HANDLER_DEFAULT_SIZE; } if ((h = php_output_handler_create_internal(handler_name, handler_name_len, php_zlib_output_handler, chunk_size, flags TSRMLS_CC))) { - ctx = (php_zlib_context *) ecalloc(1, sizeof(php_zlib_context)); - ctx->Z.zalloc = php_zlib_alloc; - ctx->Z.zfree = php_zlib_free; - php_output_handler_set_context(h, ctx, php_zlib_output_handler_dtor TSRMLS_CC); + php_output_handler_set_context(h, php_zlib_output_handler_context_init(TSRMLS_C), php_zlib_output_handler_context_dtor TSRMLS_CC); } return h; @@ -401,6 +427,85 @@ } /* }}} */ +/* {{{ php_zlib_cleanup_ob_gzhandler_mess() */ +static void php_zlib_cleanup_ob_gzhandler_mess(TSRMLS_D) +{ + if (ZLIBG(ob_gzhandler)) { + deflateEnd(&(ZLIBG(ob_gzhandler)->Z)); + php_zlib_output_handler_context_dtor(ZLIBG(ob_gzhandler)); + ZLIBG(ob_gzhandler) = NULL; + } +} +/* }}} */ + +/* {{{ proto string ob_gzhandler(string data, int flags) + Legacy hack */ +static PHP_FUNCTION(ob_gzhandler) +{ + char *in_str; + int in_len; + long flags = 0; + php_output_context ctx = {0}; + int encoding, rv; + + /* + * NOTE that the real ob_gzhandler is an alias to "zlib output compression". + * This is a really bad hack, because + * - we have to initialize a php_zlib_context on demand + * - we have to clean it up in RSHUTDOWN + * - OG(running) is not set or set to any other output handler + * - we have to mess around with php_output_context */ + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &in_str, &in_len, &flags)) { + RETURN_FALSE; + } + + if (!(encoding = php_zlib_output_encoding(TSRMLS_C))) { + RETURN_FALSE; + } + + if (flags & PHP_OUTPUT_HANDLER_START) { + switch (encoding) { + case PHP_ZLIB_ENCODING_GZIP: + sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1 TSRMLS_CC); + break; + case PHP_ZLIB_ENCODING_DEFLATE: + sapi_add_header_ex(ZEND_STRL("Content-Encoding: deflate"), 1, 1 TSRMLS_CC); + break; + } + sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 1 TSRMLS_CC); + } + + if (!ZLIBG(ob_gzhandler)) { + ZLIBG(ob_gzhandler) = php_zlib_output_handler_context_init(TSRMLS_C); + } + + TSRMLS_SET_CTX(ctx.tsrm_ls); + ctx.op = flags; + ctx.in.data = in_str; + ctx.in.used = in_len; + + rv = php_zlib_output_handler_ex(ZLIBG(ob_gzhandler), &ctx); + + if (SUCCESS != rv) { + if (ctx.out.data && ctx.out.free) { + efree(ctx.out.data); + } + php_zlib_cleanup_ob_gzhandler_mess(TSRMLS_C); + RETURN_FALSE; + } + + if (ctx.out.data) { + RETVAL_STRINGL(ctx.out.data, ctx.out.used, 1); + if (ctx.out.free) { + efree(ctx.out.data); + } + } else { + RETVAL_EMPTY_STRING(); + } +} +/* }}} */ + /* {{{ proto string zlib_get_coding_type(void) Returns the coding type used for output compression */ static PHP_FUNCTION(zlib_get_coding_type) @@ -615,6 +720,11 @@ #endif /* {{{ arginfo */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_ob_gzhandler, 0, 0, 2) + ZEND_ARG_INFO(0, data) + ZEND_ARG_INFO(0, flags) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(arginfo_zlib_get_coding_type, 0) ZEND_END_ARG_INFO() @@ -737,6 +847,7 @@ PHP_FE(zlib_encode, arginfo_zlib_encode) PHP_FE(zlib_decode, arginfo_zlib_decode) PHP_FE(zlib_get_coding_type, arginfo_zlib_get_coding_type) + PHP_FE(ob_gzhandler, arginfo_ob_gzhandler) PHP_FE_END }; /* }}} */ @@ -859,6 +970,8 @@ { ZLIBG(output_compression) = 0; + php_zlib_cleanup_ob_gzhandler_mess(TSRMLS_C); + return SUCCESS; }
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php