Diff for /embedaddon/php/ext/zlib/zlib.c between versions 1.1.1.1 and 1.1.1.5

version 1.1.1.1, 2012/02/21 23:48:05 version 1.1.1.5, 2014/06/15 20:04:01
Line 2 Line 2
    +----------------------------------------------------------------------+     +----------------------------------------------------------------------+
    | PHP Version 5                                                        |     | PHP Version 5                                                        |
    +----------------------------------------------------------------------+     +----------------------------------------------------------------------+
   | Copyright (c) 1997-2012 The PHP Group                                |   | Copyright (c) 1997-2014 The PHP Group                                |
    +----------------------------------------------------------------------+     +----------------------------------------------------------------------+
    | This source file is subject to version 3.01 of the PHP license,      |     | This source file is subject to version 3.01 of the PHP license,      |
    | that is bundled with this package in the file LICENSE, and is        |     | that is bundled with this package in the file LICENSE, and is        |
Line 13 Line 13
    | license@php.net so we can mail you a copy immediately.               |     | license@php.net so we can mail you a copy immediately.               |
    +----------------------------------------------------------------------+     +----------------------------------------------------------------------+
    | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca>                       |     | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca>                       |
   |          Stefan Rhrich <sr@linux.de>                                |   |          Stefan Rรถhrich <sr@linux.de>                                |
    |          Zeev Suraski <zeev@zend.com>                                |     |          Zeev Suraski <zeev@zend.com>                                |
    |          Jade Nicoletti <nicoletti@nns.ch>                           |     |          Jade Nicoletti <nicoletti@nns.ch>                           |
      |          Michael Wallner <mike@php.net>                              |
    +----------------------------------------------------------------------+     +----------------------------------------------------------------------+
  */   */
   
Line 28 Line 29
 #include "php.h"  #include "php.h"
 #include "SAPI.h"  #include "SAPI.h"
 #include "php_ini.h"  #include "php_ini.h"
   
 #include <stdlib.h>  
 #include <errno.h>  
 #include <sys/types.h>  
 #include <sys/stat.h>  
 #include <fcntl.h>  
   
 #ifdef PHP_WIN32  
 # define O_RDONLY _O_RDONLY  
 # include "win32/param.h"  
 #else  
 # include <sys/param.h>  
 /* #include <sys/uio.h> */  
 #endif  
   
 #include "ext/standard/head.h"  
 #include "safe_mode.h"  
 #include "ext/standard/php_standard.h"  
 #include "ext/standard/info.h"  #include "ext/standard/info.h"
   #include "ext/standard/file.h"
   #include "ext/standard/php_string.h"
 #include "php_zlib.h"  #include "php_zlib.h"
 #include "fopen_wrappers.h"  
   
#if HAVE_PWD_HZEND_DECLARE_MODULE_GLOBALS(zlib);
# ifdef PHP_WIN32 
#  include "win32/pwd.h" 
# else 
#  include <pwd.h> 
# endif 
#endif 
   
#if defined(HAVE_UNISTD_H) && defined(PHP_WIN32)/* {{{ Memory management wrappers */
# undef HAVE_UNISTD_H 
#endif 
   
#ifdef COMPILE_DL_ZLIBstatic voidpf php_zlib_alloc(voidpf opaque, uInt items, uInt size)
# ifndef PUTS{
#  define PUTS(a) php_printf("%s",a)        return (voidpf)safe_emalloc(items, size, 0);
# endif}
# ifndef PUTC 
#  define PUTC(a) PUTS(a) 
# endif 
# ifndef PHPWRITE 
#  define PHPWRITE(a,n) php_write((a),(n) TSRMLS_CC) 
# endif 
#endif 
   
/* Win32 needs some more memory */static void php_zlib_free(voidpf opaque, voidpf address)
#ifdef PHP_WIN32{
# define PHP_ZLIB_MODIFIER 100        efree((void*)address);
#else}
# define PHP_ZLIB_MODIFIER 1000/* }}} */
#endif 
   
#define OS_CODE                 0x03 /* FIXME *//* {{{ php_zlib_output_conflict_check() */
#define GZIP_HEADER_LENGTH              10static int php_zlib_output_conflict_check(const char *handler_name, size_t handler_name_len TSRMLS_DC)
#define GZIP_FOOTER_LENGTH              8{
         if (php_output_get_level(TSRMLS_C) > 0) {
                 if (php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME) TSRMLS_CC)
                 ||      php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL("ob_gzhandler") TSRMLS_CC)
                 ||  php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL("mb_output_handler") TSRMLS_CC)
                 ||      php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL("URL-Rewriter") TSRMLS_CC)) {
                         return FAILURE;
                 }
         }
         return SUCCESS;
 }
 /* }}} */
   
/* True globals, no need for thread safety *//* {{{ php_zlib_output_encoding() */
static const int gz_magic[2] = {0x1f, 0x8b};     /* gzip magic header */static int php_zlib_output_encoding(TSRMLS_D)
 {
         zval **enc;
   
static int php_zlib_output_compression_start(TSRMLS_D);        if (!ZLIBG(compression_coding)) {
                 zend_is_auto_global(ZEND_STRL("_SERVER") TSRMLS_CC);
                 if (PG(http_globals)[TRACK_VARS_SERVER] && SUCCESS == zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING"), (void *) &enc)) {
                         convert_to_string(*enc);
                         if (strstr(Z_STRVAL_PP(enc), "gzip")) {
                                 ZLIBG(compression_coding) = PHP_ZLIB_ENCODING_GZIP;
                         } else if (strstr(Z_STRVAL_PP(enc), "deflate")) {
                                 ZLIBG(compression_coding) = PHP_ZLIB_ENCODING_DEFLATE;
                         }
                 }
         }
         return ZLIBG(compression_coding);
 }
 /* }}} */
   
static PHP_MINIT_FUNCTION(zlib);/* {{{ php_zlib_output_handler_ex() */
static PHP_MSHUTDOWN_FUNCTION(zlib);static int php_zlib_output_handler_ex(php_zlib_context *ctx, php_output_context *output_context)
static PHP_RINIT_FUNCTION(zlib);{
static PHP_MINFO_FUNCTION(zlib);        int flags = Z_SYNC_FLUSH;
static PHP_FUNCTION(gzopen);        PHP_OUTPUT_TSRMLS(output_context);
static PHP_FUNCTION(readgzfile); 
static PHP_FUNCTION(gzfile); 
static PHP_FUNCTION(gzcompress); 
static PHP_FUNCTION(gzuncompress); 
static PHP_FUNCTION(gzdeflate); 
static PHP_FUNCTION(gzinflate); 
static PHP_FUNCTION(gzencode); 
static PHP_FUNCTION(ob_gzhandler); 
static PHP_FUNCTION(zlib_get_coding_type); 
   
/* {{{ arginfo */        if (output_context->op & PHP_OUTPUT_HANDLER_START) {
ZEND_BEGIN_ARG_INFO_EX(arginfo_gzfile, 0, 0, 1)                /* start up */
        ZEND_ARG_INFO(0, filename)                if (Z_OK != deflateInit2(&ctx->Z, ZLIBG(output_compression_level), Z_DEFLATED, ZLIBG(compression_coding), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) {
        ZEND_ARG_INFO(0, use_include_path)                        return FAILURE;
ZEND_END_ARG_INFO()                }
         }
   
ZEND_BEGIN_ARG_INFO_EX(arginfo_gzopen, 0, 0, 2)        if (output_context->op & PHP_OUTPUT_HANDLER_CLEAN) {
        ZEND_ARG_INFO(0, filename)                /* free buffers */
        ZEND_ARG_INFO(0, mode)                deflateEnd(&ctx->Z);
        ZEND_ARG_INFO(0, use_include_path) 
ZEND_END_ARG_INFO() 
   
ZEND_BEGIN_ARG_INFO_EX(arginfo_readgzfile, 0, 0, 1)                if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) {
        ZEND_ARG_INFO(0, filename)                        /* discard */
        ZEND_ARG_INFO(0, use_include_path)                        return SUCCESS;
ZEND_END_ARG_INFO()                } else {
                         /* restart */
                         if (Z_OK != deflateInit2(&ctx->Z, ZLIBG(output_compression_level), Z_DEFLATED, ZLIBG(compression_coding), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) {
                                 return FAILURE;
                         }
                         ctx->buffer.used = 0;
                 }
         } else {
                 if (output_context->in.used) {
                         /* append input */
                         if (ctx->buffer.free < output_context->in.used) {
                                 if (!(ctx->buffer.aptr = erealloc_recoverable(ctx->buffer.data, ctx->buffer.used + ctx->buffer.free + output_context->in.used))) {
                                         deflateEnd(&ctx->Z);
                                         return FAILURE;
                                 }
                                 ctx->buffer.data = ctx->buffer.aptr;
                                 ctx->buffer.free += output_context->in.used;
                         }
                         memcpy(ctx->buffer.data + ctx->buffer.used, output_context->in.data, output_context->in.used);
                         ctx->buffer.free -= output_context->in.used;
                         ctx->buffer.used += output_context->in.used;
                 }
                 output_context->out.size = PHP_ZLIB_BUFFER_SIZE_GUESS(output_context->in.used);
                 output_context->out.data = emalloc(output_context->out.size);
                 output_context->out.free = 1;
                 output_context->out.used = 0;
   
ZEND_BEGIN_ARG_INFO_EX(arginfo_gzcompress, 0, 0, 1)                ctx->Z.avail_in = ctx->buffer.used;
        ZEND_ARG_INFO(0, data)                ctx->Z.next_in = (Bytef *) ctx->buffer.data;
        ZEND_ARG_INFO(0, level)                ctx->Z.avail_out = output_context->out.size;
ZEND_END_ARG_INFO()                ctx->Z.next_out = (Bytef *) output_context->out.data;
   
ZEND_BEGIN_ARG_INFO_EX(arginfo_gzuncompress, 0, 0, 1)                if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) {
        ZEND_ARG_INFO(0, data)                        flags = Z_FINISH;
        ZEND_ARG_INFO(0, length)                } else if (output_context->op & PHP_OUTPUT_HANDLER_FLUSH) {
ZEND_END_ARG_INFO()                        flags = Z_FULL_FLUSH;
                 }
   
ZEND_BEGIN_ARG_INFO_EX(arginfo_gzdeflate, 0, 0, 1)                switch (deflate(&ctx->Z, flags)) {
        ZEND_ARG_INFO(0, data)                        case Z_OK:
        ZEND_ARG_INFO(0, level)                                if (flags == Z_FINISH) {
ZEND_END_ARG_INFO()                                        deflateEnd(&ctx->Z);
                                         return FAILURE;
                                 }
                         case Z_STREAM_END:
                                 if (ctx->Z.avail_in) {
                                         memmove(ctx->buffer.data, ctx->buffer.data + ctx->buffer.used - ctx->Z.avail_in, ctx->Z.avail_in);
                                 }
                                 ctx->buffer.free += ctx->buffer.used - ctx->Z.avail_in;
                                 ctx->buffer.used = ctx->Z.avail_in;
                                 output_context->out.used = output_context->out.size - ctx->Z.avail_out;
                                 break;
                         default:
                                 deflateEnd(&ctx->Z);
                                 return FAILURE;
                 }
   
ZEND_BEGIN_ARG_INFO_EX(arginfo_gzinflate, 0, 0, 1)                if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) {
        ZEND_ARG_INFO(0, data)                        deflateEnd(&ctx->Z);
        ZEND_ARG_INFO(0, length)                }
ZEND_END_ARG_INFO()        }
   
ZEND_BEGIN_ARG_INFO(arginfo_zlib_get_coding_type, 0)        return SUCCESS;
ZEND_END_ARG_INFO()}
 /* }}} */
   
ZEND_BEGIN_ARG_INFO_EX(arginfo_gzencode, 0, 0, 1)/* {{{ php_zlib_output_handler() */
        ZEND_ARG_INFO(0, data)static int php_zlib_output_handler(void **handler_context, php_output_context *output_context)
        ZEND_ARG_INFO(0, level){
        ZEND_ARG_INFO(0, encoding_mode)        php_zlib_context *ctx = *(php_zlib_context **) handler_context;
ZEND_END_ARG_INFO()        PHP_OUTPUT_TSRMLS(output_context);
   
ZEND_BEGIN_ARG_INFO_EX(arginfo_ob_gzhandler, 0, 0, 2)        if (!php_zlib_output_encoding(TSRMLS_C)) {
        ZEND_ARG_INFO(0, str)                /* "Vary: Accept-Encoding" header sent along uncompressed content breaks caching in MSIE,
        ZEND_ARG_INFO(0, mode)                        so let's just send it with successfully compressed content or unless the complete
ZEND_END_ARG_INFO()                        buffer gets discarded, see http://bugs.php.net/40325;
   
ZEND_BEGIN_ARG_INFO_EX(arginfo_gzputs, 0, 0, 2)                        Test as follows:
        ZEND_ARG_INFO(0, fp)                        +Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";'
        ZEND_ARG_INFO(0, str)                        +Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";'
        ZEND_ARG_INFO(0, length)                        -Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();'
ZEND_END_ARG_INFO()                        -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)
                 &&      (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, 0 TSRMLS_CC);
                 }
                 return FAILURE;
         }
   
ZEND_BEGIN_ARG_INFO(arginfo_gzpassthru, 0)        if (SUCCESS != php_zlib_output_handler_ex(ctx, output_context)) {
        ZEND_ARG_INFO(0, fp)                return FAILURE;
ZEND_END_ARG_INFO()        }
   
ZEND_BEGIN_ARG_INFO_EX(arginfo_gzseek, 0, 0, 2)        if (!(output_context->op & PHP_OUTPUT_HANDLER_CLEAN)) {
        ZEND_ARG_INFO(0, fp)                int flags;
        ZEND_ARG_INFO(0, offset) 
        ZEND_ARG_INFO(0, whence) 
ZEND_END_ARG_INFO() 
   
ZEND_BEGIN_ARG_INFO(arginfo_gzread, 0)                if (SUCCESS == php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS, &flags TSRMLS_CC)) {
        ZEND_ARG_INFO(0, fp)                        /* only run this once */
        ZEND_ARG_INFO(0, length)                        if (!(flags & PHP_OUTPUT_HANDLER_STARTED)) {
ZEND_END_ARG_INFO()                                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, 0 TSRMLS_CC);
                                 php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL TSRMLS_CC);
                         }
                 }
         }
   
ZEND_BEGIN_ARG_INFO_EX(arginfo_gzgetss, 0, 0, 1)        return SUCCESS;
        ZEND_ARG_INFO(0, fp)}
        ZEND_ARG_INFO(0, length) 
        ZEND_ARG_INFO(0, allowable_tags) 
ZEND_END_ARG_INFO() 
 
ZEND_BEGIN_ARG_INFO_EX(arginfo_gzgets, 0, 0, 1) 
        ZEND_ARG_INFO(0, fp) 
        ZEND_ARG_INFO(0, length) 
ZEND_END_ARG_INFO() 
 /* }}} */  /* }}} */
   
/* {{{ php_zlib_functions[]/* {{{ php_zlib_output_handler_context_init() */
 */static php_zlib_context *php_zlib_output_handler_context_init(TSRMLS_D)
static const zend_function_entry php_zlib_functions[] = {{
        PHP_FE(readgzfile,                                              arginfo_readgzfile)        php_zlib_context *ctx = (php_zlib_context *) ecalloc(1, sizeof(php_zlib_context));
        PHP_FALIAS(gzrewind,    rewind,                 arginfo_gzpassthru)        ctx->Z.zalloc = php_zlib_alloc;
        PHP_FALIAS(gzclose,             fclose,                 arginfo_gzpassthru)        ctx->Z.zfree = php_zlib_free;
        PHP_FALIAS(gzeof,               feof,                   arginfo_gzpassthru)        return ctx;
        PHP_FALIAS(gzgetc,              fgetc,                  arginfo_gzpassthru)}
        PHP_FALIAS(gzgets,              fgets,                  arginfo_gzgets) 
        PHP_FALIAS(gzgetss,             fgetss,                 arginfo_gzgetss) 
        PHP_FALIAS(gzread,              fread,                  arginfo_gzread) 
        PHP_FE(gzopen,                                                  arginfo_gzopen) 
        PHP_FALIAS(gzpassthru,  fpassthru,              arginfo_gzpassthru) 
        PHP_FALIAS(gzseek,              fseek,                  arginfo_gzseek) 
        PHP_FALIAS(gztell,              ftell,                  arginfo_gzpassthru) 
        PHP_FALIAS(gzwrite,             fwrite,                 arginfo_gzputs) 
        PHP_FALIAS(gzputs,              fwrite,                 arginfo_gzputs) 
        PHP_FE(gzfile,                                                  arginfo_gzfile) 
        PHP_FE(gzcompress,                                              arginfo_gzcompress) 
        PHP_FE(gzuncompress,                                    arginfo_gzuncompress) 
        PHP_FE(gzdeflate,                                               arginfo_gzdeflate) 
        PHP_FE(gzinflate,                                               arginfo_gzinflate) 
        PHP_FE(gzencode,                                                arginfo_gzencode) 
        PHP_FE(ob_gzhandler,                                    arginfo_ob_gzhandler) 
        PHP_FE(zlib_get_coding_type,                    arginfo_zlib_get_coding_type) 
        PHP_FE_END 
}; 
 /* }}} */  /* }}} */
   
ZEND_DECLARE_MODULE_GLOBALS(zlib)/* {{{ 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;
   
/* {{{ php_zlib_module_entry        if (ctx) {
 */                if (ctx->buffer.data) {
zend_module_entry php_zlib_module_entry = {                        efree(ctx->buffer.data);
        STANDARD_MODULE_HEADER,                }
        "zlib",                efree(ctx);
        php_zlib_functions,        }
        PHP_MINIT(zlib),}
        PHP_MSHUTDOWN(zlib), 
        PHP_RINIT(zlib), 
        NULL, 
        PHP_MINFO(zlib), 
        "1.1", 
        PHP_MODULE_GLOBALS(zlib), 
        NULL, 
        NULL, 
        NULL, 
        STANDARD_MODULE_PROPERTIES_EX 
}; 
 /* }}} */  /* }}} */
   
#ifdef COMPILE_DL_ZLIB/* {{{ php_zlib_output_handler_init() */
ZEND_GET_MODULE(php_zlib)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)
#endif{
         php_output_handler *h = NULL;
   
/* {{{ Memory management wrappers */        if (!ZLIBG(output_compression)) {
                 ZLIBG(output_compression) = chunk_size ? chunk_size : PHP_OUTPUT_HANDLER_DEFAULT_SIZE;
         }
   
static voidpf php_zlib_alloc(voidpf opaque, uInt items, uInt size)    ZLIBG(handler_registered) = 1;
{ 
        return (voidpf)safe_emalloc(items, size, 0); 
} 
   
static void php_zlib_free(voidpf opaque, voidpf address)        if ((h = php_output_handler_create_internal(handler_name, handler_name_len, php_zlib_output_handler, chunk_size, flags TSRMLS_CC))) {
{                php_output_handler_set_context(h, php_zlib_output_handler_context_init(TSRMLS_C), php_zlib_output_handler_context_dtor TSRMLS_CC);
        efree((void*)address);        }
 
         return h;
 }  }
 /* }}} */  /* }}} */
   
/* {{{ OnUpdate_zlib_output_compression *//* {{{ php_zlib_output_compression_start() */
static PHP_INI_MH(OnUpdate_zlib_output_compression)static void php_zlib_output_compression_start(TSRMLS_D)
 {  {
        int status, int_value;        zval *zoh;
        char *ini_value;        php_output_handler *h;
   
        if (new_value == NULL) {        switch (ZLIBG(output_compression)) {
                return FAILURE;                case 0:
                         break;
                 case 1:
                         ZLIBG(output_compression) = PHP_OUTPUT_HANDLER_DEFAULT_SIZE;
                         /* break omitted intentionally */
                 default:
                         if (    php_zlib_output_encoding(TSRMLS_C) &&
                                         (h = php_zlib_output_handler_init(ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME), ZLIBG(output_compression), PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC)) &&
                                         (SUCCESS == php_output_handler_start(h TSRMLS_CC))) {
                                 if (ZLIBG(output_handler) && *ZLIBG(output_handler)) {
                                         MAKE_STD_ZVAL(zoh);
                                         ZVAL_STRING(zoh, ZLIBG(output_handler), 1);
                                         php_output_start_user(zoh, ZLIBG(output_compression), PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC);
                                         zval_ptr_dtor(&zoh);
                                 }
                         }
                         break;
         }          }
   }
   /* }}} */
   
        if (!strncasecmp(new_value, "off", sizeof("off"))) {/* {{{ php_zlib_encode() */
                new_value = "0";static int php_zlib_encode(const char *in_buf, size_t in_len, char **out_buf, size_t *out_len, int encoding, int level TSRMLS_DC)
                new_value_length = sizeof("0");{
        } else if (!strncasecmp(new_value, "on", sizeof("on"))) {        int status;
                new_value = "1";        z_stream Z;
                new_value_length = sizeof("1"); 
        } 
   
        int_value = zend_atoi(new_value, new_value_length);        memset(&Z, 0, sizeof(z_stream));
        ini_value = zend_ini_string("output_handler", sizeof("output_handler"), 0);        Z.zalloc = php_zlib_alloc;
         Z.zfree = php_zlib_free;
   
        if (ini_value && *ini_value && int_value) {        if (Z_OK == (status = deflateInit2(&Z, level, Z_DEFLATED, encoding, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY))) {
                php_error_docref("ref.outcontrol" TSRMLS_CC, E_CORE_ERROR, "Cannot use both zlib.output_compression and output_handler together!!");                *out_len = PHP_ZLIB_BUFFER_SIZE_GUESS(in_len);
                return FAILURE;                *out_buf = emalloc(*out_len);
        } 
   
        if (stage == PHP_INI_STAGE_RUNTIME && SG(headers_sent) && !SG(request_info).no_headers) {                Z.next_in = (Bytef *) in_buf;
                php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "Cannot change zlib.output_compression - headers already sent");                Z.next_out = (Bytef *) *out_buf;
                return FAILURE;                Z.avail_in = in_len;
        }                Z.avail_out = *out_len;
   
        status = OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);                status = deflate(&Z, Z_FINISH);
                 deflateEnd(&Z);
   
        if (stage == PHP_INI_STAGE_RUNTIME && int_value) {                if (Z_STREAM_END == status) {
                status = php_zlib_output_compression_start(TSRMLS_C);                        /* size buffer down to actual length */
                         *out_buf = erealloc(*out_buf, Z.total_out + 1);
                         (*out_buf)[*out_len = Z.total_out] = '\0';
                         return SUCCESS;
                 } else {
                         efree(*out_buf);
                 }
         }          }
   
        return status;        *out_buf = NULL;
         *out_len = 0;
 
         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
         return FAILURE;
 }  }
 /* }}} */  /* }}} */
   
/* {{{ OnUpdate_zlib_output_compression_level *//* {{{ php_zlib_inflate_rounds() */
static PHP_INI_MH(OnUpdate_zlib_output_compression_level)static inline int php_zlib_inflate_rounds(z_stream *Z, size_t max, char **buf, size_t *len)
 {  {
        OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);        int status, round = 0;
         php_zlib_buffer buffer = {NULL, NULL, 0, 0, 0};
   
        return SUCCESS;        *buf = NULL;
}        *len = 0;
/* }}} */ 
   
/* {{{ OnUpdate_zlib_output_handler */        buffer.size = (max && (max < Z->avail_in)) ? max : Z->avail_in;
static PHP_INI_MH(OnUpdate_zlib_output_handler) 
{ 
        if (stage == PHP_INI_STAGE_RUNTIME && SG(headers_sent) && !SG(request_info).no_headers) { 
                php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "Cannot change zlib.output_handler - headers already sent"); 
                return FAILURE; 
        } 
   
        OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);        do {
                 if ((max && (max <= buffer.used)) || !(buffer.aptr = erealloc_recoverable(buffer.data, buffer.size))) {
                         status = Z_MEM_ERROR;
                 } else {
                         buffer.data = buffer.aptr;
                         Z->avail_out = buffer.free = buffer.size - buffer.used;
                         Z->next_out = (Bytef *) buffer.data + buffer.used;
 #if 0
                         fprintf(stderr, "\n%3d: %3d PRIOR: size=%7lu,\tfree=%7lu,\tused=%7lu,\tavail_in=%7lu,\tavail_out=%7lu\n", round, status, buffer.size, buffer.free, buffer.used, Z->avail_in, Z->avail_out);
 #endif
                         status = inflate(Z, Z_NO_FLUSH);
   
        return SUCCESS;                        buffer.used += buffer.free - Z->avail_out;
                         buffer.free = Z->avail_out;
 #if 0
                         fprintf(stderr, "%3d: %3d AFTER: size=%7lu,\tfree=%7lu,\tused=%7lu,\tavail_in=%7lu,\tavail_out=%7lu\n", round, status, buffer.size, buffer.free, buffer.used, Z->avail_in, Z->avail_out);
 #endif
                         buffer.size += (buffer.size >> 3) + 1;
                 }
         } while ((Z_BUF_ERROR == status || (Z_OK == status && Z->avail_in)) && ++round < 100);
 
         if (status == Z_STREAM_END) {
                 buffer.data = erealloc(buffer.data, buffer.used + 1);
                 buffer.data[buffer.used] = '\0';
                 *buf = buffer.data;
                 *len = buffer.used;
         } else {
                 if (buffer.data) {
                         efree(buffer.data);
                 }
                 /* HACK: See zlib/examples/zpipe.c inf() function for explanation. */
                 /* This works as long as this function is not used for streaming. Required to catch very short invalid data. */
                 status = (status == Z_OK) ? Z_DATA_ERROR : status;
         }
         return status;
 }  }
 /* }}} */  /* }}} */
   
   /* {{{ php_zlib_decode() */
   static int php_zlib_decode(const char *in_buf, size_t in_len, char **out_buf, size_t *out_len, int encoding, size_t max_len TSRMLS_DC)
   {
           int status = Z_DATA_ERROR;
           z_stream Z;
   
PHP_INI_BEGIN()        memset(&Z, 0, sizeof(z_stream));
        STD_PHP_INI_BOOLEAN("zlib.output_compression",      "0", PHP_INI_ALL, OnUpdate_zlib_output_compression,       output_compression,       zend_zlib_globals, zlib_globals)        Z.zalloc = php_zlib_alloc;
        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)        Z.zfree = php_zlib_free;
        STD_PHP_INI_ENTRY("zlib.output_handler",             "", PHP_INI_ALL, OnUpdate_zlib_output_handler,           output_handler,           zend_zlib_globals, zlib_globals) 
PHP_INI_END() 
   
/* {{{ PHP_MINIT_FUNCTION        if (in_len) {
 */retry_raw_inflate:
static PHP_MINIT_FUNCTION(zlib)                status = inflateInit2(&Z, encoding);
{                if (Z_OK == status) {
        php_register_url_stream_wrapper("compress.zlib", &php_stream_gzip_wrapper TSRMLS_CC);                        Z.next_in = (Bytef *) in_buf;
        php_stream_filter_register_factory("zlib.*", &php_zlib_filter_factory TSRMLS_CC);                        Z.avail_in = in_len + 1; /* NOTE: data must be zero terminated */
   
        REGISTER_LONG_CONSTANT("FORCE_GZIP", CODING_GZIP, CONST_CS | CONST_PERSISTENT);                        switch (status = php_zlib_inflate_rounds(&Z, max_len, out_buf, out_len)) {
        REGISTER_LONG_CONSTANT("FORCE_DEFLATE", CODING_DEFLATE, CONST_CS | CONST_PERSISTENT);                                case Z_STREAM_END:
                                         inflateEnd(&Z);
                                         return SUCCESS;
   
        REGISTER_INI_ENTRIES();                                case Z_DATA_ERROR:
                                         /* raw deflated data? */
                                         if (PHP_ZLIB_ENCODING_ANY == encoding) {
                                                 inflateEnd(&Z);
                                                 encoding = PHP_ZLIB_ENCODING_RAW;
                                                 goto retry_raw_inflate;
                                         }
                         }
                         inflateEnd(&Z);
                 }
         }
   
        return SUCCESS;        *out_buf = NULL;
         *out_len = 0;
 
         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
         return FAILURE;
 }  }
 /* }}} */  /* }}} */
   
/* {{{ PHP_RINIT_FUNCTION/* {{{ php_zlib_cleanup_ob_gzhandler_mess() */
 */static void php_zlib_cleanup_ob_gzhandler_mess(TSRMLS_D)
static PHP_RINIT_FUNCTION(zlib) 
 {  {
        ZLIBG(ob_gzhandler_status) = 0;        if (ZLIBG(ob_gzhandler)) {
        ZLIBG(compression_coding) = 0;                deflateEnd(&(ZLIBG(ob_gzhandler)->Z));
                php_zlib_output_handler_context_dtor(ZLIBG(ob_gzhandler) TSRMLS_CC);
        php_zlib_output_compression_start(TSRMLS_C);                ZLIBG(ob_gzhandler) = NULL;
        }
        return SUCCESS; 
 }  }
 /* }}} */  /* }}} */
   
/* {{{ PHP_MSHUTDOWN_FUNCTION/* {{{ proto string ob_gzhandler(string data, int flags)
 */   Legacy hack */
static PHP_MSHUTDOWN_FUNCTION(zlib)static PHP_FUNCTION(ob_gzhandler)
 {  {
        php_unregister_url_stream_wrapper("zlib" TSRMLS_CC);        char *in_str;
        php_stream_filter_unregister_factory("zlib.*" TSRMLS_CC);        int in_len;
         long flags = 0;
         php_output_context ctx = {0};
         int encoding, rv;
   
        UNREGISTER_INI_ENTRIES();        /*
          * 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 */
   
        return SUCCESS;        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, 0 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();
         }
 }  }
 /* }}} */  /* }}} */
   
/* {{{ PHP_MINFO_FUNCTION/* {{{ proto string zlib_get_coding_type(void)
 */   Returns the coding type used for output compression */
static PHP_MINFO_FUNCTION(zlib)static PHP_FUNCTION(zlib_get_coding_type)
 {  {
        php_info_print_table_start();        if (zend_parse_parameters_none() == FAILURE) {
        php_info_print_table_row(2, "ZLib Support", "enabled");                return;
        php_info_print_table_row(2, "Stream Wrapper support", "compress.zlib://");        }
        php_info_print_table_row(2, "Stream Filter support", "zlib.inflate, zlib.deflate");        switch (ZLIBG(compression_coding)) {
        php_info_print_table_row(2, "Compiled Version", ZLIB_VERSION);                case PHP_ZLIB_ENCODING_GZIP:
        php_info_print_table_row(2, "Linked Version", (char *) zlibVersion());                        RETURN_STRINGL("gzip", sizeof("gzip") - 1, 1);
        php_info_print_table_end();                case PHP_ZLIB_ENCODING_DEFLATE:
                        RETURN_STRINGL("deflate", sizeof("deflate") - 1, 1);
        DISPLAY_INI_ENTRIES();                default:
                         RETURN_FALSE;
         }
 }  }
 /* }}} */  /* }}} */
   
 /* {{{ proto array gzfile(string filename [, int use_include_path])  /* {{{ proto array gzfile(string filename [, int use_include_path])
   Read und uncompress entire .gz-file into an array */   Read and uncompress entire .gz-file into an array */
 static PHP_FUNCTION(gzfile)  static PHP_FUNCTION(gzfile)
 {  {
         char *filename;          char *filename;
         int filename_len;          int filename_len;
        long flags = 0;        int flags = REPORT_ERRORS;
        char *slashed, buf[8192];        char buf[8192] = {0};
         register int i = 0;          register int i = 0;
        int use_include_path = 0;        long use_include_path = 0;
         php_stream *stream;          php_stream *stream;
   
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &flags) == FAILURE) {        if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &filename, &filename_len, &use_include_path)) {
                 return;                  return;
         }          }
   
        use_include_path = flags ? USE_PATH : 0;        if (use_include_path) {
                 flags |= USE_PATH;
         }
   
         /* using a stream here is a bit more efficient (resource wise) than php_gzopen_wrapper */          /* using a stream here is a bit more efficient (resource wise) than php_gzopen_wrapper */
        stream = php_stream_gzopen(NULL, filename, "rb", use_include_path | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, NULL STREAMS_CC TSRMLS_CC);        stream = php_stream_gzopen(NULL, filename, "rb", flags, NULL, NULL STREAMS_CC TSRMLS_CC);
        if (stream == NULL) {
         if (!stream) {
                 /* Error reporting is already done by stream code */                  /* Error reporting is already done by stream code */
                 RETURN_FALSE;                  RETURN_FALSE;
         }          }
Line 415  static PHP_FUNCTION(gzfile) Line 561  static PHP_FUNCTION(gzfile)
         array_init(return_value);          array_init(return_value);
   
         /* Now loop through the file and do the magic quotes thing if needed */          /* Now loop through the file and do the magic quotes thing if needed */
        memset(buf,0,sizeof(buf));        memset(buf, 0, sizeof(buf));
            
         while (php_stream_gets(stream, buf, sizeof(buf) - 1) != NULL) {          while (php_stream_gets(stream, buf, sizeof(buf) - 1) != NULL) {
                if (PG(magic_quotes_runtime)) {                add_index_string(return_value, i++, buf, 1);
                        int len; 
 
                        slashed = php_addslashes(buf, 0, &len, 0 TSRMLS_CC); /* 0 = don't free source string */ 
                        add_index_stringl(return_value, i++, slashed, len, 0); 
                } else { 
                        add_index_string(return_value, i++, buf, 1); 
                } 
         }          }
         php_stream_close(stream);          php_stream_close(stream);
 }  }
Line 435  static PHP_FUNCTION(gzfile) Line 574  static PHP_FUNCTION(gzfile)
    Open a .gz-file and return a .gz-file pointer */     Open a .gz-file and return a .gz-file pointer */
 static PHP_FUNCTION(gzopen)  static PHP_FUNCTION(gzopen)
 {  {
        char *filename, *mode;        char *filename;
         char *mode;
         int filename_len, mode_len;          int filename_len, mode_len;
        long flags = 0;        int flags = REPORT_ERRORS;
         php_stream *stream;          php_stream *stream;
        int use_include_path = 0;        long use_include_path = 0;
   
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &filename, &filename_len, &mode, &mode_len, &flags) == FAILURE) {        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &filename, &filename_len, &mode, &mode_len, &use_include_path) == FAILURE) {
                 return;                  return;
         }          }
   
        use_include_path = flags ? USE_PATH : 0;        if (use_include_path) {
                 flags |= USE_PATH;
         }
   
        stream = php_stream_gzopen(NULL, filename, mode, use_include_path | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, NULL STREAMS_CC TSRMLS_CC);        stream = php_stream_gzopen(NULL, filename, mode, flags, NULL, NULL STREAMS_CC TSRMLS_CC);
   
         if (!stream) {          if (!stream) {
                 RETURN_FALSE;                  RETURN_FALSE;
Line 456  static PHP_FUNCTION(gzopen) Line 598  static PHP_FUNCTION(gzopen)
 }  }
 /* }}} */  /* }}} */
   
 /*  
  * Read a file and write the ouput to stdout  
  */  
 /* {{{ proto int readgzfile(string filename [, int use_include_path])  /* {{{ proto int readgzfile(string filename [, int use_include_path])
    Output a .gz-file */     Output a .gz-file */
 static PHP_FUNCTION(readgzfile)  static PHP_FUNCTION(readgzfile)
 {  {
         char *filename;          char *filename;
         int filename_len;          int filename_len;
        long flags = 0;        int flags = REPORT_ERRORS;
         php_stream *stream;          php_stream *stream;
         int size;          int size;
        int use_include_path = 0;        long use_include_path = 0;
   
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &flags) == FAILURE) {        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &use_include_path) == FAILURE) {
                 return;                  return;
         }          }
   
        use_include_path = flags ? USE_PATH : 0;        if (use_include_path) {
                 flags |= USE_PATH;
         }
   
        stream = php_stream_gzopen(NULL, filename, "rb", use_include_path | ENFORCE_SAFE_MODE, NULL, NULL STREAMS_CC TSRMLS_CC);        stream = php_stream_gzopen(NULL, filename, "rb", flags, NULL, NULL STREAMS_CC TSRMLS_CC);
 
         if (!stream) {          if (!stream) {
                 RETURN_FALSE;                  RETURN_FALSE;
         }          }
Line 486  static PHP_FUNCTION(readgzfile) Line 628  static PHP_FUNCTION(readgzfile)
 }  }
 /* }}} */  /* }}} */
   
/* {{{ proto string gzcompress(string data [, int level])#define PHP_ZLIB_ENCODE_FUNC(name, default_encoding) \
   Gzip-compress a string */static PHP_FUNCTION(name) \
static PHP_FUNCTION(gzcompress){ \
{        char *in_buf, *out_buf; \
        int data_len, status;        int in_len; \
        long level = Z_DEFAULT_COMPRESSION;        size_t out_len; \
        unsigned long l2;        long level = -1; \
        char *data, *s2;        long encoding = default_encoding; \
         if (default_encoding) { \
                 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &in_buf, &in_len, &level, &encoding)) { \
                         return; \
                 } \
         } else { \
                 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|l", &in_buf, &in_len, &encoding, &level)) { \
                         return; \
                 } \
         } \
         if (level < -1 || level > 9) { \
                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level (%ld) must be within -1..9", level); \
                 RETURN_FALSE; \
         } \
         switch (encoding) { \
                 case PHP_ZLIB_ENCODING_RAW: \
                 case PHP_ZLIB_ENCODING_GZIP: \
                 case PHP_ZLIB_ENCODING_DEFLATE: \
                         break; \
                 default: \
                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "encoding mode must be either ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE"); \
                         RETURN_FALSE; \
         } \
         if (SUCCESS != php_zlib_encode(in_buf, in_len, &out_buf, &out_len, encoding, level TSRMLS_CC)) { \
                 RETURN_FALSE; \
         } \
         RETURN_STRINGL(out_buf, out_len, 0); \
 }
   
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &level) == FAILURE) {#define PHP_ZLIB_DECODE_FUNC(name, encoding) \
                return;static PHP_FUNCTION(name) \
        }{ \
         char *in_buf, *out_buf; \
         int in_len; \
         size_t out_len; \
         long max_len = 0; \
         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &in_buf, &in_len, &max_len)) { \
                 return; \
         } \
         if (max_len < 0) { \
                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "length (%ld) must be greater or equal zero", max_len); \
                 RETURN_FALSE; \
         } \
         if (SUCCESS != php_zlib_decode(in_buf, in_len, &out_buf, &out_len, encoding, max_len TSRMLS_CC)) { \
                 RETURN_FALSE; \
         } \
         RETURN_STRINGL(out_buf, out_len, 0); \
 }
   
        if ((level < -1) || (level > 9)) {/* {{{ proto binary zlib_encode(binary data, int encoding[, int level = -1])
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level (%ld) must be within -1..9", level);   Compress data with the specified encoding */
                RETURN_FALSE;PHP_ZLIB_ENCODE_FUNC(zlib_encode, 0);
        }/* }}} */
   
        l2 = data_len + (data_len / PHP_ZLIB_MODIFIER) + 15 + 1; /* room for \0 *//* {{{ proto binary zlib_decode(binary data[, int max_decoded_len])
        s2 = (char *) emalloc(l2);   Uncompress any raw/gzip/zlib encoded data */
        if (!s2) {PHP_ZLIB_DECODE_FUNC(zlib_decode, PHP_ZLIB_ENCODING_ANY);
                RETURN_FALSE;/* }}} */
        } 
   
        if (level >= 0) {/* NOTE: The naming of these userland functions was quite unlucky */
                status = compress2(s2, &l2, data, data_len, level);/* {{{ proto binary gzdeflate(binary data[, int level = -1[, int encoding = ZLIB_ENCODING_RAW])
        } else {   Encode data with the raw deflate encoding */
                status = compress(s2, &l2, data, data_len);PHP_ZLIB_ENCODE_FUNC(gzdeflate, PHP_ZLIB_ENCODING_RAW);
        }/* }}} */
   
        if (status == Z_OK) {/* {{{ proto binary gzencode(binary data[, int level = -1[, int encoding = ZLIB_ENCODING_GZIP])
                s2 = erealloc(s2, l2 + 1);   Encode data with the gzip encoding */
                s2[l2] = '\0';PHP_ZLIB_ENCODE_FUNC(gzencode, PHP_ZLIB_ENCODING_GZIP);
                RETURN_STRINGL(s2, l2, 0); 
        } else { 
                efree(s2); 
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status)); 
                RETURN_FALSE; 
        } 
} 
 /* }}} */  /* }}} */
   
/* {{{ proto string gzuncompress(string data [, int length])/* {{{ proto binary gzcompress(binary data[, int level = -1[, int encoding = ZLIB_ENCODING_DEFLATE])
   Unzip a gzip-compressed string */   Encode data with the zlib encoding */
static PHP_FUNCTION(gzuncompress)PHP_ZLIB_ENCODE_FUNC(gzcompress, PHP_ZLIB_ENCODING_DEFLATE);
{/* }}} */
        int data_len, status; 
        unsigned int factor=1, maxfactor=16; 
        long limit = 0; 
        unsigned long plength=0, length; 
        char *data, *s1=NULL, *s2=NULL; 
   
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &limit) == FAILURE) {/* {{{ proto binary gzinflate(binary data[, int max_decoded_len])
                return;   Decode raw deflate encoded data */
        }PHP_ZLIB_DECODE_FUNC(gzinflate, PHP_ZLIB_ENCODING_RAW);
 /* }}} */
   
        if (limit < 0) {/* {{{ proto binary gzdecode(binary data[, int max_decoded_len])
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "length (%ld) must be greater or equal zero", limit);   Decode gzip encoded data */
                RETURN_FALSE;PHP_ZLIB_DECODE_FUNC(gzdecode, PHP_ZLIB_ENCODING_GZIP);
        }/* }}} */
        plength = limit; 
   
        /*/* {{{ proto binary gzuncompress(binary data[, int max_decoded_len])
         zlib::uncompress() wants to know the output data length   Decode zlib encoded data */
         if none was given as a parameterPHP_ZLIB_DECODE_FUNC(gzuncompress, PHP_ZLIB_ENCODING_DEFLATE);
         we try from input length * 2 up to input length * 2^15 
         doubling it whenever it wasn't big enough 
         that should be eneugh for all real life cases 
        */ 
        do { 
                length = plength ? plength : (unsigned long)data_len * (1 << factor++); 
                s2 = (char *) erealloc(s1, length); 
                status = uncompress(s2, &length, data, data_len); 
                s1 = s2; 
        } while ((status == Z_BUF_ERROR) && (!plength) && (factor < maxfactor)); 
 
        if (status == Z_OK) { 
                s2 = erealloc(s2, length + 1); /* space for \0 */ 
                s2[ length ] = '\0'; 
                RETURN_STRINGL(s2, length, 0); 
        } else { 
                efree(s2); 
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status)); 
                RETURN_FALSE; 
        } 
} 
 /* }}} */  /* }}} */
   
/* {{{ proto string gzdeflate(string data [, int level])#ifdef COMPILE_DL_ZLIB
   Gzip-compress a string */ZEND_GET_MODULE(php_zlib)
static PHP_FUNCTION(gzdeflate)#endif
{ 
        int data_len,status; 
        long level = Z_DEFAULT_COMPRESSION; 
        z_stream stream; 
        char *data, *s2; 
   
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &level) == FAILURE) {/* {{{ arginfo */
                return;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()
   
        if ((level < -1) || (level > 9)) {ZEND_BEGIN_ARG_INFO(arginfo_zlib_get_coding_type, 0)
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level (%ld) must be within -1..9", level);ZEND_END_ARG_INFO()
                RETURN_FALSE; 
        } 
   
        stream.data_type = Z_ASCII;ZEND_BEGIN_ARG_INFO_EX(arginfo_gzfile, 0, 0, 1)
        stream.zalloc = php_zlib_alloc;        ZEND_ARG_INFO(0, filename)
        stream.zfree  = php_zlib_free;        ZEND_ARG_INFO(0, use_include_path)
        stream.opaque = (voidpf) Z_NULL;ZEND_END_ARG_INFO()
   
        stream.next_in = (Bytef *) data;ZEND_BEGIN_ARG_INFO_EX(arginfo_gzopen, 0, 0, 2)
        stream.avail_in = data_len;        ZEND_ARG_INFO(0, filename)
         ZEND_ARG_INFO(0, mode)
         ZEND_ARG_INFO(0, use_include_path)
 ZEND_END_ARG_INFO()
   
        stream.avail_out = stream.avail_in + (stream.avail_in / PHP_ZLIB_MODIFIER) + 15 + 1; /* room for \0 */ZEND_BEGIN_ARG_INFO_EX(arginfo_readgzfile, 0, 0, 1)
         ZEND_ARG_INFO(0, filename)
         ZEND_ARG_INFO(0, use_include_path)
 ZEND_END_ARG_INFO()
   
        s2 = (char *) emalloc(stream.avail_out);ZEND_BEGIN_ARG_INFO_EX(arginfo_zlib_encode, 0, 0, 2)
        if (!s2) {        ZEND_ARG_INFO(0, data)
                RETURN_FALSE;        ZEND_ARG_INFO(0, encoding)
        }        ZEND_ARG_INFO(0, level)
 ZEND_END_ARG_INFO()
   
        stream.next_out = s2;ZEND_BEGIN_ARG_INFO_EX(arginfo_zlib_decode, 0, 0, 1)
         ZEND_ARG_INFO(0, data)
         ZEND_ARG_INFO(0, max_decoded_len)
 ZEND_END_ARG_INFO()
   
        /* init with -MAX_WBITS disables the zlib internal headers */ZEND_BEGIN_ARG_INFO_EX(arginfo_gzdeflate, 0, 0, 1)
        status = deflateInit2(&stream, level, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, 0);        ZEND_ARG_INFO(0, data)
        if (status == Z_OK) {        ZEND_ARG_INFO(0, level)
                status = deflate(&stream, Z_FINISH);        ZEND_ARG_INFO(0, encoding)
                if (status != Z_STREAM_END) {ZEND_END_ARG_INFO()
                        deflateEnd(&stream); 
                        if (status == Z_OK) { 
                                status = Z_BUF_ERROR; 
                        } 
                } else { 
                        status = deflateEnd(&stream); 
                } 
        } 
   
        if (status == Z_OK) {ZEND_BEGIN_ARG_INFO_EX(arginfo_gzencode, 0, 0, 1)
                s2 = erealloc(s2,stream.total_out + 1); /* resize to buffer to the "right" size */        ZEND_ARG_INFO(0, data)
                s2[ stream.total_out ] = '\0';        ZEND_ARG_INFO(0, level)
                RETURN_STRINGL(s2, stream.total_out, 0);        ZEND_ARG_INFO(0, encoding)
        } else {ZEND_END_ARG_INFO()
                efree(s2); 
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status)); 
                RETURN_FALSE; 
        } 
} 
/* }}} */ 
   
/* {{{ proto string gzinflate(string data [, int length])ZEND_BEGIN_ARG_INFO_EX(arginfo_gzcompress, 0, 0, 1)
   Unzip a gzip-compressed string */        ZEND_ARG_INFO(0, data)
static PHP_FUNCTION(gzinflate)        ZEND_ARG_INFO(0, level)
{        ZEND_ARG_INFO(0, encoding)
        int data_len, status;ZEND_END_ARG_INFO()
        unsigned int factor=1, maxfactor=16; 
        long limit = 0; 
        unsigned long plength=0, length; 
        char *data, *s1=NULL, *s2=NULL; 
        z_stream stream; 
   
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &limit) == FAILURE) {ZEND_BEGIN_ARG_INFO_EX(arginfo_gzinflate, 0, 0, 1)
                return;        ZEND_ARG_INFO(0, data)
        }        ZEND_ARG_INFO(0, max_decoded_len)
 ZEND_END_ARG_INFO()
   
        if (!data_len) {ZEND_BEGIN_ARG_INFO_EX(arginfo_gzdecode, 0, 0, 1)
                RETURN_FALSE;        ZEND_ARG_INFO(0, data)
        }        ZEND_ARG_INFO(0, max_decoded_len)
 ZEND_END_ARG_INFO()
   
        if (limit < 0) {ZEND_BEGIN_ARG_INFO_EX(arginfo_gzuncompress, 0, 0, 1)
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "length (%ld) must be greater or equal zero", limit);        ZEND_ARG_INFO(0, data)
                RETURN_FALSE;        ZEND_ARG_INFO(0, max_decoded_len)
        }ZEND_END_ARG_INFO()
        plength = limit; 
   
        stream.zalloc = php_zlib_alloc;ZEND_BEGIN_ARG_INFO_EX(arginfo_gzputs, 0, 0, 2)
        stream.zfree = php_zlib_free;        ZEND_ARG_INFO(0, fp)
        stream.opaque = Z_NULL;        ZEND_ARG_INFO(0, str)
        stream.avail_in = data_len + 1; /* there is room for \0 */        ZEND_ARG_INFO(0, length)
        stream.next_in = (Bytef *) data;ZEND_END_ARG_INFO()
        stream.total_out = 0; 
   
        /* init with -MAX_WBITS disables the zlib internal headers */ZEND_BEGIN_ARG_INFO(arginfo_gzpassthru, 0)
        status = inflateInit2(&stream, -MAX_WBITS);        ZEND_ARG_INFO(0, fp)
        if (status != Z_OK) {ZEND_END_ARG_INFO()
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status)); 
                RETURN_FALSE; 
        } 
   
        /*ZEND_BEGIN_ARG_INFO_EX(arginfo_gzseek, 0, 0, 2)
          stream.avail_out wants to know the output data length        ZEND_ARG_INFO(0, fp)
          if none was given as a parameter        ZEND_ARG_INFO(0, offset)
          we try from input length * 2 up to input length * 2^15        ZEND_ARG_INFO(0, whence)
          doubling it whenever it wasn't big enoughZEND_END_ARG_INFO()
          that should be enaugh for all real life cases 
        */ 
        do { 
                length = plength ? plength : (unsigned long)data_len * (1 << factor++); 
                s2 = (char *) erealloc(s1, length); 
   
                if (!s2) {ZEND_BEGIN_ARG_INFO(arginfo_gzread, 0)
                        if (s1) {        ZEND_ARG_INFO(0, fp)
                                efree(s1);        ZEND_ARG_INFO(0, length)
                        }ZEND_END_ARG_INFO()
                        inflateEnd(&stream); 
                        RETURN_FALSE; 
                } 
                s1 = s2; 
   
                stream.next_out = (Bytef *) &s2[stream.total_out];ZEND_BEGIN_ARG_INFO_EX(arginfo_gzgetss, 0, 0, 1)
                stream.avail_out = length - stream.total_out;        ZEND_ARG_INFO(0, fp)
                status = inflate(&stream, Z_NO_FLUSH);        ZEND_ARG_INFO(0, length)
         ZEND_ARG_INFO(0, allowable_tags)
 ZEND_END_ARG_INFO()
   
        } while ((Z_BUF_ERROR == status || (Z_OK == status && stream.avail_in)) && !plength && factor < maxfactor);ZEND_BEGIN_ARG_INFO_EX(arginfo_gzgets, 0, 0, 1)
         ZEND_ARG_INFO(0, fp)
         ZEND_ARG_INFO(0, length)
 ZEND_END_ARG_INFO()
 /* }}} */
   
        inflateEnd(&stream);/* {{{ php_zlib_functions[] */
static const zend_function_entry php_zlib_functions[] = {
        if ((plength && Z_OK == status) || factor >= maxfactor) {        PHP_FE(readgzfile,                                              arginfo_readgzfile)
                status = Z_MEM_ERROR;        PHP_FALIAS(gzrewind,    rewind,                 arginfo_gzpassthru)
        }        PHP_FALIAS(gzclose,             fclose,                 arginfo_gzpassthru)
        PHP_FALIAS(gzeof,               feof,                   arginfo_gzpassthru)
        if (Z_STREAM_END == status || Z_OK == status) {        PHP_FALIAS(gzgetc,              fgetc,                  arginfo_gzpassthru)
                s2 = erealloc(s2, stream.total_out + 1); /* room for \0 */        PHP_FALIAS(gzgets,              fgets,                  arginfo_gzgets)
                s2[ stream.total_out ] = '\0';        PHP_FALIAS(gzgetss,             fgetss,                 arginfo_gzgetss)
                RETURN_STRINGL(s2, stream.total_out, 0);        PHP_FALIAS(gzread,              fread,                  arginfo_gzread)
        } else {        PHP_FE(gzopen,                                                  arginfo_gzopen)
                efree(s2);        PHP_FALIAS(gzpassthru,  fpassthru,              arginfo_gzpassthru)
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));        PHP_FALIAS(gzseek,              fseek,                  arginfo_gzseek)
                RETURN_FALSE;        PHP_FALIAS(gztell,              ftell,                  arginfo_gzpassthru)
        }        PHP_FALIAS(gzwrite,             fwrite,                 arginfo_gzputs)
}        PHP_FALIAS(gzputs,              fwrite,                 arginfo_gzputs)
         PHP_FE(gzfile,                                                  arginfo_gzfile)
         PHP_FE(gzcompress,                                              arginfo_gzcompress)
         PHP_FE(gzuncompress,                                    arginfo_gzuncompress)
         PHP_FE(gzdeflate,                                               arginfo_gzdeflate)
         PHP_FE(gzinflate,                                               arginfo_gzinflate)
         PHP_FE(gzencode,                                                arginfo_gzencode)
         PHP_FE(gzdecode,                                                arginfo_gzdecode)
         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
 };
 /* }}} */  /* }}} */
   
/* {{{ proto string zlib_get_coding_type(void)/* {{{ OnUpdate_zlib_output_compression */
   Returns the coding type used for output compression */static PHP_INI_MH(OnUpdate_zlib_output_compression)
static PHP_FUNCTION(zlib_get_coding_type) 
 {  {
        switch (ZLIBG(compression_coding)) {        int status, int_value;
                case CODING_GZIP:        char *ini_value;
                        RETURN_STRINGL("gzip", sizeof("gzip") - 1, 1); 
   
                case CODING_DEFLATE:        if (new_value == NULL) {
                        RETURN_STRINGL("deflate", sizeof("deflate") - 1, 1);                return FAILURE;
         }          }
   
        RETURN_FALSE;        if (!strncasecmp(new_value, "off", sizeof("off"))) {
}                new_value = "0";
                new_value_length = sizeof("0");
/* {{{ php_do_deflate        } else if (!strncasecmp(new_value, "on", sizeof("on"))) {
 */                new_value = "1";
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)                new_value_length = sizeof("1");
{ 
        Bytef *buffer; 
        uInt prev_outlen, outlen; 
        int err; 
        int start_offset = ((do_start && ZLIBG(compression_coding) == CODING_GZIP) ? 10 : 0); 
        int end_offset = (do_end ? 8 : 0); 
 
        outlen = (uint) (str_length + (str_length / PHP_ZLIB_MODIFIER) + 12 + 1); /* leave some room for a trailing \0 */ 
        if ((outlen + start_offset + end_offset) > *p_buffer_len) { 
                buffer = (Bytef *) emalloc(outlen + start_offset + end_offset); 
        } else { 
                buffer = *p_buffer; 
         }          }
   
        ZLIBG(stream).next_out = buffer + start_offset;        int_value = zend_atoi(new_value, new_value_length);
        ZLIBG(stream).avail_out = outlen;        ini_value = zend_ini_string("output_handler", sizeof("output_handler"), 0);
   
        err = deflate(&ZLIBG(stream), Z_SYNC_FLUSH);        if (ini_value && *ini_value && int_value) {
        while (err == Z_OK && !ZLIBG(stream).avail_out) {                php_error_docref("ref.outcontrol" TSRMLS_CC, E_CORE_ERROR, "Cannot use both zlib.output_compression and output_handler together!!");
                prev_outlen = outlen;                return FAILURE;
                outlen *= 3;        }
                if ((outlen + start_offset + end_offset) > *p_buffer_len) {        if (stage == PHP_INI_STAGE_RUNTIME) {
                        buffer = erealloc(buffer, outlen + start_offset + end_offset);                status = php_output_get_status(TSRMLS_C);
                 if (status & PHP_OUTPUT_SENT) {
                         php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "Cannot change zlib.output_compression - headers already sent");
                         return FAILURE;
                 }                  }
           }
   
                ZLIBG(stream).next_out = buffer + start_offset + prev_outlen;        status = OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
                ZLIBG(stream).avail_out = prev_outlen * 2; 
   
                err = deflate(&ZLIBG(stream), Z_SYNC_FLUSH);        ZLIBG(output_compression) = ZLIBG(output_compression_default);
         if (stage == PHP_INI_STAGE_RUNTIME && int_value) {
                 if (!php_output_handler_started(ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME) TSRMLS_CC)) {
                         php_zlib_output_compression_start(TSRMLS_C);
                 }
         }          }
   
        if (do_end) {        return status;
                err = deflate(&ZLIBG(stream), Z_FINISH); 
                buffer[outlen + start_offset - ZLIBG(stream).avail_out] = '\0'; 
        } 
 
        *p_buffer = buffer; 
        *p_buffer_len = outlen - ZLIBG(stream).avail_out; 
 
        return err; 
 }  }
 /* }}} */  /* }}} */
   
/* {{{ php_deflate_string/* {{{ OnUpdate_zlib_output_handler */
 */static PHP_INI_MH(OnUpdate_zlib_output_handler)
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) 
 {  {
        int err;        if (stage == PHP_INI_STAGE_RUNTIME && (php_output_get_status(TSRMLS_C) & PHP_OUTPUT_SENT)) {
                php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "Cannot change zlib.output_handler - headers already sent");
        if (do_start) {                return FAILURE;
                ZLIBG(stream).zalloc = php_zlib_alloc; 
                ZLIBG(stream).zfree = php_zlib_free; 
                ZLIBG(stream).opaque = Z_NULL; 
 
                switch (ZLIBG(compression_coding)) { 
                        case CODING_GZIP: 
                                /* windowBits is passed < 0 to suppress zlib header & trailer */ 
                                if (deflateInit2(&ZLIBG(stream), ZLIBG(output_compression_level), Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) { 
                                        /* TODO: print out error */ 
                                        return FAILURE; 
                                } 
 
                                ZLIBG(crc) = crc32(0L, Z_NULL, 0); 
                                break; 
 
                        case CODING_DEFLATE: 
                                if (deflateInit(&ZLIBG(stream), ZLIBG(output_compression_level)) != Z_OK) { 
                                        /* TODO: print out error */ 
                                        return FAILURE; 
                                } 
                                break; 
                } 
         }          }
   
        ZLIBG(stream).next_in = (Bytef *) str;        return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
        ZLIBG(stream).avail_in = (uInt) str_length;}
 /* }}} */
  
 /* {{{ INI */
 PHP_INI_BEGIN()
         STD_PHP_INI_BOOLEAN("zlib.output_compression",      "0", PHP_INI_ALL, OnUpdate_zlib_output_compression,       output_compression_default,       zend_zlib_globals, zlib_globals)
         STD_PHP_INI_ENTRY("zlib.output_compression_level", "-1", PHP_INI_ALL, OnUpdateLong,                           output_compression_level, zend_zlib_globals, zlib_globals)
         STD_PHP_INI_ENTRY("zlib.output_handler",             "", PHP_INI_ALL, OnUpdate_zlib_output_handler,           output_handler,           zend_zlib_globals, zlib_globals)
 PHP_INI_END()
   
        if (ZLIBG(compression_coding) == CODING_GZIP) {/* }}} */
                ZLIBG(crc) = crc32(ZLIBG(crc), (const Bytef *) str, str_length); 
        } 
   
        err = php_do_deflate(str_length, (Bytef **) newstr, new_length, do_start, do_end TSRMLS_CC);/* {{{ PHP_MINIT_FUNCTION */
        /* TODO: error handling (err may be Z_STREAM_ERROR, Z_BUF_ERROR, ?) */static PHP_MINIT_FUNCTION(zlib)
 {
         php_register_url_stream_wrapper("compress.zlib", &php_stream_gzip_wrapper TSRMLS_CC);
         php_stream_filter_register_factory("zlib.*", &php_zlib_filter_factory TSRMLS_CC);
   
        if (do_start && ZLIBG(compression_coding) == CODING_GZIP) {        php_output_handler_alias_register(ZEND_STRL("ob_gzhandler"), php_zlib_output_handler_init TSRMLS_CC);
                /* Write a very simple .gz header: */        php_output_handler_conflict_register(ZEND_STRL("ob_gzhandler"), php_zlib_output_conflict_check TSRMLS_CC);
                (*newstr)[0] = gz_magic[0];        php_output_handler_conflict_register(ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME), php_zlib_output_conflict_check TSRMLS_CC);
                (*newstr)[1] = gz_magic[1]; 
                (*newstr)[2] = Z_DEFLATED; 
                (*newstr)[3] = (*newstr)[4] = (*newstr)[5] = (*newstr)[6] = (*newstr)[7] = (*newstr)[8] = 0; 
                (*newstr)[9] = OS_CODE; 
                *new_length += 10; 
        } 
        if (do_end) { 
                if (ZLIBG(compression_coding) == CODING_GZIP) { 
                        char *trailer = (*newstr) + (*new_length); 
   
                        /* write crc & stream.total_in in LSB order */        REGISTER_LONG_CONSTANT("FORCE_GZIP", PHP_ZLIB_ENCODING_GZIP, CONST_CS|CONST_PERSISTENT);
                        trailer[0] = (char) ZLIBG(crc) & 0xFF;        REGISTER_LONG_CONSTANT("FORCE_DEFLATE", PHP_ZLIB_ENCODING_DEFLATE, CONST_CS|CONST_PERSISTENT);
                        trailer[1] = (char) (ZLIBG(crc) >> 8) & 0xFF; 
                        trailer[2] = (char) (ZLIBG(crc) >> 16) & 0xFF; 
                        trailer[3] = (char) (ZLIBG(crc) >> 24) & 0xFF; 
                        trailer[4] = (char) ZLIBG(stream).total_in & 0xFF; 
                        trailer[5] = (char) (ZLIBG(stream).total_in >> 8) & 0xFF; 
                        trailer[6] = (char) (ZLIBG(stream).total_in >> 16) & 0xFF; 
                        trailer[7] = (char) (ZLIBG(stream).total_in >> 24) & 0xFF; 
                        trailer[8] = '\0'; 
                        *new_length += 8; 
                } 
                deflateEnd(&ZLIBG(stream)); 
        } 
   
           REGISTER_LONG_CONSTANT("ZLIB_ENCODING_RAW", PHP_ZLIB_ENCODING_RAW, CONST_CS|CONST_PERSISTENT);
           REGISTER_LONG_CONSTANT("ZLIB_ENCODING_GZIP", PHP_ZLIB_ENCODING_GZIP, CONST_CS|CONST_PERSISTENT);
           REGISTER_LONG_CONSTANT("ZLIB_ENCODING_DEFLATE", PHP_ZLIB_ENCODING_DEFLATE, CONST_CS|CONST_PERSISTENT);
           REGISTER_INI_ENTRIES();
         return SUCCESS;          return SUCCESS;
 }  }
 /* }}} */  /* }}} */
   
/* {{{ proto string gzencode(string data [, int level [, int encoding_mode]])/* {{{ PHP_MSHUTDOWN_FUNCTION */
   GZ encode a string */static PHP_MSHUTDOWN_FUNCTION(zlib)
static PHP_FUNCTION(gzencode) 
 {  {
        char *data, *s2;        php_unregister_url_stream_wrapper("zlib" TSRMLS_CC);
        int data_len;        php_stream_filter_unregister_factory("zlib.*" TSRMLS_CC);
        long level = Z_DEFAULT_COMPRESSION, coding = CODING_GZIP; 
        int status; 
        z_stream stream; 
   
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &data, &data_len, &level, &coding) == FAILURE) {        UNREGISTER_INI_ENTRIES();
                return; 
        } 
   
        if ((level < -1) || (level > 9)) {        return SUCCESS;
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level(%ld) must be within -1..9", level); 
                RETURN_FALSE; 
        } 
 
        if ((coding != CODING_GZIP) && (coding != CODING_DEFLATE)) { 
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "encoding mode must be FORCE_GZIP or FORCE_DEFLATE"); 
                RETURN_FALSE; 
        } 
 
        stream.zalloc = php_zlib_alloc; 
        stream.zfree = php_zlib_free; 
        stream.opaque = Z_NULL; 
 
        stream.next_in = (Bytef *) data; 
        stream.avail_in = data_len; 
 
        stream.avail_out = stream.avail_in + (stream.avail_in / PHP_ZLIB_MODIFIER) + 15 + 1; /* room for \0 */ 
        s2 = (char *) emalloc(stream.avail_out + GZIP_HEADER_LENGTH + (coding == CODING_GZIP ? GZIP_FOOTER_LENGTH : 0)); 
 
        /* add gzip file header */ 
        s2[0] = gz_magic[0]; 
        s2[1] = gz_magic[1]; 
        s2[2] = Z_DEFLATED; 
        s2[3] = s2[4] = s2[5] = s2[6] = s2[7] = s2[8] = 0; /* time set to 0 */ 
        s2[9] = OS_CODE; 
 
        stream.next_out = &(s2[GZIP_HEADER_LENGTH]); 
 
        switch (coding) { 
                case CODING_GZIP: 
                        /* windowBits is passed < 0 to suppress zlib header & trailer */ 
                        if ((status = deflateInit2(&stream, level, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) != Z_OK) { 
                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status)); 
                                RETURN_FALSE; 
                        } 
 
                        break; 
                case CODING_DEFLATE: 
                        if ((status = deflateInit(&stream, level)) != Z_OK) { 
                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status)); 
                                RETURN_FALSE; 
                        } 
                        break; 
        } 
 
        status = deflate(&stream, Z_FINISH); 
        if (status != Z_STREAM_END) { 
                deflateEnd(&stream); 
                if (status == Z_OK) { 
                        status = Z_BUF_ERROR; 
                } 
        } else { 
                status = deflateEnd(&stream); 
        } 
 
        if (status == Z_OK) { 
                /* resize to buffer to the "right" size */ 
                s2 = erealloc(s2, stream.total_out + GZIP_HEADER_LENGTH + (coding == CODING_GZIP ? GZIP_FOOTER_LENGTH : 0) + 1); 
 
                if (coding == CODING_GZIP) { 
                        char *trailer = s2 + (stream.total_out + GZIP_HEADER_LENGTH); 
                        uLong crc = crc32(0L, Z_NULL, 0); 
 
                        crc = crc32(crc, (const Bytef *) data, data_len); 
 
                        /* write crc & stream.total_in in LSB order */ 
                        trailer[0] = (char) crc & 0xFF; 
                        trailer[1] = (char) (crc >> 8) & 0xFF; 
                        trailer[2] = (char) (crc >> 16) & 0xFF; 
                        trailer[3] = (char) (crc >> 24) & 0xFF; 
                        trailer[4] = (char) stream.total_in & 0xFF; 
                        trailer[5] = (char) (stream.total_in >> 8) & 0xFF; 
                        trailer[6] = (char) (stream.total_in >> 16) & 0xFF; 
                        trailer[7] = (char) (stream.total_in >> 24) & 0xFF; 
                        trailer[8] = '\0'; 
                } else { 
                        s2[stream.total_out + GZIP_HEADER_LENGTH + (coding == CODING_GZIP ? GZIP_FOOTER_LENGTH : 0)] = '\0'; 
                } 
                RETURN_STRINGL(s2, stream.total_out + GZIP_HEADER_LENGTH + (coding == CODING_GZIP ? GZIP_FOOTER_LENGTH : 0), 0); 
        } else { 
                efree(s2); 
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status)); 
                RETURN_FALSE; 
        } 
 }  }
 /* }}} */  /* }}} */
   
/* {{{ php_ob_gzhandler_check/* {{{ PHP_RINIT_FUNCTION */
 */static PHP_RINIT_FUNCTION(zlib)
int php_ob_gzhandler_check(TSRMLS_D) 
 {  {
        /* check for wrong usages */        ZLIBG(compression_coding) = 0;
        if (OG(ob_nesting_level > 0)) {    if (!ZLIBG(handler_registered)) {
                if (php_ob_handler_used("ob_gzhandler" TSRMLS_CC)) {        ZLIBG(output_compression) = ZLIBG(output_compression_default);
                        php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used twice");        php_zlib_output_compression_start(TSRMLS_C);
                        return FAILURE;    }
                } 
                if (php_ob_handler_used("mb_output_handler" TSRMLS_CC)) { 
                        php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used after 'mb_output_handler'"); 
                        return FAILURE; 
                } 
                if (php_ob_handler_used("URL-Rewriter" TSRMLS_CC)) { 
                        php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used after 'URL-Rewriter'"); 
                        return FAILURE; 
                } 
                if (php_ob_init_conflict("ob_gzhandler", "zlib output compression" TSRMLS_CC)) { 
                        return FAILURE; 
                } 
        } 
   
         return SUCCESS;          return SUCCESS;
 }  }
   
 /* }}} */  /* }}} */
   
/* {{{ proto string ob_gzhandler(string str, int mode)/* {{{ PHP_RSHUTDOWN_FUNCTION */
   Encode str based on accept-encoding setting - designed to be called from ob_start() */static PHP_RSHUTDOWN_FUNCTION(zlib)
static PHP_FUNCTION(ob_gzhandler) 
 {  {
        char *string;        php_zlib_cleanup_ob_gzhandler_mess(TSRMLS_C);
        int string_len;    ZLIBG(handler_registered) = 0;
        long mode; 
        zval **a_encoding; 
        zend_bool return_original = 0; 
        zend_bool do_start, do_end; 
   
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &string, &string_len, &mode) == FAILURE) {    return SUCCESS;
                return; 
        } 
 
        if (ZLIBG(ob_gzhandler_status) == -1) { 
                RETURN_FALSE; 
        } 
 
        zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); 
 
        if (!PG(http_globals)[TRACK_VARS_SERVER] 
                || zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING"), (void **) &a_encoding) == FAILURE 
        ) { 
                ZLIBG(ob_gzhandler_status) = -1; 
                RETURN_FALSE; 
        } 
 
        convert_to_string_ex(a_encoding); 
        if (php_memnstr(Z_STRVAL_PP(a_encoding), "gzip", 4, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) { 
                ZLIBG(compression_coding) = CODING_GZIP; 
        } else if (php_memnstr(Z_STRVAL_PP(a_encoding), "deflate", 7, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) { 
                ZLIBG(compression_coding) = CODING_DEFLATE; 
        } else { 
                ZLIBG(ob_gzhandler_status) = -1; 
                RETURN_FALSE; 
        } 
 
        do_start = ((mode & PHP_OUTPUT_HANDLER_START) ? 1 : 0); 
        do_end = ((mode & PHP_OUTPUT_HANDLER_END) ? 1 : 0); 
        Z_STRVAL_P(return_value) = NULL; 
        Z_STRLEN_P(return_value) = 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) { 
                Z_TYPE_P(return_value) = IS_STRING; 
                if (do_start) { 
                        switch (ZLIBG(compression_coding)) { 
                                case CODING_GZIP: 
                                        if (sapi_add_header("Content-Encoding: gzip", sizeof("Content-Encoding: gzip") - 1, 1) == FAILURE) { 
                                                return_original = 1; 
                                        } 
                                        if (sapi_add_header_ex("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1, 0 TSRMLS_CC)==FAILURE) { 
                                                return_original = 1; 
                                        } 
                                        break; 
                                case CODING_DEFLATE: 
                                        if (sapi_add_header("Content-Encoding: deflate", sizeof("Content-Encoding: deflate") - 1, 1) == FAILURE) { 
                                                return_original = 1; 
                                        } 
                                        if (sapi_add_header_ex("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1, 0 TSRMLS_CC)==FAILURE) { 
                                                return_original = 1; 
                                        } 
                                        break; 
                                default: 
                                        return_original = 1; 
                                        break; 
                        } 
                } 
 
                if (return_original) { 
                        zval_dtor(return_value); 
                } 
 
        } else { 
                return_original = 1; 
        } 
 
        if (return_original) { 
                /* return the original string */ 
                RETURN_STRINGL(string, string_len, 1); 
        } 
 }  }
 /* }}} */  /* }}} */
   
/* {{{ php_gzip_output_handler/* {{{ PHP_MINFO_FUNCTION */
 */static PHP_MINFO_FUNCTION(zlib)
static void php_gzip_output_handler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC) 
 {  {
        zend_bool do_start, do_end;        php_info_print_table_start();
         php_info_print_table_header(2, "ZLib Support", "enabled");
         php_info_print_table_row(2, "Stream Wrapper", "compress.zlib://");
         php_info_print_table_row(2, "Stream Filter", "zlib.inflate, zlib.deflate");
         php_info_print_table_row(2, "Compiled Version", ZLIB_VERSION);
         php_info_print_table_row(2, "Linked Version", (char *) zlibVersion());
         php_info_print_table_end();
   
        if (!ZLIBG(output_compression) || SG(sapi_headers).http_response_code == 204 || SG(sapi_headers).http_response_code == 304) {        DISPLAY_INI_ENTRIES();
                *handled_output = NULL; 
        } else { 
                do_start = (mode & PHP_OUTPUT_HANDLER_START ? 1 : 0); 
                do_end = (mode & PHP_OUTPUT_HANDLER_END ? 1 : 0); 
 
                if (do_start) { 
                        if (!SG(headers_sent) && !SG(request_info).no_headers) { 
                                switch (ZLIBG(compression_coding)) { 
                                        case CODING_GZIP: 
                                                sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1 TSRMLS_CC); 
                                                break; 
                                        case CODING_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, 0 TSRMLS_CC); 
                        } else { 
                                /* Disable compression if headers can not be set (Fix for bug #49816) */ 
                                ZLIBG(output_compression) = 0; 
                                *handled_output = NULL; 
                                return; 
                        } 
                } 
 
                if (php_deflate_string(output, output_len, handled_output, handled_output_len, do_start, do_end TSRMLS_CC) != SUCCESS) { 
                        zend_error(E_ERROR, "Compression failed"); 
                } 
        } 
 }  }
 /* }}} */  /* }}} */
   
/* {{{ php_enable_output_compression/* {{{ ZEND_MODULE_GLOBALS_CTOR */
 */static ZEND_MODULE_GLOBALS_CTOR_D(zlib)
static int php_enable_output_compression(int buffer_size TSRMLS_DC) 
 {  {
        zval **a_encoding;        zlib_globals->ob_gzhandler = NULL;
    zlib_globals->handler_registered = 0;
        zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); 
 
        if (!PG(http_globals)[TRACK_VARS_SERVER] 
                || zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING"), (void **) &a_encoding) == FAILURE 
        ) { 
                return FAILURE; 
        } 
 
        convert_to_string_ex(a_encoding); 
 
        if (php_memnstr(Z_STRVAL_PP(a_encoding), "gzip", 4, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) { 
                ZLIBG(compression_coding) = CODING_GZIP; 
        } else if (php_memnstr(Z_STRVAL_PP(a_encoding), "deflate", 7, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) { 
                ZLIBG(compression_coding) = CODING_DEFLATE; 
        } else { 
                return FAILURE; 
        } 
 
        php_ob_set_internal_handler(php_gzip_output_handler, (uint)buffer_size, "zlib output compression", 0 TSRMLS_CC); 
 
        if (ZLIBG(output_handler) && strlen(ZLIBG(output_handler))) { 
                php_start_ob_buffer_named(ZLIBG(output_handler), 0, 1 TSRMLS_CC); 
        } 
        return SUCCESS; 
 }  }
 /* }}} */  /* }}} */
   
/* {{{ php_zlib_output_compression_start() *//* {{{ php_zlib_module_entry */
static int php_zlib_output_compression_start(TSRMLS_D)zend_module_entry php_zlib_module_entry = {
{        STANDARD_MODULE_HEADER,
        switch (ZLIBG(output_compression)) {        "zlib",
                case 0:        php_zlib_functions,
                        break;        PHP_MINIT(zlib),
                case 1:        PHP_MSHUTDOWN(zlib),
                        ZLIBG(output_compression) = 4096;        PHP_RINIT(zlib),
                        /* break omitted intentionally */        PHP_RSHUTDOWN(zlib),
                default:        PHP_MINFO(zlib),
                        /* ZLIBG(compression_coding) should be 0 when zlib compression hasn't been started yet.. */        "2.0",
                        if (ZLIBG(compression_coding) == 0) {        PHP_MODULE_GLOBALS(zlib),
                                return php_enable_output_compression(ZLIBG(output_compression) TSRMLS_CC);        ZEND_MODULE_GLOBALS_CTOR_N(zlib),
                        }        NULL,
        }        NULL,
        return SUCCESS;        STANDARD_MODULE_PROPERTIES_EX
}};
 /* }}} */  /* }}} */
   
 /*  /*

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.5


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>