From: Zeev Suraski Date: Sun, 4 Mar 2001 15:12:38 +0000 (+0000) Subject: Implemented chunked output buffering support - it's quite cool! X-Git-Tag: php-4.0.5RC1~90 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=39724f6e4a6eeb83ca0d32f1202b4a135b5e8e44;p=php Implemented chunked output buffering support - it's quite cool! --- diff --git a/NEWS b/NEWS index 97a71fe93c..44501766b5 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP 4.0 NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 200?, Version 4.0.5 +- Improved ob_gzhandler() to support chunked output buffering - it's recommended + to use it with 4KB chunks (Zeev) +- Fixed chunked output buffering (Zeev) - Forced call_user_method() and call_user_method_array() to take the object argument by reference. (Andrei) - Fixed binding of ROWIDs in OCI8. (Thies) diff --git a/ext/zlib/php_zlib.h b/ext/zlib/php_zlib.h index 7fa8916992..43c68f2b2d 100644 --- a/ext/zlib/php_zlib.h +++ b/ext/zlib/php_zlib.h @@ -32,6 +32,7 @@ typedef struct { int compression_coding; z_stream stream; uLong crc; + int ob_gzhandler_status; } php_zlib_globals; extern zend_module_entry php_zlib_module_entry; @@ -39,6 +40,7 @@ extern zend_module_entry php_zlib_module_entry; PHP_MINIT_FUNCTION(zlib); PHP_MSHUTDOWN_FUNCTION(zlib); +PHP_RINIT_FUNCTION(zlib); PHP_MINFO_FUNCTION(zlib); PHP_FUNCTION(gzopen); PHP_FUNCTION(gzclose); diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index 97fea21758..e541cf04c7 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -111,7 +111,7 @@ zend_module_entry php_zlib_module_entry = { php_zlib_functions, PHP_MINIT(zlib), PHP_MSHUTDOWN(zlib), - NULL, + PHP_RINIT(zlib), NULL, PHP_MINFO(zlib), STANDARD_MODULE_PROPERTIES @@ -158,6 +158,15 @@ PHP_MINIT_FUNCTION(zlib) return SUCCESS; } +PHP_RINIT_FUNCTION(zlib) +{ + ZLIBLS_FETCH(); + + ZLIBG(ob_gzhandler_status) = 0; + return SUCCESS; +} + + PHP_MSHUTDOWN_FUNCTION(zlib) { #if HAVE_FOPENCOOKIE @@ -930,31 +939,35 @@ PHP_FUNCTION(gzinflate) -static int php_do_deflate(uint str_length, Bytef **p_buffer, uint *p_buf_used ZLIBLS_DC) +static int php_do_deflate(uint str_length, Bytef **p_buffer, uint *p_buf_used, zend_bool do_start, zend_bool do_end ZLIBLS_DC) { Bytef *buffer; uInt prev_outlen, outlen; int err; + int start_offset = (do_start?10:0); + int end_offset = (do_end?8:0); outlen = sizeof(char) * (str_length * 1.001 + 12); - buffer = (Bytef *) emalloc(outlen+10+8); /* 10+8 for the header and trailer */ + buffer = (Bytef *) emalloc(outlen+start_offset+end_offset); - ZLIBG(stream).next_out = buffer+10; + ZLIBG(stream).next_out = buffer+start_offset; ZLIBG(stream).avail_out = outlen; - err = deflate(&ZLIBG(stream), Z_NO_FLUSH); + err = deflate(&ZLIBG(stream), Z_SYNC_FLUSH); while (err == Z_OK && !ZLIBG(stream).avail_out) { prev_outlen = outlen; outlen *= 3; - buffer = realloc(buffer, outlen+10+8); + buffer = realloc(buffer, outlen+start_offset+end_offset); - ZLIBG(stream).next_out = buffer+10 + prev_outlen; + ZLIBG(stream).next_out = buffer+start_offset + prev_outlen; ZLIBG(stream).avail_out = prev_outlen * 2; - err = deflate(&ZLIBG(stream), Z_NO_FLUSH); + err = deflate(&ZLIBG(stream), Z_SYNC_FLUSH); } - err = deflate(&ZLIBG(stream), Z_FINISH); + if (do_end) { + err = deflate(&ZLIBG(stream), Z_FINISH); + } *p_buffer = buffer; *p_buf_used = outlen - ZLIBG(stream).avail_out; @@ -962,7 +975,7 @@ static int php_do_deflate(uint str_length, Bytef **p_buffer, uint *p_buf_used ZL } -int php_deflate_string(const char *str, uint str_length, char **newstr, uint *new_length, int coding) +int php_deflate_string(const char *str, uint str_length, char **newstr, uint *new_length, int coding, zend_bool do_start, zend_bool do_end) { Bytef *buffer; uInt buf_used; @@ -973,66 +986,73 @@ int php_deflate_string(const char *str, uint str_length, char **newstr, uint *ne ZLIBG(compression_coding) = coding; - ZLIBG(stream).zalloc = Z_NULL; - ZLIBG(stream).zfree = Z_NULL; - ZLIBG(stream).opaque = Z_NULL; - - switch (coding) { - case CODING_GZIP: - /* windowBits is passed < 0 to suppress zlib header & trailer */ - if (deflateInit2(&ZLIBG(stream), Z_DEFAULT_COMPRESSION, Z_DEFLATED, - -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY) - != Z_OK) { - /* TODO: print out error */ - return FAILURE; - } + if (do_start) { + ZLIBG(stream).zalloc = Z_NULL; + ZLIBG(stream).zfree = Z_NULL; + ZLIBG(stream).opaque = Z_NULL; + switch (coding) { + case CODING_GZIP: + /* windowBits is passed < 0 to suppress zlib header & trailer */ + if (deflateInit2(&ZLIBG(stream), Z_DEFAULT_COMPRESSION, Z_DEFLATED, + -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY) + != Z_OK) { + /* TODO: print out error */ + return FAILURE; + } - /* Write a very simple .gz header: */ - sprintf(header_buffer, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], - gz_magic[1], Z_DEFLATED, 0 /*flags*/, - 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); - ZLIBG(crc) = crc32(0L, Z_NULL, 0); - break; - case CODING_DEFLATE: - if (deflateInit(&ZLIBG(stream), Z_DEFAULT_COMPRESSION) != Z_OK) { - /* TODO: print out error */ - return FAILURE; - } - break; + /* Write a very simple .gz header: */ + sprintf(header_buffer, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], + gz_magic[1], Z_DEFLATED, 0 /*flags*/, + 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + ZLIBG(crc) = crc32(0L, Z_NULL, 0); + break; + case CODING_DEFLATE: + if (deflateInit(&ZLIBG(stream), Z_DEFAULT_COMPRESSION) != Z_OK) { + /* TODO: print out error */ + return FAILURE; + } + break; + } } ZLIBG(stream).next_in = (Bytef*) str; ZLIBG(stream).avail_in = (uInt) str_length; - + if (ZLIBG(compression_coding) == 1) { - ZLIBG(crc) = crc32(ZLIBG(crc), (const Bytef *)str, str_length); + ZLIBG(crc) = crc32(ZLIBG(crc), (const Bytef *) str, str_length); } - err = php_do_deflate(str_length, &buffer, &buf_used ZLIBLS_CC); + err = php_do_deflate(str_length, &buffer, &buf_used, do_start, do_end ZLIBLS_CC); /* TODO: error handling (err may be Z_STREAM_ERROR, Z_BUF_ERROR, ?) */ - - if (ZLIBG(compression_coding) == 1) { - /* write crc & stream.total_in in LSB order */ - sprintf(trailer_buffer, "%c%c%c%c%c%c%c%c", - (char) ZLIBG(crc) & 0xFF, - (char) (ZLIBG(crc) >> 8) & 0xFF, - (char) (ZLIBG(crc) >> 16) & 0xFF, - (char) (ZLIBG(crc) >> 24) & 0xFF, - (char) ZLIBG(stream).total_in & 0xFF, - (char) (ZLIBG(stream).total_in >> 8) & 0xFF, - (char) (ZLIBG(stream).total_in >> 16) & 0xFF, - (char) (ZLIBG(stream).total_in >> 24) & 0xFF); + if (do_end) { + if (ZLIBG(compression_coding) == 1) { + /* write crc & stream.total_in in LSB order */ + sprintf(trailer_buffer, "%c%c%c%c%c%c%c%c", + (char) ZLIBG(crc) & 0xFF, + (char) (ZLIBG(crc) >> 8) & 0xFF, + (char) (ZLIBG(crc) >> 16) & 0xFF, + (char) (ZLIBG(crc) >> 24) & 0xFF, + (char) ZLIBG(stream).total_in & 0xFF, + (char) (ZLIBG(stream).total_in >> 8) & 0xFF, + (char) (ZLIBG(stream).total_in >> 16) & 0xFF, + (char) (ZLIBG(stream).total_in >> 24) & 0xFF); + } } - - memcpy(buffer, header_buffer, 10); - memcpy(buffer+10+buf_used, trailer_buffer, 8); - - *new_length = buf_used + 10 + 8; *newstr = buffer; - deflateEnd(&ZLIBG(stream)); + *new_length = buf_used; + + if (do_start) { + memcpy(buffer, header_buffer, 10); + *new_length += 10; + } + if (do_end) { + memcpy(buffer+buf_used+(do_start?10:0), trailer_buffer, 8); + *new_length += 8; + deflateEnd(&ZLIBG(stream)); + } return SUCCESS; } @@ -1044,14 +1064,14 @@ PHP_FUNCTION(gzencode) int coding; switch(ZEND_NUM_ARGS()) { - case CODING_GZIP: + case 1: if (zend_get_parameters_ex(1, &zv_string)==FAILURE) { RETURN_FALSE; } convert_to_string_ex(zv_string); coding = 1; break; - case CODING_DEFLATE: + case 2: if (zend_get_parameters_ex(2, &zv_string, &zv_coding)==FAILURE) { RETURN_FALSE; } @@ -1063,7 +1083,7 @@ PHP_FUNCTION(gzencode) ZEND_WRONG_PARAM_COUNT(); break; } - if (php_deflate_string(Z_STRVAL_PP(zv_string), Z_STRLEN_PP(zv_string), &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value), coding)==SUCCESS) { + if (php_deflate_string(Z_STRVAL_PP(zv_string), Z_STRLEN_PP(zv_string), &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value), coding, 1, 1)==SUCCESS) { Z_TYPE_P(return_value) = IS_STRING; } else { RETURN_FALSE; @@ -1074,20 +1094,23 @@ PHP_FUNCTION(gzencode) PHP_FUNCTION(ob_gzhandler) { int coding; - zval **zv_string; + zval **zv_string, **zv_mode; zval **data, **a_encoding; zend_bool return_original=0; + zend_bool do_start, do_end; - if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &zv_string)==FAILURE) { + if (ZEND_NUM_ARGS()!=2 || zend_get_parameters_ex(2, &zv_string, &zv_mode)==FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - if (zend_hash_find(&EG(symbol_table), "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"), (void **) &data)==FAILURE + if (ZLIBG(ob_gzhandler_status)==-1 + || zend_hash_find(&EG(symbol_table), "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"), (void **) &data)==FAILURE || Z_TYPE_PP(data)!=IS_ARRAY || zend_hash_find(Z_ARRVAL_PP(data), "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING"), (void **) &a_encoding)==FAILURE) { /* return the original string */ *return_value = **zv_string; zval_copy_ctor(return_value); + ZLIBG(ob_gzhandler_status)=-1; return; } convert_to_string_ex(a_encoding); @@ -1098,31 +1121,39 @@ PHP_FUNCTION(ob_gzhandler) } else { RETURN_FALSE; } - if (php_deflate_string(Z_STRVAL_PP(zv_string), Z_STRLEN_PP(zv_string), &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value), coding)==SUCCESS) { + + convert_to_long_ex(zv_mode); + do_start = ((Z_LVAL_PP(zv_mode) & PHP_OUTPUT_HANDLER_START) ? 1 : 0); + do_end = ((Z_LVAL_PP(zv_mode) & PHP_OUTPUT_HANDLER_END) ? 1 : 0); + if (php_deflate_string(Z_STRVAL_PP(zv_string), Z_STRLEN_PP(zv_string), &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value), coding, do_start, do_end)==SUCCESS) { Z_TYPE_P(return_value) = IS_STRING; - switch (coding) { - case CODING_GZIP: - if (sapi_add_header("Content-Encoding: gzip", sizeof("Content-Encoding: gzip") - 1, 1)==FAILURE) { + if (do_start) { + switch (coding) { + case CODING_GZIP: + if (sapi_add_header("Content-Encoding: gzip", sizeof("Content-Encoding: gzip") - 1, 1)==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; + } + break; + default: return_original = 1; - } - break; - case CODING_DEFLATE: - if (sapi_add_header("Content-Encoding: deflate", sizeof("Content-Encoding: deflate") - 1, 1)==FAILURE) { - return_original = 1; - } - break; - default: - return_original = 1; - break; + break; + } } if (return_original) { zval_dtor(return_value); +#if 0 } else { char lenbuf[64]; sprintf(lenbuf,"Content-Length: %d",Z_STRLEN_P(return_value)); sapi_add_header(lenbuf,strlen(lenbuf), 1); +#endif } } else { return_original = 1; @@ -1134,11 +1165,3 @@ PHP_FUNCTION(ob_gzhandler) zval_copy_ctor(return_value); } } - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - */