cvs: php4 / php.ini-dist php.ini-recommended /ext/standard head.c /ext/zlib php_zlib.h zlib.c /main main.c output.c php_output.h
| From: | Marcus B�rger | Date: | Fri, 09 Aug 2002 22:29:59 +0000 |
| Subject: | cvs: php4 / php.ini-dist php.ini-recommended /ext/standard head.c /ext/zlib php_zlib.h zlib.c /main main.c output.c php_output.h | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-13241@lists.php.net to get a copy of this message | ||
helly Fri Aug 9 18:29:59 2002 EDT
Modified files:
/php4/ext/standard head.c
/php4/main main.c output.c php_output.h
/php4 php.ini-dist php.ini-recommended
/php4/ext/zlib php_zlib.h zlib.c
Log:
Improved handling of output buffers (see news)\n#No trim for the string parameter...
Index: php4/ext/standard/head.c diff -u php4/ext/standard/head.c:1.60 php4/ext/standard/head.c:1.61 --- php4/ext/standard/head.c:1.60 Fri Aug 9 16:53:37 2002 +++ php4/ext/standard/head.c Fri Aug 9 18:29:57 2002 @@ -15,7 +15,7 @@ | Author: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | +----------------------------------------------------------------------+ */ -/* $Id: head.c,v 1.60 2002/08/09 20:53:37 helly Exp $ */ +/* $Id: head.c,v 1.61 2002/08/09 22:29:57 helly Exp $ */ #include <stdio.h> #include "php.h" @@ -126,9 +126,7 @@ ctr.line_len = strlen(cookie); result = sapi_header_op(SAPI_HEADER_ADD, &ctr TSRMLS_CC); - if (result == FAILURE) { - efree(cookie); - } + efree(cookie); return result; } Index: php4/main/main.c diff -u php4/main/main.c:1.475 php4/main/main.c:1.476 --- php4/main/main.c:1.475 Fri Aug 9 17:57:03 2002 +++ php4/main/main.c Fri Aug 9 18:29:57 2002 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: main.c,v 1.475 2002/08/09 21:57:03 helly Exp $ */ +/* $Id: main.c,v 1.476 2002/08/09 22:29:57 helly Exp $ */ /* {{{ includes */ @@ -813,13 +813,7 @@ } if (PG(output_handler) && PG(output_handler)[0]) { - zval *output_handler; - - ALLOC_INIT_ZVAL(output_handler); - Z_STRLEN_P(output_handler) = strlen(PG(output_handler)); /* this can be optimized */ - Z_STRVAL_P(output_handler) = estrndup(PG(output_handler), Z_STRLEN_P(output_handler)); - Z_TYPE_P(output_handler) = IS_STRING; - php_start_ob_buffer(output_handler, 0, 1 TSRMLS_CC); + php_start_ob_buffer_named(PG(output_handler), 0, 1 TSRMLS_CC); } else if (PG(output_buffering)) { if (PG(output_buffering)>1) { Index: php4/main/output.c diff -u php4/main/output.c:1.105 php4/main/output.c:1.106 --- php4/main/output.c:1.105 Mon Aug 5 14:54:53 2002 +++ php4/main/output.c Fri Aug 9 18:29:57 2002 @@ -14,10 +14,11 @@ +----------------------------------------------------------------------+ | Authors: Zeev Suraski <zeev@zend.com> | | Thies C. Arntzen <thies@thieso.net> | + | Marcus Boerger <helly@php.net> | +----------------------------------------------------------------------+ */ -/* $Id: output.c,v 1.105 2002/08/05 18:54:53 helly Exp $ */ +/* $Id: output.c,v 1.106 2002/08/09 22:29:57 helly Exp $ */ #include "php.h" #include "ext/standard/head.h" @@ -30,7 +31,7 @@ static int php_ub_body_write_no_header(const char *str, uint str_length TSRMLS_DC); static int php_b_body_write(const char *str, uint str_length TSRMLS_DC); -static void php_ob_init(uint initial_size, uint block_size, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC); +static int php_ob_init(uint initial_size, uint block_size, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC); static void php_ob_append(const char *text, uint text_length TSRMLS_DC); #if 0 static void php_ob_prepend(const char *text, uint text_length); @@ -114,16 +115,39 @@ * Start output buffering */ PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC) { + uint initial_size, block_size; + if (OG(ob_lock)) { + php_error(E_ERROR, "%s() Cannot use output buffering in output buffering display handlers", get_active_function_name(TSRMLS_C)); return FAILURE; } if (chunk_size) { - php_ob_init((chunk_size*3/2), chunk_size/2, output_handler, chunk_size, erase TSRMLS_CC); + initial_size = (chunk_size*3/2); + block_size = chunk_size/2; } else { - php_ob_init(40*1024, 10*1024, output_handler, chunk_size, erase TSRMLS_CC); + initial_size = 40*1024; + block_size = 10*1024; } - OG(php_body_write) = php_b_body_write; - return SUCCESS; + return php_ob_init(initial_size, block_size, output_handler, chunk_size, erase TSRMLS_CC); +} +/* }}} */ + + +/* {{{ php_start_ob_buffer_named + * Start output buffering */ +PHPAPI int php_start_ob_buffer_named(const char *output_handler_name, uint chunk_size, zend_bool erase TSRMLS_DC) +{ + zval *output_handler; + int result; + + ALLOC_INIT_ZVAL(output_handler); + Z_STRLEN_P(output_handler) = strlen(output_handler_name); /* this can be optimized */ + Z_STRVAL_P(output_handler) = estrndup(output_handler_name, Z_STRLEN_P(output_handler)); + Z_TYPE_P(output_handler) = IS_STRING; + result = php_start_ob_buffer(output_handler, chunk_size, erase TSRMLS_CC); + zval_dtor(output_handler); + FREE_ZVAL(output_handler); + return result; } /* }}} */ @@ -333,10 +357,43 @@ } /* }}} */ -/* {{{ php_ob_init +/* {{{ php_ob_init_conflict + * Returns 1 if handler_set is already used and generates error message + */ +static int php_ob_init_conflict(char *handler_new, char *handler_set TSRMLS_DC) +{ + if (php_ob_handler_used(handler_set TSRMLS_CC)) + { + php_error(E_WARNING, "%s() output handler '%s' conflicts with '%s'", get_active_function_name(TSRMLS_C), handler_new, handler_set); + return 1; + } + return 0; +} +/* }}} */ + +/* {{{ php_ob_init_named */ -static void php_ob_init(uint initial_size, uint block_size, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC) +static int php_ob_init_named(uint initial_size, uint block_size, char *handler_name, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC) { + int handler_gz, handler_mb, handler_ic; + + /* check for specific handlers where rules apply */ + handler_gz = strcmp(handler_name, "ob_gzhandler"); + handler_mb = strcmp(handler_name, "mb_output_handler"); + handler_ic = strcmp(handler_name, "ob_iconv_handler"); + /* apply rules */ + if (!handler_gz || !handler_mb || !handler_ic) { + if (php_ob_handler_used(handler_name TSRMLS_CC)) { + php_error(E_WARNING, "%s() output handler '%s' cannot be used twice", get_active_function_name(TSRMLS_C), handler_name); + return FAILURE; + } + if (!handler_gz && php_ob_init_conflict(handler_name, "zlib output compression" TSRMLS_CC)) + return FAILURE; + if (!handler_mb && php_ob_init_conflict(handler_name, "ob_iconv_handler" TSRMLS_CC)) + return FAILURE; + if (!handler_ic && php_ob_init_conflict(handler_name, "mb_output_handler" TSRMLS_CC)) + return FAILURE; + } if (OG(ob_nesting_level)>0) { if (OG(ob_nesting_level)==1) { /* initialize stack */ zend_stack_init(&OG(ob_buffers)); @@ -352,37 +409,95 @@ OG(active_ob_buffer).chunk_size = chunk_size; OG(active_ob_buffer).status = 0; OG(active_ob_buffer).internal_output_handler = NULL; + OG(active_ob_buffer).handler_name = estrdup(handler_name&&handler_name[0]?handler_name:"default output handler"); + OG(active_ob_buffer).erase = erase; + OG(php_body_write) = php_b_body_write; + return SUCCESS; +} +/* }}} */ + +/* {{{ php_ob_handler_from_string + * Create zval output handler from string + */ +static zval* php_ob_handler_from_string(const char *handler_name TSRMLS_DC) +{ + zval *output_handler; + + ALLOC_INIT_ZVAL(output_handler); + Z_STRLEN_P(output_handler) = strlen(handler_name); /* this can be optimized */ + Z_STRVAL_P(output_handler) = estrndup(handler_name, Z_STRLEN_P(output_handler)); + Z_TYPE_P(output_handler) = IS_STRING; + return output_handler; +} +/* }}} */ + +/* {{{ php_ob_init + */ +static int php_ob_init(uint initial_size, uint block_size, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC) +{ + int res, result, len; + char *handler_name, *next_handler_name; + HashPosition pos; + zval **tmp; + zval *handler_zval; + if (output_handler && output_handler->type == IS_STRING) { - OG(active_ob_buffer).handler_name = estrndup(Z_STRVAL_P(output_handler), Z_STRLEN_P(output_handler)); + result = 0; + handler_name = Z_STRVAL_P(output_handler); + while ((next_handler_name=strchr(handler_name, ',')) != NULL) { + len = next_handler_name-handler_name; + next_handler_name = estrndup(handler_name, len); + handler_zval = php_ob_handler_from_string(next_handler_name TSRMLS_CC); + res = php_ob_init_named(initial_size, block_size, next_handler_name, handler_zval, chunk_size, erase TSRMLS_CC); + result &= res; + if (!res==SUCCESS) { + zval_dtor(handler_zval); + FREE_ZVAL(handler_zval); + } + handler_name += len+1; + efree(next_handler_name); + } + handler_zval = php_ob_handler_from_string(handler_name TSRMLS_CC); + res = php_ob_init_named(initial_size, block_size, handler_name, handler_zval, chunk_size, erase TSRMLS_CC); + result &= res; + if (!res==SUCCESS) { + zval_dtor(handler_zval); + FREE_ZVAL(handler_zval); + } + result = result ? SUCCESS : FAILURE; } else if (output_handler && output_handler->type == IS_ARRAY) { - /* FIXME: Array type is not supported yet. - See call_user_function_ex() for detials. */ - OG(active_ob_buffer).handler_name = estrdup("array is not supported yet"); + result = 0; + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(output_handler), &pos); + while (zend_hash_get_current_data_ex(Z_ARRVAL_P(output_handler), (void **)&tmp, &pos) == SUCCESS) { + result &= php_ob_init(initial_size, block_size, *tmp, chunk_size, erase TSRMLS_CC); + zend_hash_move_forward_ex(Z_ARRVAL_P(output_handler), &pos); + } + result = result ? SUCCESS : FAILURE; } else { - OG(active_ob_buffer).handler_name = estrdup("default output handler"); + if (output_handler) { + SEPARATE_ZVAL(&output_handler); + output_handler->refcount++; + } + result = php_ob_init_named(initial_size, block_size, "default output handler", output_handler, chunk_size, erase TSRMLS_CC); } - OG(active_ob_buffer).erase = erase; + return result; } /* }}} */ /* {{{ php_ob_list_each */ - static int php_ob_list_each(php_ob_buffer *ob_buffer, zval *ob_handler_array) { - if (!strcmp(ob_buffer->handler_name, "zlib output compression") && ob_buffer->internal_output_handler) { - add_next_index_string(ob_handler_array, "ob_gzhandler", 1); - } else { - add_next_index_string(ob_handler_array, ob_buffer->handler_name, 1); - } + add_next_index_string(ob_handler_array, ob_buffer->handler_name, 1); return 0; } /* }}} */ /* {{{ proto array ob_list_handlers() - List all output_buffers in an array */ + * List all output_buffers in an array + */ PHP_FUNCTION(ob_list_handlers) { if (ZEND_NUM_ARGS()!=0) { @@ -404,12 +519,11 @@ /* }}} */ /* {{{ php_ob_used_each - Sets handler_name to NULL is found + * Sets handler_name to NULL is found */ static int php_ob_handler_used_each(php_ob_buffer *ob_buffer, char **handler_name) { - if ((!strcmp(ob_buffer->handler_name, "zlib output compression") && ob_buffer->internal_output_handler && !strcmp("ob_gzhandler", *handler_name)) - || !strcmp(ob_buffer->handler_name, *handler_name)) + if (!strcmp(ob_buffer->handler_name, *handler_name)) { *handler_name = NULL; return 1; @@ -419,7 +533,7 @@ /* }}} */ /* {{{ php_ob_used - returns 1 if given handler_name is used as output_handler + * returns 1 if given handler_name is used as output_handler */ PHPAPI int php_ob_handler_used(char *handler_name TSRMLS_DC) { @@ -574,7 +688,7 @@ * HEAD support */ -/* {{{ proto void ob_start([ string user_function [, int chunk_size [, bool erase]]]) +/* {{{ proto boolean ob_start([ string|array user_function [, int chunk_size [, bool erase]]]) Turn on Output Buffering (specifying an optional output handler). */ PHP_FUNCTION(ob_start) { @@ -585,20 +699,9 @@ if (zend_parse_parameters(argc TSRMLS_CC, "|zlb", &output_handler, &chunk_size, &erase) == FAILURE) - return; + RETURN_FALSE; - if (output_handler) { - SEPARATE_ZVAL(&output_handler); - output_handler->refcount++; - } if (php_start_ob_buffer(output_handler, chunk_size, erase TSRMLS_CC)==FAILURE) { - if (SG(headers_sent) && !SG(request_info).headers_only) { - OG(php_body_write) = php_ub_body_write_no_header; - } else { - OG(php_body_write) = php_ub_body_write; - } - OG(ob_nesting_level) = 0; - php_error(E_ERROR, "Cannot use output buffering in output buffering display handlers"); RETURN_FALSE; } RETURN_TRUE; @@ -754,41 +857,29 @@ } -/* {{{ proto array ob_get_status([bool full_status]) - Return the nesting level of the output buffer */ +/* {{{ proto false|array ob_get_status([bool full_status]) + Return the status of the active or all output buffers */ PHP_FUNCTION(ob_get_status) { int argc = ZEND_NUM_ARGS(); zend_bool full_status = 0; if (zend_parse_parameters(argc TSRMLS_CC, "|b", &full_status) == FAILURE ) - return; + RETURN_FALSE; if (array_init(return_value) == FAILURE) { RETURN_FALSE; } if (full_status) { - zval *elem; - - zend_stack_apply_with_argument(&OG(ob_buffers), ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *elem, void *))php_ob_buffer_status, return_value); - - MAKE_STD_ZVAL(elem); - if (array_init(elem)) - RETURN_FALSE; - - if (OG(active_ob_buffer).internal_output_handler) { - add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_INTERNAL); + if (OG(ob_nesting_level)>1) { + zend_stack_apply_with_argument(&OG(ob_buffers), ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *elem, void *))php_ob_buffer_status, return_value); } - else { - add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_USER); + if (OG(ob_nesting_level)>0 && php_ob_buffer_status(&OG(active_ob_buffer), return_value)==FAILURE) { + RETURN_FALSE; } - add_assoc_long(elem, "status", OG(active_ob_buffer).status); - add_assoc_string(elem, "name", OG(active_ob_buffer).handler_name, 1); - add_assoc_bool(elem, "del", OG(active_ob_buffer).erase); - add_next_index_zval(return_value, elem); } - else { + else if (OG(ob_nesting_level)>0) { add_assoc_long(return_value, "level", OG(ob_nesting_level)); if (OG(active_ob_buffer).internal_output_handler) { add_assoc_long(return_value, "type", PHP_OUTPUT_HANDLER_INTERNAL); Index: php4/main/php_output.h diff -u php4/main/php_output.h:1.39 php4/main/php_output.h:1.40 --- php4/main/php_output.h:1.39 Mon Aug 5 14:54:53 2002 +++ php4/main/php_output.h Fri Aug 9 18:29:57 2002 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_output.h,v 1.39 2002/08/05 18:54:53 helly Exp $ */ +/* $Id: php_output.h,v 1.40 2002/08/09 22:29:57 helly Exp $ */ #ifndef PHP_OUTPUT_H #define PHP_OUTPUT_H @@ -26,10 +26,11 @@ PHPAPI void php_output_startup(void); PHPAPI void php_output_activate(TSRMLS_D); PHPAPI void php_output_set_status(zend_bool status TSRMLS_DC); -void php_output_register_constants(TSRMLS_D); +PHPAPI void php_output_register_constants(TSRMLS_D); PHPAPI int php_body_write(const char *str, uint str_length TSRMLS_DC); PHPAPI int php_header_write(const char *str, uint str_length TSRMLS_DC); PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC); +PHPAPI int php_start_ob_buffer_named(const char *output_handler_name, uint chunk_size, zend_bool erase TSRMLS_DC); PHPAPI void php_end_ob_buffer(zend_bool send_buffer, zend_bool just_flush TSRMLS_DC); PHPAPI void php_end_ob_buffers(zend_bool send_buffer TSRMLS_DC); PHPAPI int php_ob_get_buffer(zval *p TSRMLS_DC); Index: php4/php.ini-dist diff -u php4/php.ini-dist:1.140 php4/php.ini-dist:1.141 --- php4/php.ini-dist:1.140 Fri Aug 9 02:18:46 2002 +++ php4/php.ini-dist Fri Aug 9 18:29:57 2002 @@ -98,15 +98,21 @@ : is doing. ; NOTE: You cannot use both "mb_output_handler" with "ob_inconv_handler" ; and you cannot use both "ob_gzhandler" and "zlib.output_compression". -output_handler = +;output_handler = ; Transparent output compression using the zlib library ; Valid values for this option are 'off', 'on', or a specific buffer size ; to be used for compression (default is 4KB) ; ; Note: output_handler must be empty if this is set 'On' !!!! +; Instead you must use zlib.output_handler. ; zlib.output_compression = Off + +; You cannot specify additional output handlers if zlib.output_compression +; is activated here. This setting does the same as output_handler but in +; a different order. +;zlib.output_handler = ; Implicit flush tells PHP to tell the output layer to flush itself ; automatically after every output block. This is equivalent to calling the Index: php4/php.ini-recommended diff -u php4/php.ini-recommended:1.93 php4/php.ini-recommended:1.94 --- php4/php.ini-recommended:1.93 Fri Aug 9 02:17:06 2002 +++ php4/php.ini-recommended Fri Aug 9 18:29:58 2002 @@ -111,15 +111,21 @@ : is doing. ; NOTE: You cannot use both "mb_output_handler" with "ob_inconv_handler" ; and you cannot use both "ob_gzhandler" and "zlib.output_compression". -output_handler = +;output_handler = ; Transparent output compression using the zlib library ; Valid values for this option are 'off', 'on', or a specific buffer size ; to be used for compression (default is 4KB) ; ; Note: output_handler must be empty if this is set 'On' !!!! +; Instead you must use zlib.output_handler. ; zlib.output_compression = Off + +; You cannot specify additional output handlers if zlib.output_compression +; is activated here. This setting does the same as output_handler but in +; a different order. +;zlib.output_handler = ; Implicit flush tells PHP to tell the output layer to flush itself ; automatically after every output block. This is equivalent to calling the Index: php4/ext/zlib/php_zlib.h diff -u php4/ext/zlib/php_zlib.h:1.31 php4/ext/zlib/php_zlib.h:1.32 --- php4/ext/zlib/php_zlib.h:1.31 Sun Jul 28 10:08:07 2002 +++ php4/ext/zlib/php_zlib.h Fri Aug 9 18:29:58 2002 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_zlib.h,v 1.31 2002/07/28 14:08:07 sr Exp $ */ +/* $Id: php_zlib.h,v 1.32 2002/08/09 22:29:58 helly Exp $ */ #ifndef PHP_ZLIB_H #define PHP_ZLIB_H @@ -33,6 +33,7 @@ int ob_gzip_coding; int output_compression; int output_compression_level; + char *output_handler; ZEND_END_MODULE_GLOBALS(zlib) extern zend_module_entry php_zlib_module_entry; Index: php4/ext/zlib/zlib.c diff -u php4/ext/zlib/zlib.c:1.137 php4/ext/zlib/zlib.c:1.138 --- php4/ext/zlib/zlib.c:1.137 Sun Jul 28 10:08:07 2002 +++ php4/ext/zlib/zlib.c Fri Aug 9 18:29:58 2002 @@ -18,7 +18,7 @@ | Jade Nicoletti <nicoletti@nns.ch> | +----------------------------------------------------------------------+ */ -/* $Id: zlib.c,v 1.137 2002/07/28 14:08:07 sr Exp $ */ +/* $Id: zlib.c,v 1.138 2002/08/09 22:29:58 helly Exp $ */ #define IS_EXT_MODULE #ifdef HAVE_CONFIG_H @@ -177,10 +177,25 @@ } /* }}} */ +/* {{{ OnUpdate_zlib_output_handler */ +static PHP_INI_MH(OnUpdate_zlib_output_handler) +{ + if (stage == PHP_INI_STAGE_RUNTIME && SG(headers_sent) && !SG(request_info).no_headers) { + php_error(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); + + return SUCCESS; +} +/* }}} */ + PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("zlib.output_compression", "0", PHP_INI_ALL, OnUpdate_zlib_output_compression, output_compression, zend_zlib_globals, zlib_globals) 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) + STD_PHP_INI_ENTRY("zlib.output_handler", "", PHP_INI_ALL, OnUpdate_zlib_output_handler, output_handler, zend_zlib_globals, zlib_globals) PHP_INI_END() #ifdef ZTS @@ -1000,6 +1015,9 @@ php_start_ob_buffer(NULL, buffer_size, 0 TSRMLS_CC); php_ob_set_internal_handler(php_gzip_output_handler, buffer_size*1.5, "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; } /* }}} */
Index: php4/ext/standard/head.c diff -u php4/ext/standard/head.c:1.60 php4/ext/standard/head.c:1.61 --- php4/ext/standard/head.c:1.60 Fri Aug 9 16:53:37 2002 +++ php4/ext/standard/head.c Fri Aug 9 18:29:57 2002 @@ -15,7 +15,7 @@ | Author: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | +----------------------------------------------------------------------+ */ -/* $Id: head.c,v 1.60 2002/08/09 20:53:37 helly Exp $ */ +/* $Id: head.c,v 1.61 2002/08/09 22:29:57 helly Exp $ */ #include <stdio.h> #include "php.h" @@ -126,9 +126,7 @@ ctr.line_len = strlen(cookie); result = sapi_header_op(SAPI_HEADER_ADD, &ctr TSRMLS_CC); - if (result == FAILURE) { - efree(cookie); - } + efree(cookie); return result; } Index: php4/main/main.c diff -u php4/main/main.c:1.475 php4/main/main.c:1.476 --- php4/main/main.c:1.475 Fri Aug 9 17:57:03 2002 +++ php4/main/main.c Fri Aug 9 18:29:57 2002 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: main.c,v 1.475 2002/08/09 21:57:03 helly Exp $ */ +/* $Id: main.c,v 1.476 2002/08/09 22:29:57 helly Exp $ */ /* {{{ includes */ @@ -813,13 +813,7 @@ } if (PG(output_handler) && PG(output_handler)[0]) { - zval *output_handler; - - ALLOC_INIT_ZVAL(output_handler); - Z_STRLEN_P(output_handler) = strlen(PG(output_handler)); /* this can be optimized */ - Z_STRVAL_P(output_handler) = estrndup(PG(output_handler), Z_STRLEN_P(output_handler)); - Z_TYPE_P(output_handler) = IS_STRING; - php_start_ob_buffer(output_handler, 0, 1 TSRMLS_CC); + php_start_ob_buffer_named(PG(output_handler), 0, 1 TSRMLS_CC); } else if (PG(output_buffering)) { if (PG(output_buffering)>1) { Index: php4/main/output.c diff -u php4/main/output.c:1.105 php4/main/output.c:1.106 --- php4/main/output.c:1.105 Mon Aug 5 14:54:53 2002 +++ php4/main/output.c Fri Aug 9 18:29:57 2002 @@ -14,10 +14,11 @@ +----------------------------------------------------------------------+ | Authors: Zeev Suraski <zeev@zend.com> | | Thies C. Arntzen <thies@thieso.net> | + | Marcus Boerger <helly@php.net> | +----------------------------------------------------------------------+ */ -/* $Id: output.c,v 1.105 2002/08/05 18:54:53 helly Exp $ */ +/* $Id: output.c,v 1.106 2002/08/09 22:29:57 helly Exp $ */ #include "php.h" #include "ext/standard/head.h" @@ -30,7 +31,7 @@ static int php_ub_body_write_no_header(const char *str, uint str_length TSRMLS_DC); static int php_b_body_write(const char *str, uint str_length TSRMLS_DC); -static void php_ob_init(uint initial_size, uint block_size, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC); +static int php_ob_init(uint initial_size, uint block_size, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC); static void php_ob_append(const char *text, uint text_length TSRMLS_DC); #if 0 static void php_ob_prepend(const char *text, uint text_length); @@ -114,16 +115,39 @@ * Start output buffering */ PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC) { + uint initial_size, block_size; + if (OG(ob_lock)) { + php_error(E_ERROR, "%s() Cannot use output buffering in output buffering display handlers", get_active_function_name(TSRMLS_C)); return FAILURE; } if (chunk_size) { - php_ob_init((chunk_size*3/2), chunk_size/2, output_handler, chunk_size, erase TSRMLS_CC); + initial_size = (chunk_size*3/2); + block_size = chunk_size/2; } else { - php_ob_init(40*1024, 10*1024, output_handler, chunk_size, erase TSRMLS_CC); + initial_size = 40*1024; + block_size = 10*1024; } - OG(php_body_write) = php_b_body_write; - return SUCCESS; + return php_ob_init(initial_size, block_size, output_handler, chunk_size, erase TSRMLS_CC); +} +/* }}} */ + + +/* {{{ php_start_ob_buffer_named + * Start output buffering */ +PHPAPI int php_start_ob_buffer_named(const char *output_handler_name, uint chunk_size, zend_bool erase TSRMLS_DC) +{ + zval *output_handler; + int result; + + ALLOC_INIT_ZVAL(output_handler); + Z_STRLEN_P(output_handler) = strlen(output_handler_name); /* this can be optimized */ + Z_STRVAL_P(output_handler) = estrndup(output_handler_name, Z_STRLEN_P(output_handler)); + Z_TYPE_P(output_handler) = IS_STRING; + result = php_start_ob_buffer(output_handler, chunk_size, erase TSRMLS_CC); + zval_dtor(output_handler); + FREE_ZVAL(output_handler); + return result; } /* }}} */ @@ -333,10 +357,43 @@ } /* }}} */ -/* {{{ php_ob_init +/* {{{ php_ob_init_conflict + * Returns 1 if handler_set is already used and generates error message + */ +static int php_ob_init_conflict(char *handler_new, char *handler_set TSRMLS_DC) +{ + if (php_ob_handler_used(handler_set TSRMLS_CC)) + { + php_error(E_WARNING, "%s() output handler '%s' conflicts with '%s'", get_active_function_name(TSRMLS_C), handler_new, handler_set); + return 1; + } + return 0; +} +/* }}} */ + +/* {{{ php_ob_init_named */ -static void php_ob_init(uint initial_size, uint block_size, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC) +static int php_ob_init_named(uint initial_size, uint block_size, char *handler_name, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC) { + int handler_gz, handler_mb, handler_ic; + + /* check for specific handlers where rules apply */ + handler_gz = strcmp(handler_name, "ob_gzhandler"); + handler_mb = strcmp(handler_name, "mb_output_handler"); + handler_ic = strcmp(handler_name, "ob_iconv_handler"); + /* apply rules */ + if (!handler_gz || !handler_mb || !handler_ic) { + if (php_ob_handler_used(handler_name TSRMLS_CC)) { + php_error(E_WARNING, "%s() output handler '%s' cannot be used twice", get_active_function_name(TSRMLS_C), handler_name); + return FAILURE; + } + if (!handler_gz && php_ob_init_conflict(handler_name, "zlib output compression" TSRMLS_CC)) + return FAILURE; + if (!handler_mb && php_ob_init_conflict(handler_name, "ob_iconv_handler" TSRMLS_CC)) + return FAILURE; + if (!handler_ic && php_ob_init_conflict(handler_name, "mb_output_handler" TSRMLS_CC)) + return FAILURE; + } if (OG(ob_nesting_level)>0) { if (OG(ob_nesting_level)==1) { /* initialize stack */ zend_stack_init(&OG(ob_buffers)); @@ -352,37 +409,95 @@ OG(active_ob_buffer).chunk_size = chunk_size; OG(active_ob_buffer).status = 0; OG(active_ob_buffer).internal_output_handler = NULL; + OG(active_ob_buffer).handler_name = estrdup(handler_name&&handler_name[0]?handler_name:"default output handler"); + OG(active_ob_buffer).erase = erase; + OG(php_body_write) = php_b_body_write; + return SUCCESS; +} +/* }}} */ + +/* {{{ php_ob_handler_from_string + * Create zval output handler from string + */ +static zval* php_ob_handler_from_string(const char *handler_name TSRMLS_DC) +{ + zval *output_handler; + + ALLOC_INIT_ZVAL(output_handler); + Z_STRLEN_P(output_handler) = strlen(handler_name); /* this can be optimized */ + Z_STRVAL_P(output_handler) = estrndup(handler_name, Z_STRLEN_P(output_handler)); + Z_TYPE_P(output_handler) = IS_STRING; + return output_handler; +} +/* }}} */ + +/* {{{ php_ob_init + */ +static int php_ob_init(uint initial_size, uint block_size, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC) +{ + int res, result, len; + char *handler_name, *next_handler_name; + HashPosition pos; + zval **tmp; + zval *handler_zval; + if (output_handler && output_handler->type == IS_STRING) { - OG(active_ob_buffer).handler_name = estrndup(Z_STRVAL_P(output_handler), Z_STRLEN_P(output_handler)); + result = 0; + handler_name = Z_STRVAL_P(output_handler); + while ((next_handler_name=strchr(handler_name, ',')) != NULL) { + len = next_handler_name-handler_name; + next_handler_name = estrndup(handler_name, len); + handler_zval = php_ob_handler_from_string(next_handler_name TSRMLS_CC); + res = php_ob_init_named(initial_size, block_size, next_handler_name, handler_zval, chunk_size, erase TSRMLS_CC); + result &= res; + if (!res==SUCCESS) { + zval_dtor(handler_zval); + FREE_ZVAL(handler_zval); + } + handler_name += len+1; + efree(next_handler_name); + } + handler_zval = php_ob_handler_from_string(handler_name TSRMLS_CC); + res = php_ob_init_named(initial_size, block_size, handler_name, handler_zval, chunk_size, erase TSRMLS_CC); + result &= res; + if (!res==SUCCESS) { + zval_dtor(handler_zval); + FREE_ZVAL(handler_zval); + } + result = result ? SUCCESS : FAILURE; } else if (output_handler && output_handler->type == IS_ARRAY) { - /* FIXME: Array type is not supported yet. - See call_user_function_ex() for detials. */ - OG(active_ob_buffer).handler_name = estrdup("array is not supported yet"); + result = 0; + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(output_handler), &pos); + while (zend_hash_get_current_data_ex(Z_ARRVAL_P(output_handler), (void **)&tmp, &pos) == SUCCESS) { + result &= php_ob_init(initial_size, block_size, *tmp, chunk_size, erase TSRMLS_CC); + zend_hash_move_forward_ex(Z_ARRVAL_P(output_handler), &pos); + } + result = result ? SUCCESS : FAILURE; } else { - OG(active_ob_buffer).handler_name = estrdup("default output handler"); + if (output_handler) { + SEPARATE_ZVAL(&output_handler); + output_handler->refcount++; + } + result = php_ob_init_named(initial_size, block_size, "default output handler", output_handler, chunk_size, erase TSRMLS_CC); } - OG(active_ob_buffer).erase = erase; + return result; } /* }}} */ /* {{{ php_ob_list_each */ - static int php_ob_list_each(php_ob_buffer *ob_buffer, zval *ob_handler_array) { - if (!strcmp(ob_buffer->handler_name, "zlib output compression") && ob_buffer->internal_output_handler) { - add_next_index_string(ob_handler_array, "ob_gzhandler", 1); - } else { - add_next_index_string(ob_handler_array, ob_buffer->handler_name, 1); - } + add_next_index_string(ob_handler_array, ob_buffer->handler_name, 1); return 0; } /* }}} */ /* {{{ proto array ob_list_handlers() - List all output_buffers in an array */ + * List all output_buffers in an array + */ PHP_FUNCTION(ob_list_handlers) { if (ZEND_NUM_ARGS()!=0) { @@ -404,12 +519,11 @@ /* }}} */ /* {{{ php_ob_used_each - Sets handler_name to NULL is found + * Sets handler_name to NULL is found */ static int php_ob_handler_used_each(php_ob_buffer *ob_buffer, char **handler_name) { - if ((!strcmp(ob_buffer->handler_name, "zlib output compression") && ob_buffer->internal_output_handler && !strcmp("ob_gzhandler", *handler_name)) - || !strcmp(ob_buffer->handler_name, *handler_name)) + if (!strcmp(ob_buffer->handler_name, *handler_name)) { *handler_name = NULL; return 1; @@ -419,7 +533,7 @@ /* }}} */ /* {{{ php_ob_used - returns 1 if given handler_name is used as output_handler + * returns 1 if given handler_name is used as output_handler */ PHPAPI int php_ob_handler_used(char *handler_name TSRMLS_DC) { @@ -574,7 +688,7 @@ * HEAD support */ -/* {{{ proto void ob_start([ string user_function [, int chunk_size [, bool erase]]]) +/* {{{ proto boolean ob_start([ string|array user_function [, int chunk_size [, bool erase]]]) Turn on Output Buffering (specifying an optional output handler). */ PHP_FUNCTION(ob_start) { @@ -585,20 +699,9 @@ if (zend_parse_parameters(argc TSRMLS_CC, "|zlb", &output_handler, &chunk_size, &erase) == FAILURE) - return; + RETURN_FALSE; - if (output_handler) { - SEPARATE_ZVAL(&output_handler); - output_handler->refcount++; - } if (php_start_ob_buffer(output_handler, chunk_size, erase TSRMLS_CC)==FAILURE) { - if (SG(headers_sent) && !SG(request_info).headers_only) { - OG(php_body_write) = php_ub_body_write_no_header; - } else { - OG(php_body_write) = php_ub_body_write; - } - OG(ob_nesting_level) = 0; - php_error(E_ERROR, "Cannot use output buffering in output buffering display handlers"); RETURN_FALSE; } RETURN_TRUE; @@ -754,41 +857,29 @@ } -/* {{{ proto array ob_get_status([bool full_status]) - Return the nesting level of the output buffer */ +/* {{{ proto false|array ob_get_status([bool full_status]) + Return the status of the active or all output buffers */ PHP_FUNCTION(ob_get_status) { int argc = ZEND_NUM_ARGS(); zend_bool full_status = 0; if (zend_parse_parameters(argc TSRMLS_CC, "|b", &full_status) == FAILURE ) - return; + RETURN_FALSE; if (array_init(return_value) == FAILURE) { RETURN_FALSE; } if (full_status) { - zval *elem; - - zend_stack_apply_with_argument(&OG(ob_buffers), ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *elem, void *))php_ob_buffer_status, return_value); - - MAKE_STD_ZVAL(elem); - if (array_init(elem)) - RETURN_FALSE; - - if (OG(active_ob_buffer).internal_output_handler) { - add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_INTERNAL); + if (OG(ob_nesting_level)>1) { + zend_stack_apply_with_argument(&OG(ob_buffers), ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *elem, void *))php_ob_buffer_status, return_value); } - else { - add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_USER); + if (OG(ob_nesting_level)>0 && php_ob_buffer_status(&OG(active_ob_buffer), return_value)==FAILURE) { + RETURN_FALSE; } - add_assoc_long(elem, "status", OG(active_ob_buffer).status); - add_assoc_string(elem, "name", OG(active_ob_buffer).handler_name, 1); - add_assoc_bool(elem, "del", OG(active_ob_buffer).erase); - add_next_index_zval(return_value, elem); } - else { + else if (OG(ob_nesting_level)>0) { add_assoc_long(return_value, "level", OG(ob_nesting_level)); if (OG(active_ob_buffer).internal_output_handler) { add_assoc_long(return_value, "type", PHP_OUTPUT_HANDLER_INTERNAL); Index: php4/main/php_output.h diff -u php4/main/php_output.h:1.39 php4/main/php_output.h:1.40 --- php4/main/php_output.h:1.39 Mon Aug 5 14:54:53 2002 +++ php4/main/php_output.h Fri Aug 9 18:29:57 2002 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_output.h,v 1.39 2002/08/05 18:54:53 helly Exp $ */ +/* $Id: php_output.h,v 1.40 2002/08/09 22:29:57 helly Exp $ */ #ifndef PHP_OUTPUT_H #define PHP_OUTPUT_H @@ -26,10 +26,11 @@ PHPAPI void php_output_startup(void); PHPAPI void php_output_activate(TSRMLS_D); PHPAPI void php_output_set_status(zend_bool status TSRMLS_DC); -void php_output_register_constants(TSRMLS_D); +PHPAPI void php_output_register_constants(TSRMLS_D); PHPAPI int php_body_write(const char *str, uint str_length TSRMLS_DC); PHPAPI int php_header_write(const char *str, uint str_length TSRMLS_DC); PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC); +PHPAPI int php_start_ob_buffer_named(const char *output_handler_name, uint chunk_size, zend_bool erase TSRMLS_DC); PHPAPI void php_end_ob_buffer(zend_bool send_buffer, zend_bool just_flush TSRMLS_DC); PHPAPI void php_end_ob_buffers(zend_bool send_buffer TSRMLS_DC); PHPAPI int php_ob_get_buffer(zval *p TSRMLS_DC); Index: php4/php.ini-dist diff -u php4/php.ini-dist:1.140 php4/php.ini-dist:1.141 --- php4/php.ini-dist:1.140 Fri Aug 9 02:18:46 2002 +++ php4/php.ini-dist Fri Aug 9 18:29:57 2002 @@ -98,15 +98,21 @@ : is doing. ; NOTE: You cannot use both "mb_output_handler" with "ob_inconv_handler" ; and you cannot use both "ob_gzhandler" and "zlib.output_compression". -output_handler = +;output_handler = ; Transparent output compression using the zlib library ; Valid values for this option are 'off', 'on', or a specific buffer size ; to be used for compression (default is 4KB) ; ; Note: output_handler must be empty if this is set 'On' !!!! +; Instead you must use zlib.output_handler. ; zlib.output_compression = Off + +; You cannot specify additional output handlers if zlib.output_compression +; is activated here. This setting does the same as output_handler but in +; a different order. +;zlib.output_handler = ; Implicit flush tells PHP to tell the output layer to flush itself ; automatically after every output block. This is equivalent to calling the Index: php4/php.ini-recommended diff -u php4/php.ini-recommended:1.93 php4/php.ini-recommended:1.94 --- php4/php.ini-recommended:1.93 Fri Aug 9 02:17:06 2002 +++ php4/php.ini-recommended Fri Aug 9 18:29:58 2002 @@ -111,15 +111,21 @@ : is doing. ; NOTE: You cannot use both "mb_output_handler" with "ob_inconv_handler" ; and you cannot use both "ob_gzhandler" and "zlib.output_compression". -output_handler = +;output_handler = ; Transparent output compression using the zlib library ; Valid values for this option are 'off', 'on', or a specific buffer size ; to be used for compression (default is 4KB) ; ; Note: output_handler must be empty if this is set 'On' !!!! +; Instead you must use zlib.output_handler. ; zlib.output_compression = Off + +; You cannot specify additional output handlers if zlib.output_compression +; is activated here. This setting does the same as output_handler but in +; a different order. +;zlib.output_handler = ; Implicit flush tells PHP to tell the output layer to flush itself ; automatically after every output block. This is equivalent to calling the Index: php4/ext/zlib/php_zlib.h diff -u php4/ext/zlib/php_zlib.h:1.31 php4/ext/zlib/php_zlib.h:1.32 --- php4/ext/zlib/php_zlib.h:1.31 Sun Jul 28 10:08:07 2002 +++ php4/ext/zlib/php_zlib.h Fri Aug 9 18:29:58 2002 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_zlib.h,v 1.31 2002/07/28 14:08:07 sr Exp $ */ +/* $Id: php_zlib.h,v 1.32 2002/08/09 22:29:58 helly Exp $ */ #ifndef PHP_ZLIB_H #define PHP_ZLIB_H @@ -33,6 +33,7 @@ int ob_gzip_coding; int output_compression; int output_compression_level; + char *output_handler; ZEND_END_MODULE_GLOBALS(zlib) extern zend_module_entry php_zlib_module_entry; Index: php4/ext/zlib/zlib.c diff -u php4/ext/zlib/zlib.c:1.137 php4/ext/zlib/zlib.c:1.138 --- php4/ext/zlib/zlib.c:1.137 Sun Jul 28 10:08:07 2002 +++ php4/ext/zlib/zlib.c Fri Aug 9 18:29:58 2002 @@ -18,7 +18,7 @@ | Jade Nicoletti <nicoletti@nns.ch> | +----------------------------------------------------------------------+ */ -/* $Id: zlib.c,v 1.137 2002/07/28 14:08:07 sr Exp $ */ +/* $Id: zlib.c,v 1.138 2002/08/09 22:29:58 helly Exp $ */ #define IS_EXT_MODULE #ifdef HAVE_CONFIG_H @@ -177,10 +177,25 @@ } /* }}} */ +/* {{{ OnUpdate_zlib_output_handler */ +static PHP_INI_MH(OnUpdate_zlib_output_handler) +{ + if (stage == PHP_INI_STAGE_RUNTIME && SG(headers_sent) && !SG(request_info).no_headers) { + php_error(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); + + return SUCCESS; +} +/* }}} */ + PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("zlib.output_compression", "0", PHP_INI_ALL, OnUpdate_zlib_output_compression, output_compression, zend_zlib_globals, zlib_globals) 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) + STD_PHP_INI_ENTRY("zlib.output_handler", "", PHP_INI_ALL, OnUpdate_zlib_output_handler, output_handler, zend_zlib_globals, zlib_globals) PHP_INI_END() #ifdef ZTS @@ -1000,6 +1015,9 @@ php_start_ob_buffer(NULL, buffer_size, 0 TSRMLS_CC); php_ob_set_internal_handler(php_gzip_output_handler, buffer_size*1.5, "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; } /* }}} */