/* $Id$ */
#ifdef HAVE_CONFIG_H
-# include "config.h"
+# include "config.h"
#endif
#include "php.h"
static int php_zlib_output_encoding(TSRMLS_D)
{
zval **enc;
-
+
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")) {
}
}
}
-
return ZLIBG(compression_coding);
}
/* }}} */
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";'
}
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)) {
return FAILURE;
}
}
-
+
if (output_context->op & PHP_OUTPUT_HANDLER_CLEAN) {
/* free buffers */
deflateEnd(&ctx->Z);
-
+
if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) {
/* discard */
return SUCCESS;
ctx->buffer.used = 0;
}
} else {
-
if (output_context->in.used) {
/* append input */
if (ctx->buffer.free < 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;
-
+
ctx->Z.avail_in = ctx->buffer.used;
ctx->Z.next_in = (Bytef *) ctx->buffer.data;
ctx->Z.avail_out = output_context->out.size;
ctx->Z.next_out = (Bytef *) output_context->out.data;
-
+
if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) {
flags = Z_FINISH;
} else if (output_context->op & PHP_OUTPUT_HANDLER_FLUSH) {
flags = Z_FULL_FLUSH;
}
-
+
switch (deflate(&ctx->Z, flags)) {
case Z_OK:
if (flags == Z_FINISH) {
deflateEnd(&ctx->Z);
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);
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);
}
static void php_zlib_output_handler_dtor(void *opaq TSRMLS_DC)
{
php_zlib_context *ctx = (php_zlib_context *) opaq;
-
+
if (ctx) {
if (ctx->buffer.data) {
efree(ctx->buffer.data);
{
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;
}
ctx->Z.zfree = php_zlib_free;
php_output_handler_set_context(h, ctx, php_zlib_output_handler_dtor TSRMLS_CC);
}
-
+
return h;
}
/* }}} */
{
zval *zoh, *tmp;
php_output_handler *h;
-
+
switch (ZLIBG(output_compression)) {
case 0:
break;
{
int status;
z_stream Z;
-
+
memset(&Z, 0, sizeof(z_stream));
Z.zalloc = php_zlib_alloc;
Z.zfree = php_zlib_free;
-
+
if (Z_OK == (status = deflateInit2(&Z, level, Z_DEFLATED, encoding, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY))) {
*out_len = PHP_ZLIB_BUFFER_SIZE_GUESS(in_len);
*out_buf = emalloc(*out_len);
-
+
Z.next_in = (Bytef *) in_buf;
Z.next_out = (Bytef *) *out_buf;
Z.avail_in = in_len;
Z.avail_out = *out_len;
-
+
status = deflate(&Z, Z_FINISH);
deflateEnd(&Z);
-
+
if (Z_STREAM_END == status) {
/* size buffer down to actual length */
*out_buf = erealloc(*out_buf, Z.total_out + 1);
efree(*out_buf);
}
}
-
+
*out_buf = NULL;
*out_len = 0;
-
+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
return FAILURE;
}
{
int status, round = 0;
php_zlib_buffer buffer = {NULL, NULL, 0, 0, 0};
-
+
*buf = NULL;
*len = 0;
-
+
buffer.size = Z->avail_in;
-
+
do {
if ((max && (max < buffer.used)) || !(buffer.aptr = erealloc_recoverable(buffer.data, buffer.size))) {
status = Z_MEM_ERROR;
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);
-
+
buffer.used += buffer.free - Z->avail_out;
buffer.free = Z->avail_out;
#if 0
buffer.size += (buffer.size >> 3) + 1;
}
} while ((Z_BUF_ERROR == status || (Z_OK == status && Z->avail_in)) && ++round < 100);
-
+
if (status == Z_OK || status == Z_STREAM_END) {
buffer.data = erealloc(buffer.data, buffer.used + 1);
buffer.data[buffer.used] = '\0';
} else if (buffer.data) {
efree(buffer.data);
}
-
+
return status;
}
/* }}} */
{
int status = Z_DATA_ERROR;
z_stream Z;
-
+
memset(&Z, 0, sizeof(z_stream));
Z.zalloc = php_zlib_alloc;
Z.zfree = php_zlib_free;
if (Z_OK == status) {
Z.next_in = (Bytef *) in_buf;
Z.avail_in = in_len;
-
+
switch (status = inflate_rounds(&Z, max_len, out_buf, out_len)) {
case Z_OK:
case Z_STREAM_END:
inflateEnd(&Z);
return SUCCESS;
-
+
case Z_DATA_ERROR:
/* raw deflated data? */
if (PHP_ZLIB_ENCODING_ANY == encoding) {
inflateEnd(&Z);
}
}
-
+
*out_buf = NULL;
*out_len = 0;
-
+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
return FAILURE;
}
int flags = REPORT_ERRORS;
php_stream *stream;
long use_include_path = 0;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ts|l", &filename, &filename_len, &filename_type, &mode, &mode_len, &use_include_path) == FAILURE) {
return;
}
RETURN_FALSE;
}
php_stream_to_zval(stream, return_value);
-}
+}
/* }}} */
/* {{{ proto int readgzfile(string filename [, int use_include_path]) U
php_stream *stream;
int size;
long use_include_path = 0;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t|l", &filename, &filename_len, &filename_type, &use_include_path) == FAILURE) {
return;
}
{
int status, int_value;
char *ini_value;
-
+
if (new_value == NULL) {
return FAILURE;
}
-
+
if (!strncasecmp(new_value, "off", sizeof("off"))) {
new_value = "0";
new_value_length = sizeof("0");
new_value = "1";
new_value_length = sizeof("1");
}
-
+
int_value = zend_atoi(new_value, new_value_length);
ini_value = zend_ini_string("output_handler", sizeof("output_handler"), 0);
-
+
if (ini_value && *ini_value && int_value) {
php_error_docref("ref.outcontrol" TSRMLS_CC, E_CORE_ERROR, "Cannot use both zlib.output_compression and output_handler together!!");
return FAILURE;
return FAILURE;
}
}
-
+
status = OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
-
+
if (stage == PHP_INI_STAGE_RUNTIME && int_value) {
zval tmp;
-
+
INIT_PZVAL(&tmp);
ZVAL_ASCII_STRING(&tmp, PHP_ZLIB_OUTPUT_HANDLER_NAME, ZSTR_DUPLICATE);
if (!php_output_handler_started(&tmp TSRMLS_CC)) {
}
zval_dtor(&tmp);
}
-
return status;
}
/* }}} */
{
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);
-
+
PHP_OUTPUT_ALIAS_REGISTER("ob_gzhandler", php_zlib_output_handler_init);
PHP_OUTPUT_CONFLICT_REGISTER("ob_gzhandler", php_zlib_output_conflict_check);
PHP_OUTPUT_CONFLICT_REGISTER(PHP_ZLIB_OUTPUT_HANDLER_NAME, php_zlib_output_conflict_check);
-
+
REGISTER_LONG_CONSTANT("FORCE_GZIP", PHP_ZLIB_ENCODING_GZIP, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("FORCE_DEFLATE", PHP_ZLIB_ENCODING_DEFLATE, CONST_CS|CONST_PERSISTENT);
-
+
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;
}
/* }}} */
{
php_unregister_url_stream_wrapper("zlib" TSRMLS_CC);
php_stream_filter_unregister_factory("zlib.*" TSRMLS_CC);
-
+
UNREGISTER_INI_ENTRIES();
+
return SUCCESS;
}
/* }}} */
static PHP_RINIT_FUNCTION(zlib)
{
ZLIBG(compression_coding) = 0;
-
+
php_zlib_output_compression_start(TSRMLS_C);
-
+
return SUCCESS;
}
/* }}} */