RE: [PHP-CVS] output handlers

From: Date: Tue, 06 Aug 2002 03:30:23 +0000
Subject: RE: [PHP-CVS] output handlers
References: 1  Groups: php.cvs 
Request: Send a blank email to php-cvs+get-13164@lists.php.net to get a copy of this message
er, why did you post this to php-cvs and not php-dev? -- james > -----Original Message----- > From: Marcus Boerger [mailto:marcus.boerger@t-online.de] > Sent: Tuesday, August 06, 2002 4:19 AM > To: php-cvs@lists.php.net > Subject: [PHP-CVS] output handlers > > > The problem: Using both internal zlib output compression (in preference > to ob_gzhandler) and mb_output_handler. > > The solution and some side effects: > > 1) Use ini settings (incl. new zlib.output_handler) as followed: > 'output_handler = > 'zlib.output_compression = On > 'zlib.output_handler = mb_output_handler > The new ini setting does the same as output_handler but only if > zlib.output_compression is active and after it is being activated. > > 2) ob_gzhandler, mb_output_handler, ob_iconv_handler cannot be called > twice. > > 3) ob_gzhandler cannot be combined with internal zlib compression > and mb_iconv_handler cannot be combined with mb_output_handler. > > 4) You can supply more than one handler with ob_start() by either > use a comma separated list (NO TRIM YET) or an array. > > 5) You can supply more than one handler from ini settings output_handler > and zlib.output_handler by a comma separated list (NO TRIM YET). > > What is left: > > 1) Someone to test url rewriting / session handling (Haven't had > time yet). > > 2) Check userland handlers. > > > I would very much appreciate anyone taking the time to test the patch. > > regards > marcus > > > The patch: > > cvs -z3 -q diff main\main.c main\output.c ext\zlib\php_zlib.h > ext\zlib\zlib.c (in directory S:\php4\) > Index: main/main.c > =================================================================== > RCS file: /repository/php4/main/main.c,v > retrieving revision 1.470 > diff -u -r1.470 main.c > --- main/main.c 2 Aug 2002 06:53:48 -0000 1.470 > +++ main/main.c 6 Aug 2002 03:16:35 -0000 > @@ -713,6 +713,8 @@ > 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); > + zval_dtor(output_handler); > + FREE_ZVAL(output_handler); > } > else if (PG(output_buffering)) { > if (PG(output_buffering)>1) { > @@ -1108,7 +1110,7 @@ > char *p; > unsigned char _gpc_flags[3] = {0, 0, 0}; > zend_bool have_variables_order; > - zval *dummy_track_vars_array; > + zval *dummy_track_vars_array = NULL; > zend_bool initialized_dummy_track_vars_array=0; > int i; > char *variables_order; > Index: main/output.c > =================================================================== > RCS file: /repository/php4/main/output.c,v > retrieving revision 1.105 > diff -u -r1.105 output.c > --- main/output.c 5 Aug 2002 18:54:53 -0000 1.105 > +++ main/output.c 6 Aug 2002 03:16:35 -0000 > @@ -17,7 +17,7 @@ > > +----------------------------------------------------------------------+ > */ > > -/* $Id: output.c,v 1.105 2002/08/05 18:54:53 helly Exp $ */ > +/* $Id: output.c,v 1.103 2002/05/12 22:17:58 zeev Exp $ */ > > #include "php.h" > #include "ext/standard/head.h" > @@ -30,7 +30,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 +114,20 @@ > * 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); > } > /* }}} */ > > @@ -302,8 +306,10 @@ > PHPAPI void php_ob_set_internal_handler(php_output_handler_func_t > internal_output_handler, uint buffer_size, char *handler_name, zend_bool > erase TSRMLS_DC) > { > if (OG(ob_nesting_level)==0) { > + /*php_error(E_NOTICE, "%s() set internal handler > '%s', fail", > get_active_function_name(TSRMLS_C), handler_name);*/ > return; > } > + /*php_error(E_NOTICE, "%s() set internal handler '%s'", > get_active_function_name(TSRMLS_C), handler_name);*/ > > OG(active_ob_buffer).internal_output_handler = > internal_output_handler; > OG(active_ob_buffer).internal_output_handler_buffer = (char *) > emalloc(buffer_size); > @@ -333,10 +339,44 @@ > } > /* }}} */ > > -/* {{{ 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"); > + /*php_error(E_NOTICE, "%s() check '%s'", > get_active_function_name(TSRMLS_C), handler_name);*/ > + /* 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 +392,90 @@ > 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; > + /*php_error(E_NOTICE, "%s() added output handler '%s'", > get_active_function_name(TSRMLS_C), OG(active_ob_buffer).handler_name);*/ > + return SUCCESS; > +} > +/* }}} */ > + > +/* {{{ php_ob_handler_from_string > + * Create zval output handler from string > + */ > +zval* php_ob_handler_from_string(char *handler_name TSRMLS_DC) > +{ > + zval *output_handler; > + > + ALLOC_INIT_ZVAL(output_handler); > + Z_STRLEN_P(output_handler) = strlen(handler_name); > + 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 result, len; > + char *handler_name, *next_handler_name; > + HashPosition pos; > + zval **tmp; > + > 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); > + /*php_error(E_NOTICE, "%s() init output handler > string '%s'", > get_active_function_name(TSRMLS_C), handler_name);*/ > + while ((next_handler_name=strchr(handler_name, > ',')) != NULL) { > + len = next_handler_name-handler_name; > + next_handler_name = estrndup(handler_name, len); > + result &= php_ob_init_named(initial_size, > block_size, next_handler_name, > + > php_ob_handler_from_string(next_handler_name TSRMLS_CC), chunk_size, > erase TSRMLS_CC); > + handler_name += len+1; > + efree(next_handler_name); > + } > + result &= php_ob_init_named(initial_size, > block_size, handler_name, > + php_ob_handler_from_string(handler_name > TSRMLS_CC), chunk_size, erase > TSRMLS_CC); > + 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; > + /*php_error(E_NOTICE, "%s() init output handler array", > get_active_function_name(TSRMLS_C));*/ > + /* convert everything to strings, and calculate length */ > + > 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"); > + /*php_error(E_NOTICE, "%s() init output handler other", > get_active_function_name(TSRMLS_C));*/ > + 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; > + /*php_error(E_NOTICE, "%s() init done", > get_active_function_name(TSRMLS_C));*/ > + 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 +497,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 +511,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) > { > @@ -587,18 +679,7 @@ > > &chunk_size, &erase) == FAILURE) > return; > > - 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; > @@ -769,26 +850,14 @@ > } > > 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: ext/zlib/php_zlib.h > =================================================================== > RCS file: /repository/php4/ext/zlib/php_zlib.h,v > retrieving revision 1.31 > diff -u -r1.31 php_zlib.h > --- ext/zlib/php_zlib.h 28 Jul 2002 14:08:07 -0000 1.31 > +++ ext/zlib/php_zlib.h 6 Aug 2002 03:16:35 -0000 > @@ -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: ext/zlib/zlib.c > =================================================================== > RCS file: /repository/php4/ext/zlib/zlib.c,v > retrieving revision 1.137 > diff -u -r1.137 zlib.c > --- ext/zlib/zlib.c 28 Jul 2002 14:08:07 -0000 1.137 > +++ ext/zlib/zlib.c 6 Aug 2002 03:16:35 -0000 > @@ -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 > @@ -982,7 +997,7 @@ > */ > int php_enable_output_compression(int buffer_size TSRMLS_DC) > { > - zval **a_encoding, **data; > + zval **a_encoding, **data, *output_handler; > > if (zend_hash_find(&EG(symbol_table), "HTTP_SERVER_VARS", > sizeof("HTTP_SERVER_VARS"), (void **) &data)==FAILURE > || Z_TYPE_PP(data)!=IS_ARRAY > @@ -1000,6 +1015,12 @@ > > 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))) { > + ALLOC_INIT_ZVAL(output_handler); > + ZVAL_STRING(output_handler, ZLIBG(output_handler), 0); > + php_start_ob_buffer(output_handler, buffer_size, 0 > TSRMLS_CC); > + FREE_ZVAL(output_handler); > + } > return SUCCESS; > } > /* }}} */ > > > *****CVS exited normally with code 1***** > > > -- > PHP CVS Mailing List (http://www.php.net/) > To unsubscribe, visit: http://www.php.net/unsub.php > >

« previous php.cvs (#13164) next »