cvs: php-src / README.NEW-OUTPUT-API /ext/pgsql pgsql.c /ext/session session.c /ext/soap soap.c /ext/standard basic_functions.c head.c info.c
url_scanner_ex.c url_scanner_ex.re var.c /ext/tidy tidy.c /ext/zlib php_zlib.h zlib.c /main SAPI.c main.c output.c php.h php_output.h /sapi/apache
mod_php5.c php_apache.c /sapi/apache2handler php_functions.c /sapi/apache_hooks mod_php5.c php_apache.c /sapi/cgi cgi_main.c /sapi/cli php_cli.c
/sapi/milter php_milter.c /sapi/nsapi nsapi.c /tests/output .cvsignore ob_001.phpt ob_002.phpt ob_003.phpt ob_004.phpt ob_005.phpt ob_006.phpt
ob_007.phpt ob_008.phpt ob_009.phpt ob_010.phpt ob_011.phpt ob_012.phpt ob_013.phpt ob_014.phpt ob_015.phpt
| From: | Michael Wallner | Date: | Fri, 02 Jun 2006 19:51:43 +0000 |
| Subject: | cvs: php-src / README.NEW-OUTPUT-API /ext/pgsql pgsql.c /ext/session session.c /ext/soap soap.c /ext/standard basic_functions.c head.c info.c url_scanner_ex.c url_scanner_ex.re var.c /ext/tidy tidy.c /ext/zlib php_zlib.h zlib.c /main SAPI.c main.c output.c php.h php_output.h /sapi/apache mod_php5.c php_apache.c /sapi/apache2handler php_functions.c /sapi/apache_hooks mod_php5.c php_apache.c /sapi/cgi cgi_main.c /sapi/cli php_cli.c /sapi/milter php_milter.c /sapi/nsapi nsapi.c /tests/output .cvsignore ob_001.phpt ob_002.phpt ob_003.phpt ob_004.phpt ob_005.phpt ob_006.phpt ob_007.phpt ob_008.phpt ob_009.phpt ob_010.phpt ob_011.phpt ob_012.phpt ob_013.phpt ob_014.phpt ob_015.phpt |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-38570@lists.php.net to get a copy of this message | ||
mike Fri Jun 2 19:51:43 2006 UTC
Added files:
/php-src README.NEW-OUTPUT-API
/php-src/tests/output .cvsignore ob_001.phpt ob_002.phpt
ob_003.phpt ob_004.phpt ob_005.phpt
ob_006.phpt ob_007.phpt ob_008.phpt
ob_009.phpt ob_010.phpt ob_011.phpt
ob_012.phpt ob_013.phpt ob_014.phpt
ob_015.phpt
Modified files:
/php-src/ext/pgsql pgsql.c
/php-src/ext/session session.c
/php-src/ext/soap soap.c
/php-src/ext/standard basic_functions.c head.c info.c
url_scanner_ex.c url_scanner_ex.re var.c
/php-src/ext/tidy tidy.c
/php-src/ext/zlib php_zlib.h zlib.c
/php-src/main SAPI.c main.c output.c php.h php_output.h
/php-src/sapi/apache mod_php5.c php_apache.c
/php-src/sapi/apache2handler php_functions.c
/php-src/sapi/apache_hooks mod_php5.c php_apache.c
/php-src/sapi/cgi cgi_main.c
/php-src/sapi/cli php_cli.c
/php-src/sapi/milter php_milter.c
/php-src/sapi/nsapi nsapi.c
Log:
- new output control code
# scan README.NEW-OUTPUT-API to get a grasp
# tree has been tagged with BEFORE_NEW_OUTPUT_API
#
# TODO:
# - improve existing output handlers
# - move zlib.output_compression cruft from SAPI.c to zlib.c
# - output_encoding handling was ambigious, resp. is undefined yet
# - more tests
http://cvs.php.net/viewcvs.cgi/php-src/ext/pgsql/pgsql.c?r1=1.350&r2=1.351&diff_format=u Index: php-src/ext/pgsql/pgsql.c diff -u php-src/ext/pgsql/pgsql.c:1.350 php-src/ext/pgsql/pgsql.c:1.351 --- php-src/ext/pgsql/pgsql.c:1.350 Mon Apr 10 19:50:56 2006 +++ php-src/ext/pgsql/pgsql.c Fri Jun 2 19:51:42 2006 @@ -20,7 +20,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: pgsql.c,v 1.350 2006/04/10 19:50:56 helly Exp $ */ +/* $Id: pgsql.c,v 1.351 2006/06/02 19:51:42 mike Exp $ */ #include <stdlib.h> @@ -2858,7 +2858,7 @@ tbytes = 0; while ((nbytes = lo_read((PGconn *)pgsql->conn, pgsql->lofd, buf, PGSQL_LO_READ_BUF_SIZE))>0) { - php_body_write(buf, nbytes TSRMLS_CC); + PHPWRITE(buf, nbytes); tbytes += nbytes; } RETURN_LONG(tbytes); http://cvs.php.net/viewcvs.cgi/php-src/ext/session/session.c?r1=1.434&r2=1.435&diff_format=u Index: php-src/ext/session/session.c diff -u php-src/ext/session/session.c:1.434 php-src/ext/session/session.c:1.435 --- php-src/ext/session/session.c:1.434 Thu May 18 22:07:31 2006 +++ php-src/ext/session/session.c Fri Jun 2 19:51:42 2006 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: session.c,v 1.434 2006/05/18 22:07:31 helly Exp $ */ +/* $Id: session.c,v 1.435 2006/06/02 19:51:42 mike Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -855,8 +855,8 @@ if (PS(cache_limiter)[0] == '\0') return 0; if (SG(headers_sent)) { - char *output_start_filename = php_get_output_start_filename(TSRMLS_C); - int output_start_lineno = php_get_output_start_lineno(TSRMLS_C); + char *output_start_filename = php_output_get_start_filename(); + int output_start_lineno = php_output_get_start_lineno(); if (output_start_filename) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot send session cache limiter - headers already sent (output started at %s:%d)", @@ -889,8 +889,8 @@ char *date_fmt = NULL; if (SG(headers_sent)) { - char *output_start_filename = php_get_output_start_filename(TSRMLS_C); - int output_start_lineno = php_get_output_start_lineno(TSRMLS_C); + char *output_start_filename = php_output_get_start_filename(); + int output_start_lineno = php_output_get_start_lineno(); if (output_start_filename) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot send session cookie - headers already sent by (output started at %s:%d)", http://cvs.php.net/viewcvs.cgi/php-src/ext/soap/soap.c?r1=1.189&r2=1.190&diff_format=u Index: php-src/ext/soap/soap.c diff -u php-src/ext/soap/soap.c:1.189 php-src/ext/soap/soap.c:1.190 --- php-src/ext/soap/soap.c:1.189 Fri May 26 09:04:53 2006 +++ php-src/ext/soap/soap.c Fri Jun 2 19:51:42 2006 @@ -17,7 +17,7 @@ | Dmitry Stogov <dmitry@zend.com> | +----------------------------------------------------------------------+ */ -/* $Id: soap.c,v 1.189 2006/05/26 09:04:53 dmitry Exp $ */ +/* $Id: soap.c,v 1.190 2006/06/02 19:51:42 mike Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -1482,7 +1482,7 @@ } } - if (php_start_ob_buffer(NULL, 0, 0 TSRMLS_CC) != SUCCESS) { + if (php_output_start_default() != SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_ERROR,"ob_start failed"); } @@ -1609,7 +1609,7 @@ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error calling constructor"); } if (EG(exception)) { - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_discard(); if (Z_TYPE_P(EG(exception)) == IS_OBJECT && instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) { soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC); @@ -1642,7 +1642,7 @@ } #ifdef ZEND_ENGINE_2 if (EG(exception)) { - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_discard(); if (Z_TYPE_P(EG(exception)) == IS_OBJECT && instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) { soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC); @@ -1721,14 +1721,14 @@ Z_TYPE_PP(tmp) != IS_NULL) { headerfault = *tmp; } - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_discard(); soap_server_fault_ex(function, &h->retval, h TSRMLS_CC); efree(fn_name); if (soap_obj) {zval_ptr_dtor(&soap_obj);} goto fail; #ifdef ZEND_ENGINE_2 } else if (EG(exception)) { - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_discard(); if (Z_TYPE_P(EG(exception)) == IS_OBJECT && instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) { zval *headerfault = NULL, **tmp; @@ -1774,7 +1774,7 @@ #ifdef ZEND_ENGINE_2 if (EG(exception)) { - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_discard(); if (Z_TYPE_P(EG(exception)) == IS_OBJECT && instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) { soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC); @@ -1794,7 +1794,7 @@ if (Z_TYPE(retval) == IS_OBJECT && instanceof_function(Z_OBJCE(retval), soap_fault_class_entry TSRMLS_CC)) { - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_discard(); soap_server_fault_ex(function, &retval, NULL TSRMLS_CC); goto fail; } @@ -1815,7 +1815,7 @@ } /* Flush buffer */ - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_discard(); if (doc_return) { /* xmlDocDumpMemoryEnc(doc_return, &buf, &size, XML_CHAR_ENCODING_UTF8); */ @@ -2083,11 +2083,11 @@ code = "Server"; } /* Get output buffer and send as fault detials */ - if (php_ob_get_length(&outbuflen TSRMLS_CC) != FAILURE && Z_LVAL(outbuflen) != 0) { + if (php_output_get_length(&outbuflen) != FAILURE && Z_LVAL(outbuflen) != 0) { ALLOC_INIT_ZVAL(outbuf); - php_ob_get_buffer(outbuf TSRMLS_CC); + php_output_get_contents(outbuf TSRMLS_CC); } - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_discard(); INIT_ZVAL(fault_obj); set_soap_fault(&fault_obj, NULL, code, buffer, NULL, outbuf, NULL TSRMLS_CC); http://cvs.php.net/viewcvs.cgi/php-src/ext/standard/basic_functions.c?r1=1.775&r2=1.776&diff_format=u Index: php-src/ext/standard/basic_functions.c diff -u php-src/ext/standard/basic_functions.c:1.775 php-src/ext/standard/basic_functions.c:1.776 --- php-src/ext/standard/basic_functions.c:1.775 Tue May 30 14:51:54 2006 +++ php-src/ext/standard/basic_functions.c Fri Jun 2 19:51:42 2006 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: basic_functions.c,v 1.775 2006/05/30 14:51:54 iliaa Exp $ */ +/* $Id: basic_functions.c,v 1.776 2006/06/02 19:51:42 mike Exp $ */ #include "php.h" #include "php_streams.h" @@ -2406,7 +2406,7 @@ } if (i) { - php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC); + php_output_start_default(); } php_get_highlight_struct(&syntax_highlighter_ini); @@ -2416,8 +2416,8 @@ } if (i) { - php_ob_get_buffer (return_value TSRMLS_CC); - php_end_ob_buffer (0, 0 TSRMLS_CC); + php_output_get_contents(return_value); + php_output_discard(); } else { RETURN_TRUE; } @@ -2437,7 +2437,7 @@ RETURN_FALSE; } - php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC); + php_output_start_default(); file_handle.type = ZEND_HANDLE_FILENAME; file_handle.filename = filename; @@ -2453,8 +2453,8 @@ zend_destroy_file_handle(&file_handle TSRMLS_CC); zend_restore_lexical_state(&original_lex_state TSRMLS_CC); - php_ob_get_buffer(return_value TSRMLS_CC); - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_get_contents(return_value); + php_output_discard(); return; } @@ -2476,7 +2476,7 @@ convert_to_string(expr); if (i) { - php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC); + php_output_start_default(); } EG(error_reporting) = E_ERROR; @@ -2494,8 +2494,8 @@ EG(error_reporting) = old_error_reporting; if (i) { - php_ob_get_buffer (return_value TSRMLS_CC); - php_end_ob_buffer (0, 0 TSRMLS_CC); + php_output_get_contents(return_value); + php_output_discard(); } else { RETURN_TRUE; } @@ -2739,14 +2739,14 @@ } if (i) { - php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC); + php_output_start_default(); } zend_print_zval_r(var, 0 TSRMLS_CC); if (i) { - php_ob_get_buffer (return_value TSRMLS_CC); - php_end_ob_buffer (0, 0 TSRMLS_CC); + php_output_get_contents(return_value); + php_output_discard(); } else { RETURN_TRUE; } http://cvs.php.net/viewcvs.cgi/php-src/ext/standard/head.c?r1=1.86&r2=1.87&diff_format=u Index: php-src/ext/standard/head.c diff -u php-src/ext/standard/head.c:1.86 php-src/ext/standard/head.c:1.87 --- php-src/ext/standard/head.c:1.86 Sun Feb 19 18:19:33 2006 +++ php-src/ext/standard/head.c Fri Jun 2 19:51:42 2006 @@ -15,7 +15,7 @@ | Author: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | +----------------------------------------------------------------------+ */ -/* $Id: head.c,v 1.86 2006/02/19 18:19:33 iliaa Exp $ */ +/* $Id: head.c,v 1.87 2006/06/02 19:51:42 mike Exp $ */ #include <stdio.h> #include "php.h" @@ -200,8 +200,8 @@ return; if (SG(headers_sent)) { - line = php_get_output_start_lineno(TSRMLS_C); - file = php_get_output_start_filename(TSRMLS_C); + line = php_output_get_start_lineno(); + file = php_output_get_start_filename(); } switch(ZEND_NUM_ARGS()) { http://cvs.php.net/viewcvs.cgi/php-src/ext/standard/info.c?r1=1.263&r2=1.264&diff_format=u Index: php-src/ext/standard/info.c diff -u php-src/ext/standard/info.c:1.263 php-src/ext/standard/info.c:1.264 --- php-src/ext/standard/info.c:1.263 Fri Mar 31 11:11:26 2006 +++ php-src/ext/standard/info.c Fri Jun 2 19:51:42 2006 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: info.c,v 1.263 2006/03/31 11:11:26 tony2001 Exp $ */ +/* $Id: info.c,v 1.264 2006/06/02 19:51:42 mike Exp $ */ #include "php.h" #include "php_ini.h" @@ -70,7 +70,7 @@ elem_esc = php_escape_html_entities((char *)str, str_length, &new_len, 0, ENT_QUOTES, NULL TSRMLS_CC); - written = php_body_write(elem_esc, new_len TSRMLS_CC); + written = PHPWRITE(elem_esc, new_len); efree(elem_esc); @@ -351,7 +351,7 @@ } #if HAVE_MBSTRING - if (php_ob_handler_used("mb_output_handler" TSRMLS_CC)) { + if (php_output_handler_started("mb_output_handler")) { if (MBSTRG(current_http_output_encoding) == mbfl_no_encoding_pass) { charset = "US-ASCII"; } else { @@ -361,7 +361,7 @@ #endif #if HAVE_ICONV - if (php_ob_handler_used("ob_iconv_handler" TSRMLS_CC)) { + if (php_output_handler_started("ob_iconv_handler")) { charset = ICONVG(output_encoding); } #endif @@ -999,9 +999,9 @@ } /* Andale! Andale! Yee-Hah! */ - php_start_ob_buffer(NULL, 4096, 0 TSRMLS_CC); + php_output_start_default(); php_print_info(flag TSRMLS_CC); - php_end_ob_buffer(1, 0 TSRMLS_CC); + php_output_end(); RETURN_TRUE; } http://cvs.php.net/viewcvs.cgi/php-src/ext/standard/url_scanner_ex.c?r1=1.101&r2=1.102&diff_format=u Index: php-src/ext/standard/url_scanner_ex.c diff -u php-src/ext/standard/url_scanner_ex.c:1.101 php-src/ext/standard/url_scanner_ex.c:1.102 --- php-src/ext/standard/url_scanner_ex.c:1.101 Tue Feb 28 14:46:29 2006 +++ php-src/ext/standard/url_scanner_ex.c Fri Jun 2 19:51:42 2006 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: url_scanner_ex.c,v 1.101 2006/02/28 14:46:29 iliaa Exp $ */ +/* $Id: url_scanner_ex.c,v 1.102 2006/06/02 19:51:42 mike Exp $ */ #include "php.h" @@ -109,51 +109,78 @@ q = (p = url->c) + url->len; scan: - -#line 114 "ext/standard/url_scanner_ex.c" { - YYCTYPE yych; - goto yy0; - ++YYCURSOR; -yy0: - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - switch(yych){ - case '#': goto yy6; - case ':': goto yy2; - case '?': goto yy4; - default: goto yy8; - } -yy2: ++YYCURSOR; - goto yy3; -yy3: + static unsigned char yybm[] = { + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 0, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 0, 128, 128, 128, 128, 0, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + }; + +#line 149 "ext/standard/url_scanner_ex.c" + { + YYCTYPE yych; + + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if(yybm[0+yych] & 128) { + goto yy8; + } + if(yych <= '9') goto yy6; + if(yych >= ';') goto yy4; + ++YYCURSOR; #line 115 "ext/standard/url_scanner_ex.re" -{ smart_str_append(dest, url); return; } -#line 133 "ext/standard/url_scanner_ex.c" -yy4: ++YYCURSOR; - goto yy5; -yy5: + { smart_str_append(dest, url); return; } +#line 163 "ext/standard/url_scanner_ex.c" +yy4: + ++YYCURSOR; #line 116 "ext/standard/url_scanner_ex.re" -{ sep = separator; goto scan; } -#line 139 "ext/standard/url_scanner_ex.c" -yy6: ++YYCURSOR; - goto yy7; -yy7: + { sep = separator; goto scan; } +#line 168 "ext/standard/url_scanner_ex.c" +yy6: + ++YYCURSOR; #line 117 "ext/standard/url_scanner_ex.re" -{ bash = p - 1; goto done; } -#line 145 "ext/standard/url_scanner_ex.c" -yy8: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy9; -yy9: switch(yych){ - case '#': case ':': case '?': goto yy10; - default: goto yy8; - } -yy10: + { bash = p - 1; goto done; } +#line 173 "ext/standard/url_scanner_ex.c" +yy8: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if(yybm[0+yych] & 128) { + goto yy8; + } #line 118 "ext/standard/url_scanner_ex.re" -{ goto scan; } -#line 157 "ext/standard/url_scanner_ex.c" + { goto scan; } +#line 183 "ext/standard/url_scanner_ex.c" + } } #line 119 "ext/standard/url_scanner_ex.re" @@ -323,176 +350,138 @@ state_plain: start = YYCURSOR; - -#line 328 "ext/standard/url_scanner_ex.c" { - YYCTYPE yych; - goto yy11; - ++YYCURSOR; -yy11: - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - switch(yych){ - case '<': goto yy13; - default: goto yy15; - } -yy13: ++YYCURSOR; - goto yy14; -yy14: + static unsigned char yybm[] = { + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 0, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + }; + +#line 390 "ext/standard/url_scanner_ex.c" + { + YYCTYPE yych; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if(yybm[0+yych] & 128) { + goto yy15; + } + ++YYCURSOR; #line 287 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); STATE = STATE_TAG; goto state_tag; } -#line 345 "ext/standard/url_scanner_ex.c" -yy15: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy16; -yy16: switch(yych){ - case '<': goto yy17; - default: goto yy15; - } -yy17: + { passthru(STD_ARGS); STATE = STATE_TAG; goto state_tag; } +#line 401 "ext/standard/url_scanner_ex.c" +yy15: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if(yybm[0+yych] & 128) { + goto yy15; + } #line 288 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); goto state_plain; } -#line 357 "ext/standard/url_scanner_ex.c" + { passthru(STD_ARGS); goto state_plain; } +#line 411 "ext/standard/url_scanner_ex.c" + } } #line 289 "ext/standard/url_scanner_ex.re" state_tag: start = YYCURSOR; - -#line 365 "ext/standard/url_scanner_ex.c" { - YYCTYPE yych; - goto yy18; - ++YYCURSOR; -yy18: - if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); - yych = *YYCURSOR; - switch(yych){ - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - case 'G': - case 'H': - case 'I': - case 'J': - case 'K': - case 'L': - case 'M': - case 'N': - case 'O': - case 'P': - case 'Q': - case 'R': - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'g': - case 'h': - case 'i': - case 'j': - case 'k': - case 'l': - case 'm': - case 'n': - case 'o': - case 'p': - case 'q': - case 'r': - case 's': - case 't': - case 'u': - case 'v': - case 'w': - case 'x': - case 'y': - case 'z': goto yy20; - default: goto yy22; - } -yy20: ++YYCURSOR; - yych = *YYCURSOR; - goto yy25; + static unsigned char yybm[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 0, 0, 0, 0, 0, + 0, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + +#line 455 "ext/standard/url_scanner_ex.c" + { + YYCTYPE yych; + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if(yych <= '@') goto yy22; + if(yych <= 'Z') goto yy20; + if(yych <= '`') goto yy22; + if(yych >= '{') goto yy22; +yy20: + ++YYCURSOR; + yych = *YYCURSOR; + goto yy25; yy21: #line 294 "ext/standard/url_scanner_ex.re" -{ handle_tag(STD_ARGS); /* Sets STATE */; passthru(STD_ARGS); if (STATE == STATE_PLAIN) goto state_plain; else goto state_next_arg; } -#line 433 "ext/standard/url_scanner_ex.c" -yy22: ++YYCURSOR; - goto yy23; -yy23: + { handle_tag(STD_ARGS); /* Sets STATE */; passthru(STD_ARGS); if (STATE == STATE_PLAIN) goto state_plain; else goto state_next_arg; } +#line 471 "ext/standard/url_scanner_ex.c" +yy22: + ++YYCURSOR; #line 295 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); goto state_plain_begin; } -#line 439 "ext/standard/url_scanner_ex.c" -yy24: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy25; -yy25: switch(yych){ - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - case 'G': - case 'H': - case 'I': - case 'J': - case 'K': - case 'L': - case 'M': - case 'N': - case 'O': - case 'P': - case 'Q': - case 'R': - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'g': - case 'h': - case 'i': - case 'j': - case 'k': - case 'l': - case 'm': - case 'n': - case 'o': - case 'p': - case 'q': - case 'r': - case 's': - case 't': - case 'u': - case 'v': - case 'w': - case 'x': - case 'y': - case 'z': goto yy24; - default: goto yy21; + { passthru(STD_ARGS); goto state_plain_begin; } +#line 476 "ext/standard/url_scanner_ex.c" +yy24: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yy25: + if(yybm[0+yych] & 128) { + goto yy24; + } + goto yy21; } } #line 296 "ext/standard/url_scanner_ex.re" @@ -503,107 +492,98 @@ state_next_arg: start = YYCURSOR; - -#line 508 "ext/standard/url_scanner_ex.c" { - YYCTYPE yych; - goto yy26; - ++YYCURSOR; -yy26: - if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); - yych = *YYCURSOR; - switch(yych){ - case 0x09: - case 0x0A: - case 0x0B: case 0x0D: case ' ': goto yy30; - case '>': goto yy28; - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - case 'G': - case 'H': - case 'I': - case 'J': - case 'K': - case 'L': - case 'M': - case 'N': - case 'O': - case 'P': - case 'Q': - case 'R': - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'g': - case 'h': - case 'i': - case 'j': - case 'k': - case 'l': - case 'm': - case 'n': - case 'o': - case 'p': - case 'q': - case 'r': - case 's': - case 't': - case 'u': - case 'v': - case 'w': - case 'x': - case 'y': - case 'z': goto yy32; - default: goto yy34; - } -yy28: ++YYCURSOR; - goto yy29; -yy29: + static unsigned char yybm[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 128, 128, 128, 0, 128, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 128, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + +#line 532 "ext/standard/url_scanner_ex.c" + { + YYCTYPE yych; + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if(yych <= ' ') { + if(yych <= 0x0C) { + if(yych <= 0x08) goto yy34; + if(yych <= 0x0B) goto yy30; + goto yy34; + } else { + if(yych <= 0x0D) goto yy30; + if(yych <= 0x1F) goto yy34; + goto yy30; + } + } else { + if(yych <= '@') { + if(yych != '>') goto yy34; + } else { + if(yych <= 'Z') goto yy32; + if(yych <= '`') goto yy34; + if(yych <= 'z') goto yy32; + goto yy34; + } + } + ++YYCURSOR; #line 304 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); handle_form(STD_ARGS); goto state_plain_begin; } -#line 579 "ext/standard/url_scanner_ex.c" -yy30: ++YYCURSOR; - yych = *YYCURSOR; - goto yy37; + { passthru(STD_ARGS); handle_form(STD_ARGS); goto state_plain_begin; } +#line 560 "ext/standard/url_scanner_ex.c" +yy30: + ++YYCURSOR; + yych = *YYCURSOR; + goto yy37; yy31: #line 305 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); goto state_next_arg; } -#line 586 "ext/standard/url_scanner_ex.c" -yy32: ++YYCURSOR; - goto yy33; -yy33: + { passthru(STD_ARGS); goto state_next_arg; } +#line 568 "ext/standard/url_scanner_ex.c" +yy32: + ++YYCURSOR; #line 306 "ext/standard/url_scanner_ex.re" -{ --YYCURSOR; STATE = STATE_ARG; goto state_arg; } -#line 592 "ext/standard/url_scanner_ex.c" -yy34: ++YYCURSOR; - goto yy35; -yy35: + { --YYCURSOR; STATE = STATE_ARG; goto state_arg; } +#line 573 "ext/standard/url_scanner_ex.c" +yy34: + ++YYCURSOR; #line 307 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); goto state_plain_begin; } -#line 598 "ext/standard/url_scanner_ex.c" -yy36: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy37; -yy37: switch(yych){ - case 0x09: - case 0x0A: - case 0x0B: case 0x0D: case ' ': goto yy36; - default: goto yy31; + { passthru(STD_ARGS); goto state_plain_begin; } +#line 578 "ext/standard/url_scanner_ex.c" +yy36: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yy37: + if(yybm[0+yych] & 128) { + goto yy36; + } + goto yy31; } } #line 308 "ext/standard/url_scanner_ex.re" @@ -611,139 +591,73 @@ state_arg: start = YYCURSOR; - -#line 616 "ext/standard/url_scanner_ex.c" { - YYCTYPE yych; - goto yy38; - ++YYCURSOR; -yy38: - if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); - yych = *YYCURSOR; - switch(yych){ - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - case 'G': - case 'H': - case 'I': - case 'J': - case 'K': - case 'L': - case 'M': - case 'N': - case 'O': - case 'P': - case 'Q': - case 'R': - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'g': - case 'h': - case 'i': - case 'j': - case 'k': - case 'l': - case 'm': - case 'n': - case 'o': - case 'p': - case 'q': - case 'r': - case 's': - case 't': - case 'u': - case 'v': - case 'w': - case 'x': - case 'y': - case 'z': goto yy40; - default: goto yy42; - } -yy40: ++YYCURSOR; - yych = *YYCURSOR; - goto yy45; + static unsigned char yybm[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 128, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 0, 0, 0, 0, 0, + 0, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + +#line 631 "ext/standard/url_scanner_ex.c" + { + YYCTYPE yych; + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if(yych <= '@') goto yy42; + if(yych <= 'Z') goto yy40; + if(yych <= '`') goto yy42; + if(yych >= '{') goto yy42; +yy40: + ++YYCURSOR; + yych = *YYCURSOR; + goto yy45; yy41: #line 313 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); handle_arg(STD_ARGS); STATE = STATE_BEFORE_VAL; goto state_before_val; } -#line 684 "ext/standard/url_scanner_ex.c" -yy42: ++YYCURSOR; - goto yy43; -yy43: + { passthru(STD_ARGS); handle_arg(STD_ARGS); STATE = STATE_BEFORE_VAL; goto state_before_val; } +#line 647 "ext/standard/url_scanner_ex.c" +yy42: + ++YYCURSOR; #line 314 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); STATE = STATE_NEXT_ARG; goto state_next_arg; } -#line 690 "ext/standard/url_scanner_ex.c" -yy44: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy45; -yy45: switch(yych){ - case '-': case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - case 'G': - case 'H': - case 'I': - case 'J': - case 'K': - case 'L': - case 'M': - case 'N': - case 'O': - case 'P': - case 'Q': - case 'R': - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'g': - case 'h': - case 'i': - case 'j': - case 'k': - case 'l': - case 'm': - case 'n': - case 'o': - case 'p': - case 'q': - case 'r': - case 's': - case 't': - case 'u': - case 'v': - case 'w': - case 'x': - case 'y': - case 'z': goto yy44; - default: goto yy41; + { passthru(STD_ARGS); STATE = STATE_NEXT_ARG; goto state_next_arg; } +#line 652 "ext/standard/url_scanner_ex.c" +yy44: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yy45: + if(yybm[0+yych] & 128) { + goto yy44; + } + goto yy41; } } #line 315 "ext/standard/url_scanner_ex.re" @@ -751,61 +665,90 @@ state_before_val: start = YYCURSOR; - -#line 756 "ext/standard/url_scanner_ex.c" { - YYCTYPE yych; - unsigned int yyaccept = 0; - goto yy46; - ++YYCURSOR; -yy46: - if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); - yych = *YYCURSOR; - switch(yych){ - case ' ': goto yy48; - case '=': goto yy50; - default: goto yy52; - } -yy48: yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - switch(yych){ - case ' ': goto yy55; - case '=': goto yy53; - default: goto yy49; - } + static unsigned char yybm[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 128, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + +#line 705 "ext/standard/url_scanner_ex.c" + { + YYCTYPE yych; + unsigned int yyaccept = 0; + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if(yych == ' ') goto yy48; + if(yych == '=') goto yy50; + goto yy52; +yy48: + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if(yych == ' ') goto yy55; + if(yych == '=') goto yy53; yy49: #line 321 "ext/standard/url_scanner_ex.re" -{ --YYCURSOR; goto state_next_arg_begin; } -#line 780 "ext/standard/url_scanner_ex.c" -yy50: ++YYCURSOR; - yych = *YYCURSOR; - goto yy54; + { --YYCURSOR; goto state_next_arg_begin; } +#line 722 "ext/standard/url_scanner_ex.c" +yy50: + ++YYCURSOR; + yych = *YYCURSOR; + goto yy54; yy51: #line 320 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); STATE = STATE_VAL; goto state_val; } -#line 787 "ext/standard/url_scanner_ex.c" -yy52: yych = *++YYCURSOR; - goto yy49; -yy53: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy54; -yy54: switch(yych){ - case ' ': goto yy53; - default: goto yy51; - } -yy55: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy56; -yy56: switch(yych){ - case ' ': goto yy55; - case '=': goto yy53; - default: goto yy57; - } -yy57: YYCURSOR = YYMARKER; - switch(yyaccept){ - case 0: goto yy49; + { passthru(STD_ARGS); STATE = STATE_VAL; goto state_val; } +#line 730 "ext/standard/url_scanner_ex.c" +yy52: + yych = *++YYCURSOR; + goto yy49; +yy53: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yy54: + if(yybm[0+yych] & 128) { + goto yy53; + } + goto yy51; +yy55: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if(yych == ' ') goto yy55; + if(yych == '=') goto yy53; + YYCURSOR = YYMARKER; + switch(yyaccept){ + case 0: goto yy49; + } } } #line 322 "ext/standard/url_scanner_ex.re" @@ -814,121 +757,161 @@ state_val: start = YYCURSOR; - -#line 819 "ext/standard/url_scanner_ex.c" { - YYCTYPE yych; - unsigned int yyaccept = 0; - goto yy58; - ++YYCURSOR; -yy58: - if((YYLIMIT - YYCURSOR) < 3) YYFILL(3); - yych = *YYCURSOR; - switch(yych){ - case 0x09: - case 0x0A: case 0x0D: case ' ': case '>': goto yy64; - case '"': goto yy60; - case '\'': goto yy62; - default: goto yy63; - } -yy60: yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - goto yy77; + static unsigned char yybm[] = { + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 160, 160, 248, 248, 160, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 160, 248, 56, 248, 248, 248, 248, 200, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 0, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + }; + +#line 797 "ext/standard/url_scanner_ex.c" + { + YYCTYPE yych; + unsigned int yyaccept = 0; + if((YYLIMIT - YYCURSOR) < 3) YYFILL(3); + yych = *YYCURSOR; + if(yych <= ' ') { + if(yych <= 0x0C) { + if(yych <= 0x08) goto yy63; + if(yych <= 0x0A) goto yy64; + goto yy63; + } else { + if(yych <= 0x0D) goto yy64; + if(yych <= 0x1F) goto yy63; + goto yy64; + } + } else { + if(yych <= '&') { + if(yych != '"') goto yy63; + } else { + if(yych <= '\'') goto yy62; + if(yych == '>') goto yy64; + goto yy63; + } + } + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + goto yy77; yy61: #line 330 "ext/standard/url_scanner_ex.re" -{ handle_val(STD_ARGS, 0, ' '); goto state_next_arg_begin; } -#line 841 "ext/standard/url_scanner_ex.c" -yy62: yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - goto yy69; -yy63: yych = *++YYCURSOR; - goto yy67; -yy64: ++YYCURSOR; - goto yy65; -yy65: + { handle_val(STD_ARGS, 0, ' '); goto state_next_arg_begin; } +#line 828 "ext/standard/url_scanner_ex.c" +yy62: + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + goto yy69; +yy63: + yych = *++YYCURSOR; + goto yy67; +yy64: + ++YYCURSOR; #line 331 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); goto state_next_arg_begin; } -#line 852 "ext/standard/url_scanner_ex.c" -yy66: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy67; -yy67: switch(yych){ - case 0x09: - case 0x0A: case 0x0D: case ' ': case '>': goto yy61; - default: goto yy66; - } -yy68: yyaccept = 0; - YYMARKER = ++YYCURSOR; - if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); - yych = *YYCURSOR; - goto yy69; -yy69: switch(yych){ - case 0x09: - case 0x0A: case 0x0D: case ' ': goto yy72; - case '\'': goto yy70; - case '>': goto yy61; - default: goto yy68; - } -yy70: ++YYCURSOR; - switch((yych = *YYCURSOR)) { - case 0x09: - case 0x0A: case 0x0D: case ' ': case '>': goto yy71; - default: goto yy66; - } + { passthru(STD_ARGS); goto state_next_arg_begin; } +#line 840 "ext/standard/url_scanner_ex.c" +yy66: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yy67: + if(yybm[0+yych] & 8) { + goto yy66; + } + goto yy61; +yy68: + yyaccept = 0; + YYMARKER = ++YYCURSOR; + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; +yy69: + if(yybm[0+yych] & 16) { + goto yy68; + } + if(yych <= '&') goto yy72; + if(yych >= '(') goto yy61; + ++YYCURSOR; + if(yybm[0+(yych = *YYCURSOR)] & 8) { + goto yy66; + } yy71: #line 329 "ext/standard/url_scanner_ex.re" -{ handle_val(STD_ARGS, 1, '\''); goto state_next_arg_begin; } -#line 883 "ext/standard/url_scanner_ex.c" -yy72: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy73; -yy73: switch(yych){ - case '\'': goto yy75; - case '>': goto yy74; - default: goto yy72; - } -yy74: YYCURSOR = YYMARKER; - switch(yyaccept){ - case 0: goto yy61; - } -yy75: yych = *++YYCURSOR; - goto yy71; -yy76: yyaccept = 0; - YYMARKER = ++YYCURSOR; - if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); - yych = *YYCURSOR; - goto yy77; -yy77: switch(yych){ - case 0x09: - case 0x0A: case 0x0D: case ' ': goto yy80; - case '"': goto yy78; - case '>': goto yy61; - default: goto yy76; - } -yy78: ++YYCURSOR; - switch((yych = *YYCURSOR)) { - case 0x09: - case 0x0A: case 0x0D: case ' ': case '>': goto yy79; - default: goto yy66; - } + { handle_val(STD_ARGS, 1, '\''); goto state_next_arg_begin; } +#line 868 "ext/standard/url_scanner_ex.c" +yy72: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if(yybm[0+yych] & 32) { + goto yy72; + } + if(yych <= '=') goto yy75; +yy74: + YYCURSOR = YYMARKER; + switch(yyaccept){ + case 0: goto yy61; + } +yy75: + yych = *++YYCURSOR; + goto yy71; +yy76: + yyaccept = 0; + YYMARKER = ++YYCURSOR; + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; +yy77: + if(yybm[0+yych] & 64) { + goto yy76; + } + if(yych <= '!') goto yy80; + if(yych >= '#') goto yy61; + ++YYCURSOR; + if(yybm[0+(yych = *YYCURSOR)] & 8) { + goto yy66; + } yy79: #line 328 "ext/standard/url_scanner_ex.re" -{ handle_val(STD_ARGS, 1, '"'); goto state_next_arg_begin; } -#line 920 "ext/standard/url_scanner_ex.c" -yy80: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy81; -yy81: switch(yych){ - case '"': goto yy82; - case '>': goto yy74; - default: goto yy80; + { handle_val(STD_ARGS, 1, '"'); goto state_next_arg_begin; } +#line 903 "ext/standard/url_scanner_ex.c" +yy80: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if(yybm[0+yych] & 128) { + goto yy80; + } + if(yych >= '>') goto yy74; + ++YYCURSOR; + yych = *YYCURSOR; + goto yy79; } -yy82: ++YYCURSOR; - yych = *YYCURSOR; - goto yy79; } #line 332 "ext/standard/url_scanner_ex.re" @@ -1055,7 +1038,7 @@ if (! BG(url_adapt_state_ex).active) { php_url_scanner_ex_activate(TSRMLS_C); - php_ob_set_internal_handler(php_url_scanner_output_handler, 0, "URL-Rewriter", 1 TSRMLS_CC); + php_output_start_internal("URL-Rewriter", php_url_scanner_output_handler, 0, PHP_OUTPUT_HANDLER_STDFLAGS); BG(url_adapt_state_ex).active = 1; } http://cvs.php.net/viewcvs.cgi/php-src/ext/standard/url_scanner_ex.re?r1=1.78&r2=1.79&diff_format=u Index: php-src/ext/standard/url_scanner_ex.re diff -u php-src/ext/standard/url_scanner_ex.re:1.78 php-src/ext/standard/url_scanner_ex.re:1.79 --- php-src/ext/standard/url_scanner_ex.re:1.78 Tue Feb 28 14:46:29 2006 +++ php-src/ext/standard/url_scanner_ex.re Fri Jun 2 19:51:42 2006 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: url_scanner_ex.re,v 1.78 2006/02/28 14:46:29 iliaa Exp $ */ +/* $Id: url_scanner_ex.re,v 1.79 2006/06/02 19:51:42 mike Exp $ */ #include "php.h" @@ -453,7 +453,7 @@ if (! BG(url_adapt_state_ex).active) { php_url_scanner_ex_activate(TSRMLS_C); - php_ob_set_internal_handler(php_url_scanner_output_handler, 0, "URL-Rewriter", 1 TSRMLS_CC); + php_output_start_internal("URL-Rewriter", php_url_scanner_output_handler, 0, PHP_OUTPUT_HANDLER_STDFLAGS); BG(url_adapt_state_ex).active = 1; } http://cvs.php.net/viewcvs.cgi/php-src/ext/standard/var.c?r1=1.231&r2=1.232&diff_format=u Index: php-src/ext/standard/var.c diff -u php-src/ext/standard/var.c:1.231 php-src/ext/standard/var.c:1.232 --- php-src/ext/standard/var.c:1.231 Tue May 30 14:51:54 2006 +++ php-src/ext/standard/var.c Fri Jun 2 19:51:42 2006 @@ -12,13 +12,13 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Authors: Jani Lehtimäki <jkl@njet.net> | + | Authors: Jani Lehtim�i <jkl@njet.net> | | Thies C. Arntzen <thies@thieso.net> | | Sascha Schumann <sascha@schumann.cx> | +----------------------------------------------------------------------+ */ -/* $Id: var.c,v 1.231 2006/05/30 14:51:54 iliaa Exp $ */ +/* $Id: var.c,v 1.232 2006/06/02 19:51:42 mike Exp $ */ @@ -602,7 +602,7 @@ } if (return_output) { - php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC); + php_output_start_default(); } /* UTODO @@ -614,8 +614,8 @@ php_var_export(&var, 1 TSRMLS_CC); if (return_output) { - php_ob_get_buffer (return_value TSRMLS_CC); - php_end_ob_buffer (0, 0 TSRMLS_CC); + php_output_get_contents(return_value); + php_output_discard(); } } /* }}} */ http://cvs.php.net/viewcvs.cgi/php-src/ext/tidy/tidy.c?r1=1.86&r2=1.87&diff_format=u Index: php-src/ext/tidy/tidy.c diff -u php-src/ext/tidy/tidy.c:1.86 php-src/ext/tidy/tidy.c:1.87 --- php-src/ext/tidy/tidy.c:1.86 Wed May 24 21:22:27 2006 +++ php-src/ext/tidy/tidy.c Fri Jun 2 19:51:42 2006 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: tidy.c,v 1.86 2006/05/24 21:22:27 tony2001 Exp $ */ +/* $Id: tidy.c,v 1.87 2006/06/02 19:51:42 mike Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -985,9 +985,13 @@ PHP_RINIT_FUNCTION(tidy) { if (INI_BOOL("tidy.clean_output") == TRUE) { - if (php_start_ob_buffer_named("ob_tidyhandler", 0, 1 TSRMLS_CC) == FAILURE) { + zval *name; + MAKE_STD_ZVAL(name); + ZVAL_ASCII_STRINGL(name, "ob_tidyhandler", sizeof("ob_tidyhandler"), ZSTR_DUPLICATE); + if (php_output_start_user(name, 0, PHP_OUTPUT_HANDLER_STDFLAGS) == FAILURE) { zend_error(E_NOTICE, "Failure installing Tidy output buffering."); } + zval_ptr_dtor(&name); } return SUCCESS; @@ -1009,7 +1013,7 @@ php_info_print_table_start(); php_info_print_table_header(2, "Tidy support", "enabled"); php_info_print_table_row(2, "libTidy Release", (char *)tidyReleaseDate()); - php_info_print_table_row(2, "Extension Version", PHP_TIDY_MODULE_VERSION " ($Id: tidy.c,v 1.86 2006/05/24 21:22:27 tony2001 Exp $)"); + php_info_print_table_row(2, "Extension Version", PHP_TIDY_MODULE_VERSION " ($Id: tidy.c,v 1.87 2006/06/02 19:51:42 mike Exp $)"); php_info_print_table_end(); DISPLAY_INI_ENTRIES(); http://cvs.php.net/viewcvs.cgi/php-src/ext/zlib/php_zlib.h?r1=1.43&r2=1.44&diff_format=u Index: php-src/ext/zlib/php_zlib.h diff -u php-src/ext/zlib/php_zlib.h:1.43 php-src/ext/zlib/php_zlib.h:1.44 --- php-src/ext/zlib/php_zlib.h:1.43 Sun Jan 1 13:09:56 2006 +++ php-src/ext/zlib/php_zlib.h Fri Jun 2 19:51:42 2006 @@ -13,11 +13,11 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | - | Stefan Röhrich <sr@linux.de> | + | Stefan R�rich <sr@linux.de> | +----------------------------------------------------------------------+ */ -/* $Id: php_zlib.h,v 1.43 2006/01/01 13:09:56 sniper Exp $ */ +/* $Id: php_zlib.h,v 1.44 2006/06/02 19:51:42 mike Exp $ */ #ifndef PHP_ZLIB_H #define PHP_ZLIB_H @@ -55,7 +55,7 @@ PHP_FUNCTION(zlib_get_coding_type); int php_enable_output_compression(int buffer_size TSRMLS_DC); -int php_ob_gzhandler_check(TSRMLS_D); +int php_ob_gzhandler_check(zval *handler_name TSRMLS_DC); php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); extern php_stream_ops php_stream_gzio_ops; http://cvs.php.net/viewcvs.cgi/php-src/ext/zlib/zlib.c?r1=1.193&r2=1.194&diff_format=u Index: php-src/ext/zlib/zlib.c diff -u php-src/ext/zlib/zlib.c:1.193 php-src/ext/zlib/zlib.c:1.194 --- php-src/ext/zlib/zlib.c:1.193 Sat Apr 29 14:38:35 2006 +++ php-src/ext/zlib/zlib.c Fri Jun 2 19:51:42 2006 @@ -13,13 +13,13 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | - | Stefan Röhrich <sr@linux.de> | + | Stefan R�rich <sr@linux.de> | | Zeev Suraski <zeev@zend.com> | | Jade Nicoletti <nicoletti@nns.ch> | +----------------------------------------------------------------------+ */ -/* $Id: zlib.c,v 1.193 2006/04/29 14:38:35 fmk Exp $ */ +/* $Id: zlib.c,v 1.194 2006/06/02 19:51:42 mike Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -211,11 +211,15 @@ */ PHP_MINIT_FUNCTION(zlib) { + zval tmp; #ifdef ZTS ts_allocate_id(&zlib_globals_id, sizeof(zend_zlib_globals), (ts_allocate_ctor) php_zlib_init_globals, NULL); #endif 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); + INIT_PZVAL(&tmp); + ZVAL_ASCII_STRINGL(&tmp, "ob_gzhandler", sizeof("ob_gzhandler")-1, 0); + php_output_handler_conflict_register(&tmp, php_ob_gzhandler_check); REGISTER_LONG_CONSTANT("FORCE_GZIP", CODING_GZIP, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FORCE_DEFLATE", CODING_DEFLATE, CONST_CS | CONST_PERSISTENT); @@ -828,30 +832,41 @@ /* {{{ php_ob_gzhandler_check */ -int php_ob_gzhandler_check(TSRMLS_D) +int php_ob_gzhandler_check(zval *handler_name TSRMLS_DC) { /* check for wrong usages */ - if (OG(ob_nesting_level > 0)) { - if (php_ob_handler_used("ob_gzhandler" TSRMLS_CC)) { + if (php_output_get_level() > 0) { + zval tmp; + + if (php_output_handler_started(handler_name)) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used twice"); return FAILURE; } - if (php_ob_handler_used("mb_output_handler" TSRMLS_CC)) { + INIT_PZVAL(&tmp); + ZVAL_ASCII_STRINGL(&tmp, "mb_output_handler", sizeof("mb_output_handler")-1, ZSTR_DUPLICATE); + if (php_output_handler_started(&tmp)) { + zval_dtor(&tmp); 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)) { + zval_dtor(&tmp); + ZVAL_ASCII_STRINGL(&tmp, "URL-Reqriter", sizeof("URL-Rewriter")-1, ZSTR_DUPLICATE); + if (php_output_handler_started(&tmp)) { + zval_dtor(&tmp); 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)) { + zval_dtor(&tmp); + ZVAL_ASCII_STRINGL(&tmp, "zlib output compression", sizeof("zlib output compression")-1, ZSTR_DUPLICATE); + if (php_output_handler_conflict(handler_name, &tmp)) { + zval_dtor(&tmp); return FAILURE; } + zval_dtor(&tmp); } return SUCCESS; } - /* }}} */ /* {{{ proto string ob_gzhandler(string str, int mode) @@ -869,8 +884,9 @@ return; } - if(ZLIBG(ob_gzhandler_status) == -1) + if(ZLIBG(ob_gzhandler_status) == -1) { RETURN_FALSE; + } zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); @@ -878,16 +894,20 @@ || 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; + 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; + } + } + + if (ZLIBG(ob_gzhandler_status == -1)) { + /* don't call this handler any more */ + php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_DISABLE, NULL); RETURN_FALSE; } @@ -931,8 +951,13 @@ } if (return_original) { + /* don't call this handler any more */ + php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_DISABLE, NULL); /* return the original string */ RETURN_STRINGL(string, string_len, 1); + } else { + /* don't allow cleaning and removing any longer */ + php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL); } } /* }}} */ @@ -959,7 +984,7 @@ */ int php_enable_output_compression(int buffer_size TSRMLS_DC) { - zval **a_encoding; + zval **a_encoding, *output_handler; zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); @@ -979,10 +1004,16 @@ 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); + MAKE_STD_ZVAL(output_handler); + ZVAL_ASCII_STRINGL(output_handler, "zlib output compression", sizeof("zlib output compression")-1, ZSTR_DUPLICATE); + php_output_start_internal(output_handler, php_gzip_output_handler, buffer_size, PHP_OUTPUT_HANDLER_STDFLAGS); + zval_ptr_dtor(&output_handler); + + if (ZLIBG(output_handler) && *ZLIBG(output_handler)) { + MAKE_STD_ZVAL(output_handler); + ZVAL_ASCII_STRING(output_handler, ZLIBG(output_handler), ZSTR_DUPLICATE); + php_output_start_user(output_handler, 0, PHP_OUTPUT_HANDLER_STDFLAGS); + zval_ptr_dtor(&output_handler); } return SUCCESS; } http://cvs.php.net/viewcvs.cgi/php-src/main/SAPI.c?r1=1.214&r2=1.215&diff_format=u Index: php-src/main/SAPI.c diff -u php-src/main/SAPI.c:1.214 php-src/main/SAPI.c:1.215 --- php-src/main/SAPI.c:1.214 Wed May 10 21:25:01 2006 +++ php-src/main/SAPI.c Fri Jun 2 19:51:42 2006 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: SAPI.c,v 1.214 2006/05/10 21:25:01 rasmus Exp $ */ +/* $Id: SAPI.c,v 1.215 2006/06/02 19:51:42 mike Exp $ */ #include <ctype.h> #include <sys/stat.h> @@ -553,8 +553,8 @@ int http_response_code; if (SG(headers_sent) && !SG(request_info).no_headers) { - char *output_start_filename = php_get_output_start_filename(TSRMLS_C); - int output_start_lineno = php_get_output_start_lineno(TSRMLS_C); + char *output_start_filename = php_output_get_start_filename(); + int output_start_lineno = php_output_get_start_lineno(); if (output_start_filename) { sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent by (output started at %s:%d)", @@ -720,6 +720,7 @@ } #if HAVE_ZLIB + /* TODO: move to zlib.c */ /* Add output compression headers at this late stage in order to make it possible to switch it off inside the script. */ http://cvs.php.net/viewcvs.cgi/php-src/main/main.c?r1=1.692&r2=1.693&diff_format=u Index: php-src/main/main.c diff -u php-src/main/main.c:1.692 php-src/main/main.c:1.693 --- php-src/main/main.c:1.692 Sat May 27 20:53:38 2006 +++ php-src/main/main.c Fri Jun 2 19:51:42 2006 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: main.c,v 1.692 2006/05/27 20:53:38 johannes Exp $ */ +/* $Id: main.c,v 1.693 2006/06/02 19:51:42 mike Exp $ */ /* {{{ includes */ @@ -234,8 +234,8 @@ #define PHP_INI_OPTION_HEADERS_SENT(option_name) \ if (SG(headers_sent)) { \ - char *output_start_filename = php_get_output_start_filename(TSRMLS_C); \ - int output_start_lineno = php_get_output_start_lineno(TSRMLS_C); \ + char *output_start_filename = php_output_get_start_filename(); \ + int output_start_lineno = php_output_get_start_lineno(); \ if (output_start_filename) { \ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Option " #option_name " cannot be changed after headers have been sent (output started at %s:%d)", \ output_start_filename, output_start_lineno); \ @@ -870,14 +870,7 @@ php_log_err(log_buffer TSRMLS_CC); efree(log_buffer); } - if (PG(display_errors) - && ((module_initialized && !PG(during_request_startup)) - || (PG(display_startup_errors) - && (OG(php_body_write)==php_default_output_func || OG(php_body_write)==php_ub_body_write_no_header || OG(php_body_write)==php_ub_body_write) - ) - ) - ) { - + if (PG(display_errors) && ((module_initialized && !PG(during_request_startup)) || (PG(display_startup_errors)))) { if (PG(xmlrpc_errors)) { php_printf("<?xml version=\"1.0\"?><methodResponse><fault><value><struct><member><name>faultCode</name><value><int>%ld</int></value></member><member><name>faultString</name><value><string>%s:%s in %s on line %d</string></value></member></struct></value></fault></methodResponse>", PG(xmlrpc_error_number), error_type_str, buffer, error_filename, error_lineno); } else { @@ -1182,7 +1175,7 @@ zend_try { PG(during_request_startup) = 1; - php_output_activate(TSRMLS_C); + php_output_activate(); /* initialize global variables */ PG(modules_activated) = 0; @@ -1208,15 +1201,16 @@ } if (PG(output_handler) && PG(output_handler)[0]) { - php_start_ob_buffer_named(PG(output_handler), 0, 1 TSRMLS_CC); + zval *oh; + + MAKE_STD_ZVAL(oh); + ZVAL_ASCII_STRING(oh, PG(output_handler), ZSTR_DUPLICATE); + php_output_start_user(oh, 0, PHP_OUTPUT_HANDLER_STDFLAGS); + zval_ptr_dtor(&oh); } else if (PG(output_buffering)) { - if (PG(output_buffering)>1) { - php_start_ob_buffer(NULL, PG(output_buffering), 1 TSRMLS_CC); - } else { - php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC); - } + php_output_start_user(NULL, PG(output_buffering) > 1 ? PG(output_buffering) : 0, PHP_OUTPUT_HANDLER_STDFLAGS); } else if (PG(implicit_flush)) { - php_start_implicit_flush(TSRMLS_C); + php_output_set_implicit_flush(1); } /* We turn this off in php_execute_script() */ @@ -1246,13 +1240,12 @@ return FAILURE; } - php_output_activate(TSRMLS_C); + php_output_activate(); sapi_activate(TSRMLS_C); php_hash_environment(TSRMLS_C); zend_try { PG(during_request_startup) = 1; - php_output_activate(TSRMLS_C); if (PG(expose_php)) { sapi_add_header(SAPI_PHP_VERSION_HEADER, sizeof(SAPI_PHP_VERSION_HEADER)-1, 1); } @@ -1279,7 +1272,7 @@ return FAILURE; } - php_output_activate(TSRMLS_C); + php_output_activate(); sapi_activate_headers_only(TSRMLS_C); php_hash_environment(TSRMLS_C); @@ -1372,7 +1365,12 @@ /* 3. Flush all output buffers */ zend_try { - php_end_ob_buffers((zend_bool)(SG(request_info).headers_only?0:1) TSRMLS_CC); + if (SG(request_info).headers_only) { + php_output_discard_all(); + } else { + php_output_end_all(); + } + php_output_deactivate(); } zend_end_try(); /* 4. Send the set HTTP headers (note: This must be done AFTER php_end_ob_buffers() !!) */ @@ -1432,12 +1430,12 @@ /* }}} */ -/* {{{ php_body_write_wrapper +/* {{{ php_output_wrapper */ -static int php_body_write_wrapper(const char *str, uint str_length) +static int php_output_wrapper(const char *str, uint str_length) { TSRMLS_FETCH(); - return php_body_write(str, str_length TSRMLS_CC); + return php_output_write(str, str_length); } /* }}} */ @@ -1523,7 +1521,7 @@ zuf.error_function = php_error_cb; zuf.printf_function = php_printf; - zuf.write_function = php_body_write_wrapper; + zuf.write_function = php_output_wrapper; zuf.fopen_function = php_fopen_wrapper_for_zend; zuf.message_handler = php_message_handler_for_zend; zuf.block_interruptions = sapi_module.block_interruptions; @@ -1667,7 +1665,7 @@ REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS); REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MAX", LONG_MAX, CONST_PERSISTENT | CONST_CS); REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", sizeof(long), CONST_PERSISTENT | CONST_CS); - php_output_register_constants(TSRMLS_C); + php_output_register_constants(); php_rfc1867_register_constants(TSRMLS_C); if (php_startup_ticks(TSRMLS_C) == FAILURE) { @@ -1785,6 +1783,8 @@ zend_ini_global_shutdown(TSRMLS_C); #endif + php_output_shutdown(); + module_initialized = 0; if (PG(last_error_message)) { free(PG(last_error_message)); @@ -1946,7 +1946,7 @@ TSRMLS_FETCH(); PG(connection_status) = PHP_CONNECTION_ABORTED; - php_output_set_status(0 TSRMLS_CC); + php_output_set_status(PHP_OUTPUT_DISABLED); if (!PG(ignore_user_abort)) { zend_bailout(); http://cvs.php.net/viewcvs.cgi/php-src/main/output.c?r1=1.177&r2=1.178&diff_format=u Index: php-src/main/output.c diff -u php-src/main/output.c:1.177 php-src/main/output.c:1.178 --- php-src/main/output.c:1.177 Mon Mar 27 08:26:20 2006 +++ php-src/main/output.c Fri Jun 2 19:51:42 2006 @@ -1,4 +1,4 @@ -/* +/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ @@ -15,801 +15,1209 @@ | Authors: Zeev Suraski <zeev@zend.com> | | Thies C. Arntzen <thies@thieso.net> | | Marcus Boerger <helly@php.net> | + | New API: Michael Wallner <mike@php.net> | +----------------------------------------------------------------------+ */ -/* $Id: output.c,v 1.177 2006/03/27 08:26:20 tony2001 Exp $ */ +/* $Id: output.c,v 1.178 2006/06/02 19:51:42 mike Exp $ */ + +#ifndef PHP_OUTPUT_DEBUG +# define PHP_OUTPUT_DEBUG 0 +#endif +#ifndef PHP_OUTPUT_NOINLINE +# define PHP_OUTPUT_NOINLINE 0 +#endif #include "php.h" #include "ext/standard/head.h" -#include "ext/standard/basic_functions.h" #include "ext/standard/url_scanner_ex.h" -#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB) -#include "ext/zlib/php_zlib.h" -#endif #include "SAPI.h" +#include "zend_stack.h" +#include "php_output.h" -#define OB_DEFAULT_HANDLER_NAME "default output handler" - -/* output functions */ -static int php_b_body_write(const char *str, uint str_length TSRMLS_DC); +ZEND_DECLARE_MODULE_GLOBALS(output); -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); +#if PHP_OUTPUT_NOINLINE || PHP_OUTPUT_DEBUG +# undef inline +# define inline #endif -#ifdef ZTS -int output_globals_id; -#else -php_output_globals output_globals; -#endif +/* {{{ aliases, conflict and reverse conflict hash tables */ +static HashTable php_output_handler_aliases; +static HashTable php_output_handler_conflicts; +static HashTable php_output_handler_reverse_conflicts; +/* }}} */ + +/* {{{ forward declarations */ +static inline int php_output_lock_error(int op TSRMLS_DC); +static inline void php_output_op(int op, const char *str, size_t len TSRMLS_DC); + +static inline php_output_handler *php_output_handler_init(zval *name, size_t chunk_size, int flags); +static inline int php_output_handler_op(php_output_handler *handler, php_output_context *context); +static inline int php_output_handler_append(php_output_handler *handler, const php_output_buffer *buf TSRMLS_DC); +static inline zval *php_output_handler_status(php_output_handler *handler, zval *entry); + +static inline php_output_context *php_output_context_init(php_output_context *context, int op TSRMLS_DC); +static inline void php_output_context_reset(php_output_context *context); +static inline void php_output_context_swap(php_output_context *context); +static inline void php_output_context_dtor(php_output_context *context); + +static inline int php_output_stack_pop(int discard, int shutdown TSRMLS_DC); -/* {{{ php_default_output_func */ -PHPAPI int php_default_output_func(const char *str, uint str_len TSRMLS_DC) +static int php_output_stack_apply_op(void *h, void *c); +static int php_output_stack_apply_clean(void *h, void *c); +static int php_output_stack_apply_list(void *h, void *z); +static int php_output_stack_apply_status(void *h, void *z); + +static int php_output_handler_compat_func(void **handler_context, php_output_context *output_context); +static int php_output_handler_default_func(void **handler_context, php_output_context *output_context); +static int php_output_handler_devnull_func(void **handler_context, php_output_context *output_context); +/* }}} */ + +/* {{{ static void php_output_init_globals(zend_output_globals *G) + Initialize the module globals on MINIT */ +static inline void php_output_init_globals(zend_output_globals *G) { - fwrite(str, 1, str_len, stderr); - return str_len; + memset(G, 0, sizeof(*G)); } /* }}} */ -/* {{{ php_output_init_globals */ -static void php_output_init_globals(php_output_globals *output_globals_p TSRMLS_DC) +/* {{{ void php_output_startup(void) + Set up module globals and initalize the conflict and reverse conflict hash tables */ +PHPAPI void php_output_startup(void) { - OG(php_body_write) = php_default_output_func; - OG(php_header_write) = php_default_output_func; - OG(implicit_flush) = 0; - OG(output_start_filename) = NULL; - OG(output_start_lineno) = 0; + ZEND_INIT_MODULE_GLOBALS(output, php_output_init_globals, NULL); + zend_hash_init(&php_output_handler_aliases, 0, NULL, NULL, 1); + zend_hash_init(&php_output_handler_conflicts, 0, NULL, NULL, 1); + zend_hash_init(&php_output_handler_reverse_conflicts, 0, NULL, (void (*)(void *)) zend_hash_destroy, 1); } /* }}} */ +/* {{{ void php_output_shutdown(void) + Destroy module globals and the conflict and reverse conflict hash tables */ +PHPAPI void php_output_shutdown(void) +{ + zend_hash_destroy(&php_output_handler_aliases); + zend_hash_destroy(&php_output_handler_conflicts); + zend_hash_destroy(&php_output_handler_reverse_conflicts); +} +/* }}} */ -/* {{{ php_output_startup - Start output layer */ -PHPAPI void php_output_startup(void) +/* {{{ SUCCESS|FAILURE php_output_activate(TSRMLS_D) + Reset output globals and setup the output handler stack */ +PHPAPI int _php_output_activate(TSRMLS_D) { #ifdef ZTS - ts_allocate_id(&output_globals_id, sizeof(php_output_globals), (ts_allocate_ctor) php_output_init_globals, NULL); -#else - php_output_init_globals(&output_globals TSRMLS_CC); + memset((*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(output_globals_id)], 0, sizeof(zend_output_globals)); +#else + memset(&output_globals, 0, sizeof(zend_output_globals)); #endif + if (SUCCESS != zend_stack_init(&OG(handlers))) { + return FAILURE; + } + + MAKE_STD_ZVAL(OG(default_output_handler_name)); + ZVAL_ASCII_STRINGL(OG(default_output_handler_name), "default output handler", sizeof("default output handler")-1, ZSTR_DUPLICATE); + MAKE_STD_ZVAL(OG(devnull_output_handler_name)); + ZVAL_ASCII_STRINGL(OG(devnull_output_handler_name), "null output handler", sizeof("null output handler")-1, ZSTR_DUPLICATE); + + return SUCCESS; } /* }}} */ - -/* {{{ php_output_activate - Initilize output global for activation */ -PHPAPI void php_output_activate(TSRMLS_D) +/* {{{ void php_output_deactivate(TSRMLS_D) + Destroy the output handler stack */ +PHPAPI void _php_output_deactivate(TSRMLS_D) { - OG(php_body_write) = php_ub_body_write; - OG(php_header_write) = sapi_module.ub_write; - OG(ob_nesting_level) = 0; - OG(ob_lock) = 0; - OG(disable_output) = 0; - OG(output_start_filename) = NULL; - OG(output_start_lineno) = 0; + php_output_handler **handler = NULL; + + OG(active) = NULL; + OG(running) = NULL; + /* release all output handlers */ + while (SUCCESS == zend_stack_top(&OG(handlers), (void *) &handler)) { + php_output_handler_free(handler); + zend_stack_del_top(&OG(handlers)); + } + zend_stack_destroy(&OG(handlers)); + + zval_ptr_dtor(&OG(default_output_handler_name)); + zval_ptr_dtor(&OG(devnull_output_handler_name)); } /* }}} */ +/* {{{ void _php_output_register_constants() */ +PHPAPI void _php_output_register_constants(TSRMLS_D) +{ + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_START", PHP_OUTPUT_HANDLER_START, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_WRITE", PHP_OUTPUT_HANDLER_WRITE, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_FLUSH", PHP_OUTPUT_HANDLER_FLUSH, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CLEAN", PHP_OUTPUT_HANDLER_CLEAN, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_FINAL", PHP_OUTPUT_HANDLER_FINAL, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CONT", PHP_OUTPUT_HANDLER_WRITE, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_END", PHP_OUTPUT_HANDLER_FINAL, CONST_CS | CONST_PERSISTENT); + + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CLEANABLE", PHP_OUTPUT_HANDLER_CLEANABLE, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_REMOVABLE", PHP_OUTPUT_HANDLER_REMOVABLE, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_STDFLAGS", PHP_OUTPUT_HANDLER_STDFLAGS, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_STARTED", PHP_OUTPUT_HANDLER_STARTED, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_DISABLED", PHP_OUTPUT_HANDLER_DISABLED, CONST_CS | CONST_PERSISTENT); +} +/* }}} */ -/* {{{ php_output_set_status - Toggle output status. Do NOT use in application code, only in SAPIs where appropriate. */ -PHPAPI void php_output_set_status(zend_bool status TSRMLS_DC) +/* {{{ void php_output_set_status(int status) + Used by SAPIs to disable output */ +PHPAPI void _php_output_set_status(int status TSRMLS_DC) { - OG(disable_output) = !status; + OG(flags) = status & 0xf; } /* }}} */ -/* {{{ php_output_register_constants */ -void php_output_register_constants(TSRMLS_D) +/* {{{ int php_output_get_status() + Get output control status */ +PHPAPI int _php_output_get_status(TSRMLS_D) { - REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_START", PHP_OUTPUT_HANDLER_START, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CONT", PHP_OUTPUT_HANDLER_CONT, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_END", PHP_OUTPUT_HANDLER_END, CONST_CS | CONST_PERSISTENT); + return OG(flags) + | (OG(active) ? PHP_OUTPUT_ACTIVE : 0) + | (OG(running)? PHP_OUTPUT_LOCKED : 0); } /* }}} */ +/* {{{ zval *php_output_get_default_handler_name() */ +PHPAPI zval *_php_output_get_default_handler_name(TSRMLS_D) +{ + return OG(default_output_handler_name); +} +/* }}} */ -/* {{{ php_body_wirte - * Write body part */ -PHPAPI int php_body_write(const char *str, uint str_length TSRMLS_DC) +/* {{{ zval *php_output_get_devnull_handler_name() */ +PHPAPI zval *_php_output_get_devnull_handler_name(TSRMLS_D) { - return OG(php_body_write)(str, str_length TSRMLS_CC); + return OG(devnull_output_handler_name); } /* }}} */ -/* {{{ php_header_wirte - * Write HTTP header */ -PHPAPI int php_header_write(const char *str, uint str_length TSRMLS_DC) +/* {{{ int php_output_write_unbuffered(const char *str, size_t len) + Unbuffered write */ +PHPAPI int _php_output_write_unbuffered(const char *str, size_t len TSRMLS_DC) { - if (OG(disable_output)) { + if (OG(flags) & PHP_OUTPUT_DISABLED) { return 0; - } else { - return OG(php_header_write)(str, str_length TSRMLS_CC); } + return sapi_module.ub_write(str, len TSRMLS_CC); } /* }}} */ -/* {{{ php_start_ob_buffer - * Start output buffering */ -PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC) +/* {{{ int php_output_write(const char *str, size_t len) + Buffered write */ +PHPAPI int _php_output_write(const char *str, size_t len TSRMLS_DC) { - uint initial_size, block_size; - - if (OG(ob_lock)) { - 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_docref("ref.outcontrol" TSRMLS_CC, E_ERROR, "Cannot use output buffering in output buffering display handlers"); - return FAILURE; + if (OG(flags) & PHP_OUTPUT_DISABLED) { + return 0; } - if (chunk_size > 0) { - if (chunk_size==1) { - chunk_size = 4096; + php_output_op(PHP_OUTPUT_HANDLER_WRITE, str, len TSRMLS_CC); + return (int) len; +} +/* }}} */ + +/* {{{ void php_output_flush() + Flush the most recent output handlers buffer */ +PHPAPI void _php_output_flush(TSRMLS_D) +{ + php_output_context context; + + if (OG(active)) { + php_output_context_init(&context, PHP_OUTPUT_HANDLER_FLUSH TSRMLS_CC); + php_output_handler_op(OG(active), &context); + if (context.out.data && context.out.used) { + zend_stack_del_top(&OG(handlers)); + php_output_write(context.out.data, context.out.used); + zend_stack_push(&OG(handlers), &OG(active), sizeof(php_output_handler *)); } - initial_size = (chunk_size*3/2); - block_size = chunk_size/2; - } else { - initial_size = 40*1024; - block_size = 10*1024; + php_output_context_dtor(&context); } - 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) +/* {{{ void php_output_flush_all() + Flush all output buffers subsequently */ +PHPAPI void _php_output_flush_all(TSRMLS_D) { - 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; + if (OG(active)) { + php_output_op(PHP_OUTPUT_HANDLER_FLUSH, NULL, 0 TSRMLS_CC); + } } /* }}} */ -/* {{{ php_end_ob_buffer - * End output buffering (one level) */ -PHPAPI void php_end_ob_buffer(zend_bool send_buffer, zend_bool just_flush TSRMLS_DC) +/* {{{ SUCCESS|FAILURE php_output_clean() + Cleans the most recent output handlers buffer if the handler is cleanable */ +PHPAPI int _php_output_clean(TSRMLS_D) { - char *final_buffer=NULL; - unsigned int final_buffer_length=0; - zval *alternate_buffer=NULL; - char *to_be_destroyed_buffer, *to_be_destroyed_handler_name; - char *to_be_destroyed_handled_output[2] = { 0, 0 }; - int status; - php_ob_buffer *prev_ob_buffer_p=NULL; - php_ob_buffer orig_ob_buffer; - - if (OG(ob_nesting_level)==0) { - return; - } - status = 0; - if (!OG(active_ob_buffer).status & PHP_OUTPUT_HANDLER_START) { - /* our first call */ - status |= PHP_OUTPUT_HANDLER_START; - } - if (just_flush) { - status |= PHP_OUTPUT_HANDLER_CONT; - } else { - status |= PHP_OUTPUT_HANDLER_END; + php_output_context context; + + if (OG(active) && (OG(active)->flags & PHP_OUTPUT_HANDLER_CLEANABLE)) { + OG(active)->buffer.used = 0; + php_output_context_init(&context, PHP_OUTPUT_HANDLER_CLEAN TSRMLS_CC); + php_output_handler_op(OG(active), &context); + php_output_context_dtor(&context); + return SUCCESS; } + return FAILURE; +} +/* }}} */ -#if 0 - { - FILE *fp; - fp = fopen("/tmp/ob_log", "a"); - fprintf(fp, "NestLevel: %d ObStatus: %d HandlerName: %s\n", OG(ob_nesting_level), status, OG(active_ob_buffer).handler_name.s); - fclose(fp); - } -#endif +/* {{{ void php_output_clean_all() + Cleans all output handler buffers, without regard whether the handler is cleanable */ +PHPAPI void _php_output_clean_all(TSRMLS_D) +{ + php_output_context context; - if (OG(active_ob_buffer).internal_output_handler) { - final_buffer = OG(active_ob_buffer).internal_output_handler_buffer; - final_buffer_length = OG(active_ob_buffer).internal_output_handler_buffer_size; - OG(active_ob_buffer).internal_output_handler(OG(active_ob_buffer).buffer, OG(active_ob_buffer).text_length, &final_buffer, &final_buffer_length, status TSRMLS_CC); - } else if (OG(active_ob_buffer).output_handler) { - zval **params[2]; - zval *orig_buffer; - zval *z_status; - - ALLOC_INIT_ZVAL(orig_buffer); - ZVAL_U_STRINGL(ZEND_U_CONVERTER(UG(output_encoding_conv)), orig_buffer, OG(active_ob_buffer).buffer, OG(active_ob_buffer).text_length, 1); - orig_buffer->refcount=2; /* don't let call_user_function() destroy our buffer */ - orig_buffer->is_ref=1; - - ALLOC_INIT_ZVAL(z_status); - ZVAL_LONG(z_status, status); - - params[0] = &orig_buffer; - params[1] = &z_status; - OG(ob_lock) = 1; - - if (call_user_function_ex(CG(function_table), NULL, OG(active_ob_buffer).output_handler, &alternate_buffer, 2, params, 1, NULL TSRMLS_CC)==SUCCESS) { - if (alternate_buffer && !(Z_TYPE_P(alternate_buffer)==IS_BOOL && Z_BVAL_P(alternate_buffer)==0)) { - convert_to_string_ex(&alternate_buffer); - final_buffer = Z_STRVAL_P(alternate_buffer); - final_buffer_length = Z_STRLEN_P(alternate_buffer); - } - } - OG(ob_lock) = 0; - if (!just_flush) { - zval_ptr_dtor(&OG(active_ob_buffer).output_handler); - } - orig_buffer->refcount -=2; - if (orig_buffer->refcount <= 0) { /* free the zval */ - zval_dtor(orig_buffer); - FREE_ZVAL(orig_buffer); - } - zval_ptr_dtor(&z_status); + if (OG(active)) { + php_output_context_init(&context, PHP_OUTPUT_HANDLER_CLEAN TSRMLS_CC); + zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_TOPDOWN, php_output_stack_apply_clean, &context); } +} - if (!final_buffer) { - final_buffer = OG(active_ob_buffer).buffer; - final_buffer_length = OG(active_ob_buffer).text_length; +/* {{{ SUCCESS|FAILURE php_output_end() + Finalizes the most recent output handler at pops it off the stack if the handler is removable */ +PHPAPI int _php_output_end(TSRMLS_D) +{ + if (php_output_stack_pop(0, 0 TSRMLS_CC)) { + return SUCCESS; } + return FAILURE; +} +/* }}} */ - if (OG(ob_nesting_level)==1) { /* end buffering */ - 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; - } - } +/* {{{ void php_output_end_all() + Finalizes all output handlers and ends output buffering without regard whether a handler is removable */ +PHPAPI void _php_output_end_all(TSRMLS_D) +{ + while (OG(active) && php_output_stack_pop(0, 1 TSRMLS_CC)); +} +/* }}} */ - to_be_destroyed_buffer = OG(active_ob_buffer).buffer; - /* FIXME: unicode support??? */ - to_be_destroyed_handler_name = OG(active_ob_buffer).handler_name.s; - if (OG(active_ob_buffer).internal_output_handler - && (final_buffer != OG(active_ob_buffer).internal_output_handler_buffer) - && (final_buffer != OG(active_ob_buffer).buffer)) { - to_be_destroyed_handled_output[0] = final_buffer; +/* {{{ SUCCESS|FAILURE php_output_discard() + Discards the most recent output handlers buffer and pops it off the stack if the handler is removable */ +PHPAPI int _php_output_discard(TSRMLS_D) +{ + if (php_output_stack_pop(1, 0 TSRMLS_CC)) { + return SUCCESS; } + return FAILURE; +} +/* }}} */ - if (!just_flush) { - if (OG(active_ob_buffer).internal_output_handler) { - to_be_destroyed_handled_output[1] = OG(active_ob_buffer).internal_output_handler_buffer; - } - } - if (OG(ob_nesting_level)>1) { /* restore previous buffer */ - zend_stack_top(&OG(ob_buffers), (void **) &prev_ob_buffer_p); - orig_ob_buffer = OG(active_ob_buffer); - OG(active_ob_buffer) = *prev_ob_buffer_p; - zend_stack_del_top(&OG(ob_buffers)); - if (!just_flush && OG(ob_nesting_level)==2) { /* destroy the stack */ - zend_stack_destroy(&OG(ob_buffers)); - } +/* {{{ void php_output_discard_all() + Discard all output handlers and buffers without regard whether a handler is removable */ +PHPAPI void _php_output_discard_all(TSRMLS_D) +{ + while (OG(active)) { + php_output_stack_pop(1, 1 TSRMLS_CC); } - OG(ob_nesting_level)--; +} +/* }}} */ - if (send_buffer) { - if (just_flush) { /* if flush is called prior to proper end, ensure presence of NUL */ - final_buffer[final_buffer_length] = '\0'; - } - OG(php_body_write)(final_buffer, final_buffer_length TSRMLS_CC); +/* {{{ int php_output_get_level() + Get output buffering level, ie. how many output handlers the stack contains */ +PHPAPI int _php_output_get_level(TSRMLS_D) +{ + return OG(active) ? zend_stack_count(&OG(handlers)) : 0; +} +/* }}} */ + +/* {{{ SUCCESS|FAILURE php_output_get_contents(zval *z) + Get the contents of the active output handlers buffer */ +PHPAPI int _php_output_get_contents(zval *p TSRMLS_DC) +{ + if (OG(active)) { + ZVAL_STRINGL(p, OG(active)->buffer.data, OG(active)->buffer.used, 1); + return SUCCESS; + } else { + ZVAL_NULL(p); + return FAILURE; } +} - if (just_flush) { /* we restored the previous ob, return to the current */ - if (prev_ob_buffer_p) { - zend_stack_push(&OG(ob_buffers), &OG(active_ob_buffer), sizeof(php_ob_buffer)); - OG(active_ob_buffer) = orig_ob_buffer; - } - OG(ob_nesting_level)++; +/* {{{ SUCCESS|FAILURE php_output_get_length(zval *z) + Get the length of the active output handlers buffer */ +PHPAPI int _php_output_get_length(zval *p TSRMLS_DC) +{ + if (OG(active)) { + ZVAL_LONG(p, OG(active)->buffer.used); + return SUCCESS; + } else { + ZVAL_NULL(p); + return FAILURE; } +} +/* }}} */ - if (alternate_buffer) { - zval_ptr_dtor(&alternate_buffer); +/* {{{ SUCCESS|FAILURE php_output_handler_start_default() + Start a "default output handler" */ +PHPAPI int _php_output_start_default(TSRMLS_D) +{ + php_output_handler *handler; + + handler = php_output_handler_create_internal(OG(default_output_handler_name), php_output_handler_default_func, 0, PHP_OUTPUT_HANDLER_STDFLAGS); + if (SUCCESS == php_output_handler_start(handler)) { + return SUCCESS; } + php_output_handler_free(&handler); + return FAILURE; +} +/* }}} */ - if (status & PHP_OUTPUT_HANDLER_END) { - efree(to_be_destroyed_handler_name); +/* {{{ SUCCESS|FAILURE php_output_handler_start_devnull() + Start a "null output handler" */ +PHPAPI int _php_output_start_devnull(TSRMLS_D) +{ + php_output_handler *handler; + + handler = php_output_handler_create_internal(OG(devnull_output_handler_name), php_output_handler_devnull_func, PHP_OUTPUT_HANDLER_DEFAULT_SIZE, 0); + if (SUCCESS == php_output_handler_start(handler)) { + return SUCCESS; } - if (!just_flush) { - efree(to_be_destroyed_buffer); + php_output_handler_free(&handler); + return FAILURE; +} +/* }}} */ + +/* {{{ SUCCESS|FAILURE php_output_start_user(zval *handler, size_t chunk_size, int flags) + Start a user level output handler */ +PHPAPI int _php_output_start_user(zval *output_handler, size_t chunk_size, int flags TSRMLS_DC) +{ + php_output_handler *handler; + + if (output_handler) { + handler = php_output_handler_create_user(output_handler, chunk_size, flags); } else { - OG(active_ob_buffer).text_length = 0; - OG(active_ob_buffer).status |= PHP_OUTPUT_HANDLER_START; - OG(php_body_write) = php_b_body_write; + handler = php_output_handler_create_internal(OG(default_output_handler_name), php_output_handler_default_func, chunk_size, flags); } - if (to_be_destroyed_handled_output[0]) { - efree(to_be_destroyed_handled_output[0]); - } - if (to_be_destroyed_handled_output[1]) { - efree(to_be_destroyed_handled_output[1]); + if (SUCCESS == php_output_handler_start(handler)) { + return SUCCESS; } + php_output_handler_free(&handler); + return FAILURE; } /* }}} */ -/* {{{ php_end_ob_buffers - * End output buffering (all buffers) */ -PHPAPI void php_end_ob_buffers(zend_bool send_buffer TSRMLS_DC) +/* {{{ SUCCESS|FAILURE php_output_start_internal(const char *name, php_output_handler_func_t handler, size_t chunk_size, int flags) + Start an internal output handler that does not have to maintain a non-global state */ +PHPAPI int _php_output_start_internal(zval *name, php_output_handler_func_t output_handler, size_t chunk_size, int flags TSRMLS_DC) { - while (OG(ob_nesting_level)!=0) { - php_end_ob_buffer(send_buffer, 0 TSRMLS_CC); + php_output_handler *handler; + + handler = php_output_handler_create_internal(name, php_output_handler_compat_func, chunk_size, flags); + php_output_handler_set_context(handler, output_handler, NULL); + if (SUCCESS == php_output_handler_start(handler)) { + return SUCCESS; } + php_output_handler_free(&handler); + return FAILURE; } /* }}} */ -/* {{{ php_start_implicit_flush - */ -PHPAPI void php_start_implicit_flush(TSRMLS_D) +/* {{{ php_output_handler *php_output_handler_create_user(zval *handler, size_t chunk_size, int flags) + Create a user level output handler */ +PHPAPI php_output_handler *_php_output_handler_create_user(zval *output_handler, size_t chunk_size, int flags TSRMLS_DC) { - OG(implicit_flush)=1; + zval *handler_name = NULL; + php_output_handler *handler = NULL; + php_output_handler_context_func_t *internal = NULL; + + switch (Z_TYPE_P(output_handler)) { + case IS_NULL: + break; + case IS_STRING: + case IS_UNICODE: + if (Z_UNILEN_P(output_handler) && (internal = php_output_handler_alias(output_handler))) { + return php_output_handler_create_internal(output_handler, *internal, chunk_size, flags); + } + default: + MAKE_STD_ZVAL(handler_name); + ZVAL_NULL(handler_name); + if (zend_is_callable(output_handler, 0, handler_name)) { + handler = php_output_handler_init(handler_name, chunk_size, (flags & ~0xf) | PHP_OUTPUT_HANDLER_USER); + ZVAL_ADDREF(output_handler); + handler->user = output_handler; + } + zval_ptr_dtor(&handler_name); + return handler; + } + + return php_output_handler_create_internal(OG(default_output_handler_name), php_output_handler_default_func, chunk_size, flags); } /* }}} */ -/* {{{ php_end_implicit_flush - */ -PHPAPI void php_end_implicit_flush(TSRMLS_D) +/* {{{ php_output_handler *php_output_handler_create_internal(const char *name, php_output_handler_context_func_t handler, size_t chunk_size, int flags) + Create an internal output handler that can maintain a non-global state */ +PHPAPI php_output_handler *_php_output_handler_create_internal(zval *name, php_output_handler_context_func_t output_handler, size_t chunk_size, int flags TSRMLS_DC) { - OG(implicit_flush)=0; + php_output_handler *handler; + + handler = php_output_handler_init(name, chunk_size, (flags & ~0xf) | PHP_OUTPUT_HANDLER_INTERNAL); + handler->internal = output_handler; + + return handler; } -/* }}} */ -/* {{{ php_ob_set_internal_handler - */ -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) +/* {{{ void php_output_handler_set_context(php_output_handler *handler, void *opaq, void (*dtor)(void* TSRMLS_DC)) + Set the context/state of an output handler. Calls the dtor of the previous context if there is one */ +PHPAPI void _php_output_handler_set_context(php_output_handler *handler, void *opaq, void (*dtor)(void* TSRMLS_DC) TSRMLS_DC) { - /* FIXME: Unicode support??? */ - if (OG(ob_nesting_level)==0 || OG(active_ob_buffer).internal_output_handler || strcmp(OG(active_ob_buffer).handler_name.s, OB_DEFAULT_HANDLER_NAME)) { - php_start_ob_buffer(NULL, buffer_size, erase TSRMLS_CC); + if (handler->dtor && handler->opaq) { + handler->dtor(handler->opaq TSRMLS_CC); } + handler->dtor = dtor; + handler->opaq = opaq; +} +/* }}} */ - OG(active_ob_buffer).internal_output_handler = internal_output_handler; - OG(active_ob_buffer).internal_output_handler_buffer = (char *) emalloc(buffer_size); - OG(active_ob_buffer).internal_output_handler_buffer_size = buffer_size; - if (OG(active_ob_buffer).handler_name.s) { - efree(OG(active_ob_buffer).handler_name.s); +/* {{{ SUCCESS|FAILURE php_output_handler_start(php_output_handler *handler) + Starts the set up output handler and pushes it on top of the stack. Checks for any conflicts regarding the output handler to start */ +PHPAPI int _php_output_handler_start(php_output_handler *handler TSRMLS_DC) +{ + HashTable *rconflicts; + php_output_handler_conflict_check_t *conflict; + + if (php_output_lock_error(PHP_OUTPUT_HANDLER_START TSRMLS_CC) || !handler) { + return FAILURE; } - OG(active_ob_buffer).handler_name.s = estrdup(handler_name); - OG(active_ob_buffer).erase = erase; + if (SUCCESS == zend_u_hash_find(&php_output_handler_conflicts, Z_TYPE_P(handler->name), Z_UNIVAL_P(handler->name), Z_UNILEN_P(handler->name), (void *) &conflict)) { + if (SUCCESS != (*conflict)(handler->name TSRMLS_CC)) { + return FAILURE; + } + } + if (SUCCESS == zend_u_hash_find(&php_output_handler_reverse_conflicts, Z_TYPE_P(handler->name), Z_UNIVAL_P(handler->name), Z_UNILEN_P(handler->name), (void *) &rconflicts)) { + for ( zend_hash_internal_pointer_reset(rconflicts); + zend_hash_get_current_data(rconflicts, (void *) &conflict) == SUCCESS; + zend_hash_move_forward(rconflicts)) { + if (SUCCESS != (*conflict)(handler->name TSRMLS_CC)) { + return FAILURE; + } + } + } + /* zend_stack_push never returns SUCCESS but FAILURE or stack level */ + if (FAILURE == (handler->level = zend_stack_push(&OG(handlers), &handler, sizeof(php_output_handler *)))) { + return FAILURE; + } + OG(active) = handler; + return SUCCESS; } /* }}} */ -/* - * Output buffering - implementation - */ - -/* {{{ php_ob_allocate - */ -static inline void php_ob_allocate(uint text_length TSRMLS_DC) +/* {{{ int php_output_handler_started(const char *name) + Check whether a certain output handler is in use */ +PHPAPI int _php_output_handler_started(zval *name TSRMLS_DC) { - uint new_len = OG(active_ob_buffer).text_length + text_length; - - if (OG(active_ob_buffer).size < new_len) { - uint buf_size = OG(active_ob_buffer).size; - while (buf_size <= new_len) { - buf_size += OG(active_ob_buffer).block_size; + php_output_handler **handlers; + int i, count = php_output_get_level(); + + if (count) { + handlers = *(php_output_handler ***) zend_stack_base(&OG(handlers)); + + for (i = 0; i < count; ++i) { + if (!zend_binary_zval_strcmp(handlers[i]->name, name)) { + return 1; + } } - - OG(active_ob_buffer).buffer = (char *) erealloc(OG(active_ob_buffer).buffer, buf_size+1); - OG(active_ob_buffer).size = buf_size; } - OG(active_ob_buffer).text_length = new_len; + + return 0; } /* }}} */ -/* {{{ php_ob_init_conflict - * Returns 1 if handler_set is already used and generates error message - */ -PHPAPI int php_ob_init_conflict(char *handler_new, char *handler_set TSRMLS_DC) +/* {{{ int php_output_handler_conflict(const char *handler_new, const char *handler_old) + Check whether a certain handler is in use and issue a warning that the new handler would conflict with the already used one */ +PHPAPI int _php_output_handler_conflict(zval *handler_new, zval *handler_set TSRMLS_DC) { - if (php_ob_handler_used(handler_set TSRMLS_CC)) { - php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler '%s' conflicts with '%s'", handler_new, handler_set); + if (php_output_handler_started(handler_set)) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler '%v' conflicts with '%v'", Z_UNIVAL_P(handler_new), Z_UNIVAL_P(handler_set)); return 1; } return 0; } /* }}} */ -/* {{{ php_ob_init_named - */ -static int php_ob_init_named(uint initial_size, uint block_size, zend_uchar type, zstr handler_name, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC) +/* {{{ SUCCESS|FAILURE php_output_handler_conflict_register(const char name[], php_output_handler_conflict_check_t check_func) + Register a conflict checking function on MINIT */ +PHPAPI int _php_output_handler_conflict_register(zval *name, php_output_handler_conflict_check_t check_func TSRMLS_DC) { - int handler_len; + if (!EG(current_module)) { + zend_error(E_ERROR, "Cannot register an output handler conflict outside of MINIT"); + return FAILURE; + } + return zend_u_hash_update(&php_output_handler_conflicts, Z_TYPE_P(name), Z_UNIVAL_P(name), Z_UNILEN_P(name), &check_func, sizeof(php_output_handler_conflict_check_t *), NULL); +} +/* }}} */ - if (output_handler && !zend_is_callable(output_handler, 0, NULL)) { +/* {{{ SUCCESS|FAILURE php_output_handler_reverse_conflict_register(const char name[], php_output_handler_conflict_check_t check_func) + Register a reverse conflict checking function on MINIT */ +PHPAPI int _php_output_handler_reverse_conflict_register(zval *name, php_output_handler_conflict_check_t check_func TSRMLS_DC) +{ + HashTable rev, *rev_ptr = NULL; + + if (!EG(current_module)) { + zend_error(E_ERROR, "Cannot register a reverse output handler conflict outside of MINIT"); return FAILURE; } - if (type == IS_UNICODE) { - handler_len = u_strlen(handler_name.u); + if (SUCCESS == zend_u_hash_find(&php_output_handler_reverse_conflicts, Z_TYPE_P(name), Z_UNIVAL_P(name), Z_UNILEN_P(name), (void *) &rev_ptr)) { + return zend_hash_next_index_insert(rev_ptr, &check_func, sizeof(php_output_handler_conflict_check_t *), NULL); } else { - handler_len = strlen(handler_name.s); - } - if (OG(ob_nesting_level)>0) { -#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB) - if ((handler_len == sizeof("ob_gzhandler")-1) && - (ZEND_U_EQUAL(type, handler_name, handler_len, "ob_gzhandler", sizeof("ob_gzhandler"))) && - php_ob_gzhandler_check(TSRMLS_C)) { + zend_hash_init(&rev, 1, NULL, NULL, 1); + if (SUCCESS != zend_hash_next_index_insert(&rev, &check_func, sizeof(php_output_handler_conflict_check_t *), NULL)) { + zend_hash_destroy(&rev); return FAILURE; } -#endif - if (OG(ob_nesting_level)==1) { /* initialize stack */ - zend_stack_init(&OG(ob_buffers)); + if (SUCCESS != zend_u_hash_update(&php_output_handler_reverse_conflicts, Z_TYPE_P(name), Z_UNIVAL_P(name), Z_UNILEN_P(name), &rev, sizeof(HashTable), NULL)) { + zend_hash_destroy(&rev); + return FAILURE; } - zend_stack_push(&OG(ob_buffers), &OG(active_ob_buffer), sizeof(php_ob_buffer)); + return SUCCESS; } - OG(ob_nesting_level)++; - OG(active_ob_buffer).block_size = block_size; - OG(active_ob_buffer).size = initial_size; - OG(active_ob_buffer).buffer = (char *) emalloc(initial_size+1); - OG(active_ob_buffer).text_length = 0; - OG(active_ob_buffer).output_handler = output_handler; - OG(active_ob_buffer).chunk_size = chunk_size; - OG(active_ob_buffer).status = 0; - OG(active_ob_buffer).internal_output_handler = NULL; - if (type == IS_UNICODE) { - /* FIXME: Unicode support??? */ - OG(active_ob_buffer).handler_name.u = eustrdup((handler_name.u && handler_name.u[0])?handler_name.u:(UChar*)OB_DEFAULT_HANDLER_NAME); - } else { - OG(active_ob_buffer).handler_name.s = estrdup((handler_name.s && handler_name.s[0])?handler_name.s:OB_DEFAULT_HANDLER_NAME); - } - 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, int len TSRMLS_DC) +/* {{{ php_output_handler_context_func_t php_output_handler_alias(const char[] name) + Get an internal output handler for a user handler if it exists */ +PHPAPI php_output_handler_context_func_t *_php_output_handler_alias(zval *name TSRMLS_DC) { - zval *output_handler; - - ALLOC_INIT_ZVAL(output_handler); - Z_STRLEN_P(output_handler) = len; - Z_STRVAL_P(output_handler) = estrndup(handler_name, len); - Z_TYPE_P(output_handler) = IS_STRING; - return output_handler; + php_output_handler_context_func_t *func = NULL; + + zend_u_hash_find(&php_output_handler_aliases, Z_TYPE_P(name), Z_UNIVAL_P(name), Z_UNILEN_P(name), (void *) &func); + return func; } /* }}} */ -/* {{{ php_ob_handler_from_unicode - * Create zval output handler from unicode - */ -static zval* php_ob_handler_from_unicode(const UChar *handler_name, int len TSRMLS_DC) +/* {{{ SUCCESS|FAILURE php_output_handler_alias_register(const char[] name, php_output_handler_context_func_t func) + Registers an internal output handler as alias for a user handler */ +PHPAPI int _php_output_handler_alias_register_ex(zval *name, php_output_handler_context_func_t func TSRMLS_DC) { - zval *output_handler; - - ALLOC_INIT_ZVAL(output_handler); - Z_USTRLEN_P(output_handler) = len; - Z_USTRVAL_P(output_handler) = eustrndup(handler_name, len); - Z_TYPE_P(output_handler) = IS_UNICODE; - return output_handler; + if (!EG(current_module)) { + zend_error(E_ERROR, "Cannot register an output handler alias outside of MINIT"); + return FAILURE; + } + return zend_u_hash_update(&php_output_handler_aliases, Z_TYPE_P(name), Z_UNIVAL_P(name), Z_UNILEN_P(name), &func, sizeof(php_output_handler_context_func_t *), NULL); } /* }}} */ -/* {{{ 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) +/* {{{ SUCCESS|FAILURE php_output_handler_hook(int type, void *arg) + Output handler hook for output handler functions to check/modify the current handlers abilities */ +PHPAPI int _php_output_handler_hook(int type, void *arg TSRMLS_DC) { - int result = FAILURE, handler_len, len; - HashPosition pos; - zval **tmp; - zval *handler_zval; - - if (output_handler && output_handler->type == IS_STRING) { - zstr next_handler_name; - zstr handler_name = Z_UNIVAL_P(output_handler); - handler_len = Z_UNILEN_P(output_handler); - - result = SUCCESS; - if (handler_len && handler_name.s[0] != '\0') { - while ((next_handler_name.s=strchr(handler_name.s, ',')) != NULL) { - len = next_handler_name.s-handler_name.s; - next_handler_name.s = estrndup(handler_name.s, len); - handler_zval = php_ob_handler_from_string(next_handler_name.s, len TSRMLS_CC); - result = php_ob_init_named(initial_size, block_size, IS_STRING, next_handler_name, handler_zval, chunk_size, erase TSRMLS_CC); - if (result != SUCCESS) { - zval_dtor(handler_zval); - FREE_ZVAL(handler_zval); - } - handler_name.s += len+1; - handler_len -= len+1; - efree(next_handler_name.s); - } - } - if (result == SUCCESS) { - handler_zval = php_ob_handler_from_string(handler_name.s, handler_len TSRMLS_CC); - result = php_ob_init_named(initial_size, block_size, IS_STRING, handler_name, handler_zval, chunk_size, erase TSRMLS_CC); - if (result != SUCCESS) { - zval_dtor(handler_zval); - FREE_ZVAL(handler_zval); - } - } - } else if (output_handler && output_handler->type == IS_UNICODE) { - zstr next_handler_name; - zstr handler_name = Z_UNIVAL_P(output_handler); - handler_len = Z_UNILEN_P(output_handler); - - result = SUCCESS; - if (handler_len && handler_name.u[0] != 0) { - while ((next_handler_name.u=u_strchr(handler_name.u, ',')) != NULL) { - len = next_handler_name.u-handler_name.u; - next_handler_name.u = eustrndup(handler_name.u, len); - handler_zval = php_ob_handler_from_unicode(next_handler_name.u, len TSRMLS_CC); - result = php_ob_init_named(initial_size, block_size, IS_UNICODE, next_handler_name, handler_zval, chunk_size, erase TSRMLS_CC); - if (result != SUCCESS) { - zval_dtor(handler_zval); - FREE_ZVAL(handler_zval); - } - handler_name.u += len+1; - handler_len -= len+1; - efree(next_handler_name.u); - } - } - if (result == SUCCESS) { - handler_zval = php_ob_handler_from_unicode(handler_name.u, handler_len TSRMLS_CC); - result = php_ob_init_named(initial_size, block_size, IS_UNICODE, handler_name, handler_zval, chunk_size, erase TSRMLS_CC); - if (result != SUCCESS) { - zval_dtor(handler_zval); - FREE_ZVAL(handler_zval); - } - } - } else if (output_handler && output_handler->type == IS_ARRAY) { - zval handler_name; - - /* do we have array(object,method) */ - if (zend_is_callable(output_handler, 0, &handler_name)) { - SEPARATE_ZVAL(&output_handler); - output_handler->refcount++; - result = php_ob_init_named(initial_size, block_size, Z_TYPE(handler_name), Z_UNIVAL(handler_name), output_handler, chunk_size, erase TSRMLS_CC); - zval_dtor(&handler_name); - } else { - zval_dtor(&handler_name); - /* init all array elements recursively */ - 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); - if (result == FAILURE) { - break; - } - zend_hash_move_forward_ex(Z_ARRVAL_P(output_handler), &pos); - } + if (OG(running)) { + switch (type) { + case PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ: + *(void ***) arg = &OG(running)->opaq; + return SUCCESS; + case PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS: + *(int *) arg = OG(running)->flags; + return SUCCESS; + case PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE: + OG(running)->flags &= ~PHP_OUTPUT_HANDLER_STDFLAGS; + return SUCCESS; + case PHP_OUTPUT_HANDLER_HOOK_DISABLE: + OG(running)->flags |= PHP_OUTPUT_HANDLER_DISABLED; + return SUCCESS; } - } else if (output_handler && output_handler->type == IS_OBJECT) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "No method name given: use ob_start(array($object,'method')) to specify instance $object and the name of a method of class %v to use as output handler", Z_OBJCE_P(output_handler)->name); - result = FAILURE; - } else { - zstr z_name; - - z_name.s = OB_DEFAULT_HANDLER_NAME; - result = php_ob_init_named(initial_size, block_size, IS_STRING, z_name, NULL, chunk_size, erase TSRMLS_CC); } - return result; + return FAILURE; } /* }}} */ -/* {{{ php_ob_list_each - */ -static int php_ob_list_each(php_ob_buffer *ob_buffer, zval *ob_handler_array) +/* {{{ void php_output_handler_dtor(php_output_handler *handler) + Destroy an output handler */ +PHPAPI void _php_output_handler_dtor(php_output_handler *handler TSRMLS_DC) { - TSRMLS_FETCH(); - - add_next_index_text(ob_handler_array, ob_buffer->handler_name, 1); - return 0; + zval_ptr_dtor(&handler->name); + STR_FREE(handler->buffer.data); + if (handler->flags & PHP_OUTPUT_HANDLER_USER) { + zval_ptr_dtor(&handler->user); + } + if (handler->dtor && handler->opaq) { + handler->dtor(handler->opaq TSRMLS_CC); + } + memset(handler, 0, sizeof(*handler)); } /* }}} */ -/* {{{ proto false|array ob_list_handlers() - * List all output_buffers in an array - */ -PHP_FUNCTION(ob_list_handlers) +/* {{{ void php_output_handler_free(php_output_handler **handler) + Destroy and free an output handler */ +PHPAPI void _php_output_handler_free(php_output_handler **h TSRMLS_DC) { - if (ZEND_NUM_ARGS()!=0) { - ZEND_WRONG_PARAM_COUNT(); - RETURN_FALSE; + if (*h) { + php_output_handler_dtor(*h); + efree(*h); + *h = NULL; } +} +/* }}} */ - array_init(return_value); - if (OG(ob_nesting_level)) { - if (OG(ob_nesting_level)>1) { - zend_stack_apply_with_argument(&OG(ob_buffers), ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *element, void *)) php_ob_list_each, return_value); - } - php_ob_list_each(&OG(active_ob_buffer), return_value); +/* void php_output_set_implicit_flush(int enabled) + Enable or disable implicit flush */ +PHPAPI void _php_output_set_implicit_flush(int flush TSRMLS_DC) +{ + if (flush) { + OG(flags) |= PHP_OUTPUT_IMPLICITFLUSH; + } else { + OG(flags) &= ~PHP_OUTPUT_IMPLICITFLUSH; } } /* }}} */ -/* {{{ php_ob_used_each - * Sets handler_name to NULL is found - */ -static int php_ob_handler_used_each(php_ob_buffer *ob_buffer, char **handler_name) +/* {{{ char *php_output_get_start_filename() + Get the file name where output has started */ +PHPAPI char *_php_output_get_start_filename(TSRMLS_D) { - /* FIXME: Unicode support??? */ - if (!strcmp(ob_buffer->handler_name.s, *handler_name)) { - *handler_name = NULL; + return OG(output_start_filename); +} +/* }}} */ + +/* {{{ int php_output_get_start_lineno() + Get the line number where output has started */ +PHPAPI int _php_output_get_start_lineno(TSRMLS_D) +{ + return OG(output_start_lineno); +} +/* }}} */ + +/* {{{ static int php_output_lock_error(int op TSRMLS_DC) + Checks whether an unallowed operation is attempted from within the output handler and issues a fatal error */ +static inline int php_output_lock_error(int op TSRMLS_DC) +{ + /* if there's no ob active, ob has been stopped */ + if (op && OG(active) && OG(running)) { + /* fatal error */ + php_output_deactivate(); + php_error_docref("ref.outcontrol" TSRMLS_CC, E_ERROR, "Cannot use output buffering in output buffering display handlers"); return 1; } return 0; } /* }}} */ -/* {{{ php_ob_used - * returns 1 if given handler_name is used as output_handler - */ -PHPAPI int php_ob_handler_used(char *handler_name TSRMLS_DC) +/* {{{ static php_output_context *php_output_context_init(php_output_context *context, int op TSRMLS_DC) + Initialize a new output context */ +static inline php_output_context *php_output_context_init(php_output_context *context, int op TSRMLS_DC) { - /* FIXME: Unicode support??? */ - char *tmp = handler_name; - - if (OG(ob_nesting_level)) { - if (!strcmp(OG(active_ob_buffer).handler_name.s, handler_name)) { - return 1; - } - if (OG(ob_nesting_level)>1) { - zend_stack_apply_with_argument(&OG(ob_buffers), ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *element, void *)) php_ob_handler_used_each, &tmp); - } + if (!context) { + context = emalloc(sizeof(php_output_context)); } - return tmp ? 0 : 1; + + memset(context, 0, sizeof(php_output_context)); + TSRMLS_SET_CTX(context->tsrm_ls); + context->op = op; + + return context; } /* }}} */ -/* {{{ php_ob_append - */ -static inline void php_ob_append(const char *text, uint text_length TSRMLS_DC) +/* {{{ static void php_output_context_reset(php_output_context *context) + Reset an output context */ +static inline void php_output_context_reset(php_output_context *context) { - char *target; - int original_ob_text_length; - - original_ob_text_length=OG(active_ob_buffer).text_length; - - php_ob_allocate(text_length TSRMLS_CC); - target = OG(active_ob_buffer).buffer+original_ob_text_length; - memcpy(target, text, text_length); - target[text_length]=0; + int op = context->op; + php_output_context_dtor(context); + memset(context, 0, sizeof(php_output_context)); + context->op = op; +} +/* }}} */ - /* If implicit_flush is On or chunked buffering, send contents to next buffer and return. */ - if (OG(active_ob_buffer).chunk_size - && OG(active_ob_buffer).text_length >= OG(active_ob_buffer).chunk_size) { - - php_end_ob_buffer(1, 1 TSRMLS_CC); - return; +/* {{{ static void php_output_context_swap(php_output_context *context) + Swap output contexts buffers */ +static inline void php_output_context_swap(php_output_context *context) +{ + if (context->in.free && context->in.data) { + efree(context->in.data); } + context->in.data = context->out.data; + context->in.used = context->out.used; + context->in.free = context->out.free; + context->in.size = context->out.size; + context->out.data = NULL; + context->out.used = 0; + context->out.size = 0; } /* }}} */ -#if 0 -static inline void php_ob_prepend(const char *text, uint text_length) +/* {{{ static void php_output_context_pass(php_output_context *context) + Pass input to output buffer */ +static inline void php_output_context_pass(php_output_context *context) { - char *p, *start; - TSRMLS_FETCH(); - - php_ob_allocate(text_length TSRMLS_CC); - - /* php_ob_allocate() may change OG(ob_buffer), so we can't initialize p&start earlier */ - p = OG(ob_buffer)+OG(ob_text_length); - start = OG(ob_buffer); + context->out.data = context->in.data; + context->out.used = context->in.used; + context->out.size = context->in.size; + context->out.free = context->in.free; + context->in.data = NULL; + context->in.used = 0; + context->in.size = 0; +} +/* }}} */ - while (--p>=start) { - p[text_length] = *p; +/* {{{ static void php_output_context_dtor(php_output_context *context) + Destroy the contents of an output context */ +static inline void php_output_context_dtor(php_output_context *context) +{ + if (context->in.free && context->in.data) { + efree(context->in.data); + } + if (context->out.free && context->out.data) { + efree(context->out.data); } - memcpy(OG(ob_buffer), text, text_length); - OG(ob_buffer)[OG(active_ob_buffer).text_length]=0; } -#endif +/* }}} */ +/* {{{ static php_output_handler *php_output_handler_init(zval *name, size_t chunk_size, int flags) + Allocates and initializes a php_output_handler structure */ +static inline php_output_handler *php_output_handler_init(zval *name, size_t chunk_size, int flags) +{ + php_output_handler *handler; + + handler = ecalloc(1, sizeof(php_output_handler)); + ZVAL_ADDREF(name); + handler->name = name; + handler->size = chunk_size; + handler->flags = flags; + handler->buffer.size = PHP_OUTPUT_HANDLER_INITBUF_SIZE(chunk_size); + handler->buffer.data = emalloc(handler->buffer.size); + + return handler; +} +/* }}} */ -/* {{{ php_ob_get_buffer - * Return the current output buffer */ -PHPAPI int php_ob_get_buffer(zval *p TSRMLS_DC) +/* {{{ static int php_output_handler_appen(php_output_handler *handler, const php_output_buffer *buf TSRMLS_DC) + Appends input to the output handlers buffer and indicates whether the buffer does not have to be processed by the output handler */ +static inline int php_output_handler_append(php_output_handler *handler, const php_output_buffer *buf TSRMLS_DC) { - if (OG(ob_nesting_level)==0) { - return FAILURE; + /* store it away */ + if ((handler->buffer.size - handler->buffer.used) <= buf->used) { + size_t grow_int = PHP_OUTPUT_HANDLER_INITBUF_SIZE(handler->size); + size_t grow_buf = PHP_OUTPUT_HANDLER_INITBUF_SIZE(buf->used + 1 - (handler->buffer.size - handler->buffer.used)); + size_t grow_max = MAX(grow_int, grow_buf); + + handler->buffer.data = erealloc(handler->buffer.data, handler->buffer.size += grow_max); } - ZVAL_U_STRINGL(ZEND_U_CONVERTER(UG(output_encoding_conv)), p, OG(active_ob_buffer).buffer, OG(active_ob_buffer).text_length, 1); - return SUCCESS; + memcpy(handler->buffer.data + handler->buffer.used, buf->data, buf->used); + handler->buffer.used += buf->used; + handler->buffer.data[handler->buffer.used] = '\0'; + + /* chunked buffering */ + if (handler->size && (handler->buffer.used >= handler->size)) { + /* store away errors and/or any intermediate output */ + return OG(running) ? 1 : 0; + } + return 1; } /* }}} */ -/* {{{ php_ob_get_length - * Return the size of the current output buffer */ -PHPAPI int php_ob_get_length(zval *p TSRMLS_DC) +/* {{{ static PHP_OUTPUT_HANDLER_(SUCCESS|FAILURE|NO_DATA) php_output_handler_op(php_output_handler *handler, php_output_context *context) + Output handler operation dispatcher, applying context op to the php_output_handler handler */ +static inline int php_output_handler_op(php_output_handler *handler, php_output_context *context) { - if (OG(ob_nesting_level) == 0) { - return FAILURE; + int status, op; + PHP_OUTPUT_TSRMLS(context); + +#if PHP_OUTPUT_DEBUG + fprintf(stderr, ">>> op(%d, " + "handler=%p, " + "name=%s, " + "flags=%d, " + "buffer.data=%s, " + "buffer.used=%lu, " + "buffer.size=%lu, " + "in.data=%s, " + "in.used=%lu)\n", + context->op, + handler, + handler->name, + handler->flags, + handler->buffer.data, + handler->buffer.used, + handler->buffer.size, + context->in.data, + context->in.used + ); +#endif + + op = context->op; + if (php_output_lock_error(op TSRMLS_CC)) { + /* fatal error */ + return PHP_OUTPUT_HANDLER_FAILURE; } - ZVAL_LONG(p, OG(active_ob_buffer).text_length); - return SUCCESS; + + /* storable? */ + if (php_output_handler_append(handler, &context->in TSRMLS_CC) && !op) { + status = PHP_OUTPUT_HANDLER_NO_DATA; + } else { + /* need to start? */ + if (!(handler->flags & PHP_OUTPUT_HANDLER_STARTED)) { + handler->flags |= PHP_OUTPUT_HANDLER_STARTED; + op |= PHP_OUTPUT_HANDLER_START; + } + + OG(running) = handler; + if (handler->flags & PHP_OUTPUT_HANDLER_USER) { + zval *retval = NULL, **params[2], *flags, *input; + + MAKE_STD_ZVAL(input); + ZVAL_STRINGL(input, handler->buffer.data, handler->buffer.used, 1); + MAKE_STD_ZVAL(flags); + ZVAL_LONG(flags, (long) op); + params[0] = &input; + params[1] = &flags; + + if ( (SUCCESS == call_user_function_ex(CG(function_table), NULL, handler->user, &retval, 2, params, 1, NULL TSRMLS_CC)) && + retval && (Z_TYPE_P(retval) != IS_NULL) && (Z_TYPE_P(retval) != IS_BOOL || Z_BVAL_P(retval))) { + /* user handler may have returned TRUE */ + status = PHP_OUTPUT_HANDLER_NO_DATA; + if (Z_TYPE_P(retval) != IS_BOOL) { + convert_to_string_ex(&retval); + if (Z_STRLEN_P(retval)) { + context->out.data = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval)); + context->out.used = Z_STRLEN_P(retval); + context->out.free = 1; + status = PHP_OUTPUT_HANDLER_SUCCESS; + } + } + } else { + /* call failed, pass internal buffer along */ + status = PHP_OUTPUT_HANDLER_FAILURE; + } + if (retval) { + zval_ptr_dtor(&retval); + } + zval_ptr_dtor(&input); + zval_ptr_dtor(&flags); + } else { + + context->in.data = handler->buffer.data; + context->in.used = handler->buffer.used; + context->in.free = 0; + + if (SUCCESS == handler->internal(&handler->opaq, context)) { + if (context->out.used) { + status = PHP_OUTPUT_HANDLER_SUCCESS; + } else { + status = PHP_OUTPUT_HANDLER_NO_DATA; + } + } else { + status = PHP_OUTPUT_HANDLER_FAILURE; + } + } + OG(running) = NULL; + } + + switch (status) { + case PHP_OUTPUT_HANDLER_FAILURE: + /* disable this handler */ + handler->flags |= PHP_OUTPUT_HANDLER_DISABLED; + /* returns handlers buffer */ + context->out.data = handler->buffer.data; + context->out.used = handler->buffer.used; + context->out.free = 1; + handler->buffer.data = NULL; + handler->buffer.used = 0; + handler->buffer.size = 0; + break; + case PHP_OUTPUT_HANDLER_SUCCESS: + /* no more buffered data */ + handler->buffer.used = 0; + break; + case PHP_OUTPUT_HANDLER_NO_DATA: + /* handler ate all */ + php_output_context_reset(context); + break; + } + + return status; } /* }}} */ -/* - * Wrapper functions - implementation - */ +/* {{{ static void php_output_op(int op, const char *str, size_t len TSRMLS_DC) + Output op dispatcher, passes input and output handlers output through the output handler stack until it gets written to the SAPI */ +static inline void php_output_op(int op, const char *str, size_t len TSRMLS_DC) +{ + php_output_context context; + php_output_handler **active; + int obh_cnt; + + if (php_output_lock_error(op TSRMLS_CC)) { + return; + } + + php_output_context_init(&context, op TSRMLS_CC); + + /* + * broken up for better performance: + * - apply op to the one active handler; note that OG(active) might be popped off the stack on a flush + * - or apply op to the handler stack + */ + if (OG(active) && (obh_cnt = zend_stack_count(&OG(handlers)))) { + context.in.data = (char *) str; + context.in.used = len; + + if (obh_cnt > 1) { + zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_TOPDOWN, php_output_stack_apply_op, &context); + } else if ((SUCCESS == zend_stack_top(&OG(handlers), (void *) &active)) && (!((*active)->flags & PHP_OUTPUT_HANDLER_DISABLED))) { + php_output_handler_op(*active, &context); + } else { + php_output_context_pass(&context); + } + } else { + context.out.data = (char *) str; + context.out.used = len; + } + + if (context.out.data) { + if (context.out.used) { +#if PHP_OUTPUT_DEBUG + fprintf(stderr, "::: sapi_write('%s', %lu)\n", context.out.data, context.out.used); +#endif + if (!SG(headers_sent) && php_header(TSRMLS_C)) { + if (zend_is_compiling(TSRMLS_C)) { + OG(output_start_filename) = zend_get_compiled_filename(TSRMLS_C); + OG(output_start_lineno) = zend_get_compiled_lineno(TSRMLS_C); + } else if (zend_is_executing(TSRMLS_C)) { + OG(output_start_filename) = zend_get_executed_filename(TSRMLS_C); + OG(output_start_lineno) = zend_get_executed_lineno(TSRMLS_C); + } +#if PHP_OUTPUT_DEBUG + fprintf(stderr, "!!! output started at: %s (%d)\n", OG(output_start_filename), OG(output_start_lineno)); +#endif + } + sapi_module.ub_write(context.out.data, context.out.used TSRMLS_CC); + if (OG(flags) & PHP_OUTPUT_IMPLICITFLUSH) { + sapi_flush(TSRMLS_C); + } + } + } + php_output_context_dtor(&context); +} +/* }}} */ -/* buffered output function */ -static int php_b_body_write(const char *str, uint str_length TSRMLS_DC) +/* {{{ static int php_output_stack_apply_op(void *h, void *c) + Operation callback for the stack apply function */ +static int php_output_stack_apply_op(void *h, void *c) { - php_ob_append(str, str_length TSRMLS_CC); - return str_length; + int status = PHP_OUTPUT_HANDLER_FAILURE, was_disabled; + php_output_handler *handler = *(php_output_handler **) h; + php_output_context *context = (php_output_context *) c; + + if (!(was_disabled = (handler->flags & PHP_OUTPUT_HANDLER_DISABLED))) { + status = php_output_handler_op(handler, context); + } + + /* + * handler ate all => break + * handler returned data or failed resp. is disabled => continue + */ + switch (status) { + case PHP_OUTPUT_HANDLER_NO_DATA: + return 1; + + case PHP_OUTPUT_HANDLER_SUCCESS: + /* swap contexts buffers, unless this is the last handler in the stack */ + if (handler->level) { + php_output_context_swap(context); + } + return 0; + + case PHP_OUTPUT_HANDLER_FAILURE: + default: + if (was_disabled) { + /* pass input along, if it's the last handler in the stack */ + if (!handler->level) { + php_output_context_pass(context); + } + } else { + /* swap buffers, unless this is the last handler */ + if (handler->level) { + php_output_context_swap(context); + } + } + return 0; + } } +/* }}} */ -/* {{{ php_ub_body_write_no_header - */ -PHPAPI int php_ub_body_write_no_header(const char *str, uint str_length TSRMLS_DC) +/* {{{ static int php_output_stack_apply_clean(void *h, void *c) + Clean callback for the stack apply function */ +static int php_output_stack_apply_clean(void *h, void *c) { - int result; + php_output_handler *handler = *(php_output_handler **) h; + php_output_context *context = (php_output_context *) c; + + handler->buffer.used = 0; + php_output_handler_op(handler, context); + php_output_context_reset(context); + return 0; +} +/* }}} */ - if (OG(disable_output)) { - return 0; - } +/* {{{ static int php_output_stack_apply_list(void *h, void *z) + List callback for the stack apply function */ +static int php_output_stack_apply_list(void *h, void *z) +{ + php_output_handler *handler = *(php_output_handler **) h; + zval *array = (zval *) z; + + if (Z_TYPE_P(handler->name) == IS_UNICODE) { + add_next_index_unicodel(array, Z_USTRVAL_P(handler->name), Z_USTRLEN_P(handler->name), 1); + } else { + add_next_index_stringl(array, Z_STRVAL_P(handler->name), Z_STRLEN_P(handler->name), 1); + } + return 0; +} +/* }}} */ - result = OG(php_header_write)(str, str_length TSRMLS_CC); +/* {{{ static int php_output_stack_apply_status(void *h, void *z) + Status callback for the stack apply function */ +static int php_output_stack_apply_status(void *h, void *z) +{ + php_output_handler *handler = *(php_output_handler **) h; + zval *array = (zval *) z; + + add_next_index_zval(array, php_output_handler_status(handler, NULL)); + + return 0; +} +/* }}} */ - if (OG(implicit_flush)) { - sapi_flush(TSRMLS_C); +/* {{{ static zval *php_output_handler_status(php_output_handler *handler, zval *entry) + Returns an array with the status of the output handler */ +static inline zval *php_output_handler_status(php_output_handler *handler, zval *entry) +{ + if (!entry) { + MAKE_STD_ZVAL(entry); + array_init(entry); } - - return result; + + if (Z_TYPE_P(handler->name) == IS_UNICODE) { + add_assoc_unicodel(entry, "name", Z_USTRVAL_P(handler->name), Z_USTRLEN_P(handler->name), 1); + } else { + add_assoc_stringl(entry, "name", Z_STRVAL_P(handler->name), Z_STRLEN_P(handler->name), 1); + } + add_assoc_long(entry, "type", (long) (handler->flags & 0xf)); + add_assoc_long(entry, "flags", (long) handler->flags); + add_assoc_long(entry, "level", (long) handler->level); + add_assoc_long(entry, "chunk_size", (long) handler->size); + add_assoc_long(entry, "buffer_size", (long) handler->buffer.size); + add_assoc_long(entry, "buffer_used", (long) handler->buffer.used); + + return entry; } /* }}} */ -/* {{{ php_ub_body_write - */ -PHPAPI int php_ub_body_write(const char *str, uint str_length TSRMLS_DC) +/* {{{ static int php_output_stack_pop(int discard, int shutdown TSRMLS_DC) + Pops an output handler off the stack, ignores whether the handler is removable if shutdown==1, discards the handlers output if discard==1 */ +static inline int php_output_stack_pop(int discard, int shutdown TSRMLS_DC) { - int result = 0; - - if (SG(request_info).headers_only) { - if(SG(headers_sent)) { - return 0; + php_output_context context; + php_output_handler **current, *orphan = OG(active); + + if (!orphan) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer. No buffer to delete."); + return 0; + } else if (!shutdown && !(orphan->flags & PHP_OUTPUT_HANDLER_REMOVABLE)) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", orphan->name); + return 0; + } else { + php_output_context_init(&context, PHP_OUTPUT_HANDLER_FINAL TSRMLS_CC); + + /* don't run the output handler if it's disabled */ + if (!(orphan->flags & PHP_OUTPUT_HANDLER_DISABLED)) { + /* didn't it start yet? */ + if (!(orphan->flags & PHP_OUTPUT_HANDLER_STARTED)) { + context.op |= PHP_OUTPUT_HANDLER_START; + } + /* signal that we're cleaning up */ + if (discard) { + context.op |= PHP_OUTPUT_HANDLER_CLEAN; + } + php_output_handler_op(orphan, &context); } - php_header(TSRMLS_C); - zend_bailout(); - } - if (php_header(TSRMLS_C)) { - if (zend_is_compiling(TSRMLS_C)) { - OG(output_start_filename) = zend_get_compiled_filename(TSRMLS_C); - OG(output_start_lineno) = zend_get_compiled_lineno(TSRMLS_C); - } else if (zend_is_executing(TSRMLS_C)) { - OG(output_start_filename) = zend_get_executed_filename(TSRMLS_C); - OG(output_start_lineno) = zend_get_executed_lineno(TSRMLS_C); + + /* pop it off the stack */ + zend_stack_del_top(&OG(handlers)); + if (SUCCESS == zend_stack_top(&OG(handlers), (void *) ¤t)) { + OG(active) = *current; + } else { + OG(active) = NULL; + } + + /* pass output along */ + if (context.out.data && context.out.used && !discard) { + php_output_write(context.out.data, context.out.used); } + + /* destroy the handler (after write!) */ + php_output_handler_free(&orphan); + php_output_context_dtor(&context); + + return 1; + } +} +/* }}} */ - OG(php_body_write) = php_ub_body_write_no_header; - result = php_ub_body_write_no_header(str, str_length TSRMLS_CC); +/* {{{ static SUCCESS|FAILURE php_output_handler_compat_func(void *ctx, int op, const char *in, size_t in_len, char **out, size_t *out_len TSRMLS_DC) + php_output_handler_context_func_t for php_output_handler_func_t output handlers */ +static int php_output_handler_compat_func(void **handler_context, php_output_context *output_context) +{ + php_output_handler_func_t func = *(php_output_handler_func_t *) handler_context; + PHP_OUTPUT_TSRMLS(output_context); + + if (func) { + func(output_context->in.data, output_context->in.used, &output_context->out.data, &output_context->out.used, output_context->op TSRMLS_CC); + output_context->out.free = 1; + return SUCCESS; } + return FAILURE; +} +/* }}} */ + +/* {{{ static SUCCESS|FAILURE php_output_handler_default_func(void *ctx, int op, const char *in, size_t in_len, char **out, size_t *out_len TSRMLS_DC) + Default output handler */ +static int php_output_handler_default_func(void **handler_context, php_output_context *output_context) +{ + output_context->out.data = output_context->in.data; + output_context->out.used = output_context->in.used; + output_context->out.free = output_context->in.free; + output_context->in.data = NULL; + output_context->in.used = 0; + return SUCCESS; +} +/* }}} */ - return result; +/* {{{ static SUCCESS|FAILURE php_output_handler_devnull_func(void *ctx, int op, const char *in, size_t in_len, char **out, size_t *out_len TSRMLS_DC) + Null output handler */ +static int php_output_handler_devnull_func(void **handler_context, php_output_context *output_context) +{ + return SUCCESS; } /* }}} */ /* - * HEAD support + * USERLAND (nearly 1:1 of old output.c) */ -/* {{{ proto bool ob_start([ string|array user_function [, int chunk_size [, bool erase]]]) +/* {{{ proto bool ob_start([ string|array user_function [, int chunk_size [, int flags]]]) Turn on Output Buffering (specifying an optional output handler). */ PHP_FUNCTION(ob_start) { - zval *output_handler=NULL; - long chunk_size=0; - zend_bool erase=1; - int argc = ZEND_NUM_ARGS(); + zval *output_handler = NULL; + long chunk_size = 0; + long flags = PHP_OUTPUT_HANDLER_CLEANABLE|PHP_OUTPUT_HANDLER_REMOVABLE; - if (zend_parse_parameters(argc TSRMLS_CC, "|zlb", &output_handler, &chunk_size, &erase) == FAILURE) { + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|zlb", &output_handler, &chunk_size, &flags)) { RETURN_FALSE; } - - if (chunk_size < 0) + if (chunk_size < 0) { chunk_size = 0; + } - if (php_start_ob_buffer(output_handler, chunk_size, erase TSRMLS_CC)==FAILURE) { + if (SUCCESS != php_output_start_user(output_handler, chunk_size, flags)) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to create buffer."); RETURN_FALSE; } RETURN_TRUE; @@ -820,16 +1228,16 @@ Flush (send) contents of the output buffer. The last buffer content is sent to next buffer */ PHP_FUNCTION(ob_flush) { - if (ZEND_NUM_ARGS() != 0) { + if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - - if (!OG(ob_nesting_level)) { + + if (!OG(active)) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to flush buffer. No buffer to flush."); RETURN_FALSE; } - php_end_ob_buffer(1, 1 TSRMLS_CC); + php_output_flush(); RETURN_TRUE; } /* }}} */ @@ -839,21 +1247,18 @@ Clean (delete) the current output buffer */ PHP_FUNCTION(ob_clean) { - if (ZEND_NUM_ARGS() != 0) { + if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - if (!OG(ob_nesting_level)) { + if (!OG(active)) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer. No buffer to delete."); RETURN_FALSE; } - - if (!OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) { - php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active_ob_buffer).handler_name); + if (SUCCESS != php_output_clean()) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active)->name); RETURN_FALSE; } - - php_end_ob_buffer(0, 1 TSRMLS_CC); RETURN_TRUE; } /* }}} */ @@ -862,20 +1267,18 @@ Flush (send) the output buffer, and delete current output buffer */ PHP_FUNCTION(ob_end_flush) { - if (ZEND_NUM_ARGS() != 0) { + if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - if (!OG(ob_nesting_level)) { + if (!OG(active)) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete and flush buffer. No buffer to delete or flush."); RETURN_FALSE; } - if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) { - php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active_ob_buffer).handler_name); + if (SUCCESS != php_output_end()) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active)->name); RETURN_FALSE; } - - php_end_ob_buffer(1, 0 TSRMLS_CC); RETURN_TRUE; } /* }}} */ @@ -884,20 +1287,18 @@ Clean the output buffer, and delete current output buffer */ PHP_FUNCTION(ob_end_clean) { - if (ZEND_NUM_ARGS() != 0) { + if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - - if (!OG(ob_nesting_level)) { + + if (!OG(active)) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer. No buffer to delete."); RETURN_FALSE; } - if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) { - php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active_ob_buffer).handler_name); + if (SUCCESS != php_output_discard()) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active)->name); RETURN_FALSE; } - - php_end_ob_buffer(0, 0 TSRMLS_CC); RETURN_TRUE; } /* }}} */ @@ -906,25 +1307,17 @@ Get current buffer contents, flush (send) the output buffer, and delete current output buffer */ PHP_FUNCTION(ob_get_flush) { - if (ZEND_NUM_ARGS() != 0) { + if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - - /* get contents */ - if (php_ob_get_buffer(return_value TSRMLS_CC)==FAILURE) { - RETURN_FALSE; - } - /* error checks */ - if (!OG(ob_nesting_level)) { + + if (SUCCESS != php_output_get_contents(return_value)) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete and flush buffer. No buffer to delete or flush."); RETURN_FALSE; } - if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) { - php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active_ob_buffer).handler_name); - RETURN_FALSE; + if (SUCCESS != php_output_end()) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active)->name); } - /* flush */ - php_end_ob_buffer(1, 0 TSRMLS_CC); } /* }}} */ @@ -932,24 +1325,17 @@ Get current buffer contents and delete current output buffer */ PHP_FUNCTION(ob_get_clean) { - if (ZEND_NUM_ARGS() != 0) - ZEND_WRONG_PARAM_COUNT(); - - /* get contents */ - if (php_ob_get_buffer(return_value TSRMLS_CC)==FAILURE) { - RETURN_FALSE; + if (ZEND_NUM_ARGS()) { + ZEND_WRONG_PARAM_COUNT(); } - /* error checks */ - if (!OG(ob_nesting_level)) { + + if (SUCCESS != php_output_get_contents(return_value)) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer. No buffer to delete."); RETURN_FALSE; } - if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) { - php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active_ob_buffer).handler_name); - RETURN_FALSE; + if (SUCCESS != php_output_discard()) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active)->name); } - /* delete buffer */ - php_end_ob_buffer(0, 0 TSRMLS_CC); } /* }}} */ @@ -957,11 +1343,10 @@ Return the contents of the output buffer */ PHP_FUNCTION(ob_get_contents) { - if (ZEND_NUM_ARGS() != 0) { + if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - - if (php_ob_get_buffer(return_value TSRMLS_CC)==FAILURE) { + if (SUCCESS != php_output_get_contents(return_value)) { RETURN_FALSE; } } @@ -971,11 +1356,10 @@ Return the nesting level of the output buffer */ PHP_FUNCTION(ob_get_level) { - if (ZEND_NUM_ARGS() != 0) { + if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - - RETURN_LONG (OG(ob_nesting_level)); + RETURN_LONG(php_output_get_level()); } /* }}} */ @@ -983,130 +1367,66 @@ Return the length of the output buffer */ PHP_FUNCTION(ob_get_length) { - if (ZEND_NUM_ARGS() != 0) { + if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - - if (php_ob_get_length(return_value TSRMLS_CC)==FAILURE) { + if (SUCCESS != php_output_get_length(return_value)) { RETURN_FALSE; } } /* }}} */ -/* {{{ int php_ob_buffer_status(php_ob_buffer *ob_buffer, zval *result) */ -static int php_ob_buffer_status(php_ob_buffer *ob_buffer, zval *result) +/* {{{ proto false|array ob_list_handlers() + * List all output_buffers in an array + */ +PHP_FUNCTION(ob_list_handlers) { - zval *elem; - TSRMLS_FETCH(); - - MAKE_STD_ZVAL(elem); - array_init(elem); - - add_assoc_long(elem, "chunk_size", ob_buffer->chunk_size); - if (!ob_buffer->chunk_size) { - add_assoc_long(elem, "size", ob_buffer->size); - add_assoc_long(elem, "block_size", ob_buffer->block_size); - } - if (ob_buffer->internal_output_handler) { - add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_INTERNAL); - add_assoc_long(elem, "buffer_size", ob_buffer->internal_output_handler_buffer_size); - } - else { - add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_USER); - } - add_assoc_long(elem, "status", ob_buffer->status); - add_assoc_text(elem, "name", ob_buffer->handler_name, 1); - add_assoc_bool(elem, "del", ob_buffer->erase); - add_next_index_zval(result, elem); - - return SUCCESS; + if (ZEND_NUM_ARGS()) { + ZEND_WRONG_PARAM_COUNT(); + } + if (!OG(active)) { + RETURN_FALSE; + } + + array_init(return_value); + zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_BOTTOMUP, php_output_stack_apply_list, return_value); } /* }}} */ - /* {{{ 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 ) + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &full_status)) { RETURN_FALSE; + } + if (!OG(active)) { + RETURN_FALSE; + } array_init(return_value); - if (full_status) { - 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); - } - if (OG(ob_nesting_level)>0 && php_ob_buffer_status(&OG(active_ob_buffer), return_value)==FAILURE) { - RETURN_FALSE; - } - } 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); - } else { - add_assoc_long(return_value, "type", PHP_OUTPUT_HANDLER_USER); - } - add_assoc_long(return_value, "status", OG(active_ob_buffer).status); - add_assoc_text(return_value, "name", OG(active_ob_buffer).handler_name, 1); - add_assoc_bool(return_value, "del", OG(active_ob_buffer).erase); + zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_BOTTOMUP, php_output_stack_apply_status, return_value); + } else { + php_output_handler_status(OG(active), return_value); } } /* }}} */ - /* {{{ proto void ob_implicit_flush([int flag]) Turn implicit flush on/off and is equivalent to calling flush() after every output call */ PHP_FUNCTION(ob_implicit_flush) { - zval **zv_flag; - int flag; - - switch(ZEND_NUM_ARGS()) { - case 0: - flag = 1; - break; - case 1: - if (zend_get_parameters_ex(1, &zv_flag)==FAILURE) { - RETURN_FALSE; - } - convert_to_long_ex(zv_flag); - flag = Z_LVAL_PP(zv_flag); - break; - default: - ZEND_WRONG_PARAM_COUNT(); - break; - } - if (flag) { - php_start_implicit_flush(TSRMLS_C); - } else { - php_end_implicit_flush(TSRMLS_C); + long flag = 1; + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flag)) { + php_output_set_implicit_flush(flag); } } /* }}} */ - -/* {{{ char *php_get_output_start_filename(TSRMLS_D) - Return filename start output something */ -PHPAPI char *php_get_output_start_filename(TSRMLS_D) -{ - return OG(output_start_filename); -} -/* }}} */ - - -/* {{{ char *php_get_output_start_lineno(TSRMLS_D) - Return line number start output something */ -PHPAPI int php_get_output_start_lineno(TSRMLS_D) -{ - return OG(output_start_lineno); -} -/* }}} */ - - /* {{{ proto bool output_reset_rewrite_vars(void) Reset(clear) URL rewriter values */ PHP_FUNCTION(output_reset_rewrite_vars) @@ -1119,7 +1439,6 @@ } /* }}} */ - /* {{{ proto bool output_add_rewrite_var(string name, string value) Add URL rewriter values */ PHP_FUNCTION(output_add_rewrite_var) http://cvs.php.net/viewcvs.cgi/php-src/main/php.h?r1=1.230&r2=1.231&diff_format=u Index: php-src/main/php.h diff -u php-src/main/php.h:1.230 php-src/main/php.h:1.231 --- php-src/main/php.h:1.230 Thu May 25 18:48:30 2006 +++ php-src/main/php.h Fri Jun 2 19:51:42 2006 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php.h,v 1.230 2006/05/25 18:48:30 edink Exp $ */ +/* $Id: php.h,v 1.231 2006/06/02 19:51:42 mike Exp $ */ #ifndef PHP_H #define PHP_H @@ -373,20 +373,7 @@ /* Output support */ #include "main/php_output.h" -#define PHPWRITE(str, str_len) php_body_write((str), (str_len) TSRMLS_CC) -#define PUTS(str) do { \ - const char *__str = (str); \ - php_body_write(__str, strlen(__str) TSRMLS_CC); \ -} while (0) - -#define PUTC(c) (php_body_write(&(c), 1 TSRMLS_CC), (c)) -#define PHPWRITE_H(str, str_len) php_header_write((str), (str_len) TSRMLS_CC) -#define PUTS_H(str) do { \ - const char *__str = (str); \ - php_header_write(__str, strlen(__str) TSRMLS_CC); \ -} while (0) -#define PUTC_H(c) (php_header_write(&(c), 1 TSRMLS_CC), (c)) #ifdef ZTS #define VIRTUAL_DIR http://cvs.php.net/viewcvs.cgi/php-src/main/php_output.h?r1=1.55&r2=1.56&diff_format=u Index: php-src/main/php_output.h diff -u php-src/main/php_output.h:1.55 php-src/main/php_output.h:1.56 --- php-src/main/php_output.h:1.55 Thu Mar 2 13:12:45 2006 +++ php-src/main/php_output.h Fri Jun 2 19:51:42 2006 @@ -12,44 +12,291 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Zeev Suraski <zeev@zend.com> | + | Author: Michael Wallner <mike@php.net> | +----------------------------------------------------------------------+ */ -/* $Id: php_output.h,v 1.55 2006/03/02 13:12:45 dmitry Exp $ */ +/* $Id: php_output.h,v 1.56 2006/06/02 19:51:42 mike Exp $ */ #ifndef PHP_OUTPUT_H #define PHP_OUTPUT_H +#define PHP_OUTPUT_NEWAPI 1 + +/* handler ops */ +#define PHP_OUTPUT_HANDLER_WRITE 0x00 /* standard passthru */ +#define PHP_OUTPUT_HANDLER_START 0x01 /* start */ +#define PHP_OUTPUT_HANDLER_CLEAN 0x02 /* restart */ +#define PHP_OUTPUT_HANDLER_FLUSH 0x04 /* pass along as much as possible */ +#define PHP_OUTPUT_HANDLER_FINAL 0x08 /* finalize */ +#define PHP_OUTPUT_HANDLER_CONT PHP_OUTPUT_HANDLER_WRITE +#define PHP_OUTPUT_HANDLER_END PHP_OUTPUT_HANDLER_FINAL + +/* handler types */ +#define PHP_OUTPUT_HANDLER_INTERNAL 0x0000 +#define PHP_OUTPUT_HANDLER_USER 0x0001 + +/* handler ability flags */ +#define PHP_OUTPUT_HANDLER_CLEANABLE 0x0010 +#define PHP_OUTPUT_HANDLER_REMOVABLE 0x0020 +#define PHP_OUTPUT_HANDLER_STDFLAGS 0x0030 + +/* handler status flags */ +#define PHP_OUTPUT_HANDLER_STARTED 0x1000 +#define PHP_OUTPUT_HANDLER_DISABLED 0x2000 + +/* handler op return values */ +#define PHP_OUTPUT_HANDLER_FAILURE 0 +#define PHP_OUTPUT_HANDLER_SUCCESS 1 +#define PHP_OUTPUT_HANDLER_NO_DATA 2 + +/* real global flags */ +#define PHP_OUTPUT_IMPLICITFLUSH 0x01 +#define PHP_OUTPUT_DISABLED 0x02 +/* supplementary flags for php_output_get_status() */ +#define PHP_OUTPUT_ACTIVE 0x10 +#define PHP_OUTPUT_LOCKED 0x20 + +/* handler hooks */ +#define PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ 1 +#define PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS 2 +#define PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE 3 +#define PHP_OUTPUT_HANDLER_HOOK_DISABLE 4 + +#define PHP_OUTPUT_HANDLER_INITBUF_SIZE(s) \ +( (s) ? \ + (s) + PHP_OUTPUT_HANDLER_ALIGNTO_SIZE - ((s) % (PHP_OUTPUT_HANDLER_ALIGNTO_SIZE >> 2)) : \ + PHP_OUTPUT_HANDLER_DEFAULT_SIZE \ +) +#define PHP_OUTPUT_HANDLER_ALIGNTO_SIZE 0x1000 +#define PHP_OUTPUT_HANDLER_DEFAULT_SIZE 0x4000 +#define PHP_OUTPUT_HANDLER_DEFAULT_NAME "default output handler" +#define PHP_OUTPUT_HANDLER_DEVNULL_NAME "null output handler" + +PHPAPI zval php_output_handler_default; +PHPAPI zval php_output_handler_devnull; + +typedef struct _php_output_buffer { + char *data; + size_t size; + size_t used; + uint free:1; + uint _res:31; +} php_output_buffer; + +typedef struct _php_output_context { + int op; + php_output_buffer in; + php_output_buffer out; +#ifdef ZTS + void ***tsrm_ls; +#endif +} php_output_context; + +#define PHP_OUTPUT_TSRMLS(ctx) TSRMLS_FETCH_FROM_CTX((ctx)->tsrm_ls) + +/* old-style, stateless callback */ typedef void (*php_output_handler_func_t)(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC); +/* new-style, opaque context callback */ +typedef int (*php_output_handler_context_func_t)(void **handler_context, php_output_context *output_context); +/* conflict check callback */ +typedef int (*php_output_handler_conflict_check_t)(zval *handler_name TSRMLS_DC); + +typedef struct _php_output_handler { + zval *name; + int flags; + int level; + size_t size; + php_output_buffer buffer; + + void *opaq; + void (*dtor)(void *opaq TSRMLS_DC); + + union { + zval *user; + php_output_handler_context_func_t internal; + }; +} php_output_handler; + +ZEND_BEGIN_MODULE_GLOBALS(output) + int flags; + zend_stack handlers; + php_output_handler *active; + php_output_handler *running; + char *output_start_filename; + int output_start_lineno; + zval *default_output_handler_name; + zval *devnull_output_handler_name; +ZEND_END_MODULE_GLOBALS(output); + +/* there should not be a need to use OG() from outside of output.c */ +#ifdef ZTS +#define OG(v) TSRMG(output_globals_id, zend_output_globals *, v) +#else +#define OG(v) (output_globals.v) +#endif + +/* convenience macros */ +#define PHPWRITE(str, str_len) php_output_write((str), (str_len)) +#define PHPWRITE_H(str, str_len) php_output_write_unbuffered((str), (str_len)) + +#define PUTC(c) (php_output_write(&(c), 1), (c)) +#define PUTC_H(c) (php_output_write_unbuffered(&(c), 1), (c)) + +#define PUTS(str) do { \ + const char *__str = (str); \ + php_output_write(__str, strlen(__str)); \ +} while (0) +#define PUTS_H(str) do { \ + const char *__str = (str); \ + php_output_write_unbuffered(__str, strlen(__str)); \ +} while (0) + BEGIN_EXTERN_C() +#define php_output_tearup() \ + php_output_startup(); \ + php_output_activate() +#define php_output_teardown() \ + php_output_end_all(); \ + php_output_deactivate(); \ + php_output_shutdown() + +/* MINIT */ PHPAPI void php_output_startup(void); -PHPAPI void php_output_activate(TSRMLS_D); -PHPAPI void php_output_set_status(zend_bool status TSRMLS_DC); -PHPAPI void php_output_register_constants(TSRMLS_D); -PHPAPI int php_default_output_func(const char *str, uint str_len TSRMLS_DC); -PHPAPI int php_ub_body_write(const char *str, uint str_length TSRMLS_DC); -PHPAPI int php_ub_body_write_no_header(const char *str, uint str_length TSRMLS_DC); -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); -PHPAPI int php_ob_get_length(zval *p TSRMLS_DC); -PHPAPI void php_start_implicit_flush(TSRMLS_D); -PHPAPI void php_end_implicit_flush(TSRMLS_D); -PHPAPI char *php_get_output_start_filename(TSRMLS_D); -PHPAPI int php_get_output_start_lineno(TSRMLS_D); -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); -PHPAPI int php_ob_handler_used(char *handler_name TSRMLS_DC); -PHPAPI int php_ob_init_conflict(char *handler_new, char *handler_set TSRMLS_DC); -PHPAPI int php_ob_get_buffer(zval *p TSRMLS_DC); -PHPAPI int php_ob_get_length(zval *p TSRMLS_DC); +/* MSHUTDOWN */ +PHPAPI void php_output_shutdown(void); + +#define php_output_register_constants() _php_output_register_constants(TSRMLS_C) +PHPAPI void _php_output_register_constants(TSRMLS_D); + +/* RINIT */ +#define php_output_activate() _php_output_activate(TSRMLS_C) +PHPAPI int _php_output_activate(TSRMLS_D); +/* RSHUTDOWN */ +#define php_output_deactivate() _php_output_deactivate(TSRMLS_C) +PHPAPI void _php_output_deactivate(TSRMLS_D); + + +#define php_output_get_default_handler_name() _php_output_get_default_handler_name(TSRMLS_C) +PHPAPI zval *_php_output_get_default_handler_name(TSRMLS_D); + +#define php_output_get_devnull_handler_name() _php_output_get_devnull_handler_name(TSRMLS_C) +PHPAPI zval *_php_output_get_devnull_handler_name(TSRMLS_D); + + +#define php_output_set_status(s) _php_output_set_status((s) TSRMLS_CC) +PHPAPI void _php_output_set_status(int status TSRMLS_DC); + +#define php_output_get_status() _php_output_get_status(TSRMLS_C) +PHPAPI int _php_output_get_status(TSRMLS_D); + +#define php_output_write_unbuffered(s, l) _php_output_write_unbuffered((s), (l) TSRMLS_CC) +PHPAPI int _php_output_write_unbuffered(const char *str, size_t len TSRMLS_DC); + +#define php_output_write(s, l) _php_output_write((s), (l) TSRMLS_CC) +PHPAPI int _php_output_write(const char *str, size_t len TSRMLS_DC); + +#define php_output_flush() _php_output_flush(TSRMLS_C) +PHPAPI void _php_output_flush(TSRMLS_D); + +#define php_output_flush_all() _php_output_flush_all(TSRMLS_C) +PHPAPI void _php_output_flush_all(TSRMLS_D); + +#define php_output_clean() _php_output_clean(TSRMLS_C) +PHPAPI int _php_output_clean(TSRMLS_D); + +#define php_output_clean_all() _php_output_clean_all(TSRMLS_C) +PHPAPI void _php_output_clean_all(TSRMLS_D); + +#define php_output_end() _php_output_end(TSRMLS_C) +PHPAPI int _php_output_end(TSRMLS_D); + +#define php_output_end_all() _php_output_end_all(TSRMLS_C) +PHPAPI void _php_output_end_all(TSRMLS_D); + +#define php_output_discard() _php_output_discard(TSRMLS_C) +PHPAPI int _php_output_discard(TSRMLS_D); + +#define php_output_discard_all() _php_output_discard_all(TSRMLS_C) +PHPAPI void _php_output_discard_all(TSRMLS_D); + + +#define php_output_get_contents(p) _php_output_get_contents((p) TSRMLS_CC) +PHPAPI int _php_output_get_contents(zval *p TSRMLS_DC); + +#define php_output_get_length(p) _php_output_get_length((p) TSRMLS_CC) +PHPAPI int _php_output_get_length(zval *TSRMLS_DC); + +#define php_output_get_level() _php_output_get_level(TSRMLS_C) +PHPAPI int _php_output_get_level(TSRMLS_D); + + +#define php_output_start_default() _php_output_start_default(TSRMLS_C) +PHPAPI int _php_output_start_default(TSRMLS_D); + +#define php_output_start_devnull() _php_output_start_devnull(TSRMLS_C) +PHPAPI int _php_output_start_devnull(TSRMLS_D); + +#define php_output_start_user(h, s, f) _php_output_start_user((h), (s), (f) TSRMLS_CC) +PHPAPI int _php_output_start_user(zval *output_handler, size_t chunk_size, int flags TSRMLS_DC); + +#define php_output_start_internal(n, h, s, f) _php_output_start_internal((n), (h), (s), (f) TSRMLS_CC) +PHPAPI int _php_output_start_internal(zval *name, php_output_handler_func_t output_handler, size_t chunk_size, int flags TSRMLS_DC); + +#define php_output_handler_create_user(h, s, f) _php_output_handler_create_user((h), (s), (f) TSRMLS_CC) +PHPAPI php_output_handler *_php_output_handler_create_user(zval *handler, size_t chunk_size, int flags TSRMLS_DC); + +#define php_output_handler_create_internal(n, h, s, f) _php_output_handler_create_internal((n), (h), (s), (f) TSRMLS_CC) +PHPAPI php_output_handler *_php_output_handler_create_internal(zval *name, php_output_handler_context_func_t handler, size_t chunk_size, int flags TSRMLS_DC); + +#define php_output_handler_set_context(h, c, d) _php_output_handler_set_context((h), (c), (d) TSRMLS_CC) +PHPAPI void _php_output_handler_set_context(php_output_handler *handler, void *opaq, void (*dtor)(void* TSRMLS_DC) TSRMLS_DC); + +#define php_output_handler_start(h) _php_output_handler_start((h) TSRMLS_CC) +PHPAPI int _php_output_handler_start(php_output_handler *handler TSRMLS_DC); + +#define php_output_handler_started(n) _php_output_handler_started((n) TSRMLS_CC) +PHPAPI int _php_output_handler_started(zval *name TSRMLS_DC); + +#define php_output_handler_hook(t, a) _php_output_handler_hook((t), (a) TSRMLS_CC) +PHPAPI int _php_output_handler_hook(int type, void *arg TSRMLS_DC); + +#define php_output_handler_dtor(h) _php_output_handler_dtor((h) TSRMLS_CC) +PHPAPI void _php_output_handler_dtor(php_output_handler *handler TSRMLS_DC); + +#define php_output_handler_free(h) _php_output_handler_free((h) TSRMLS_CC) +PHPAPI void _php_output_handler_free(php_output_handler **handler TSRMLS_DC); + + +#define php_output_set_implicit_flush(f) _php_output_set_implicit_flush((f) TSRMLS_CC) +PHPAPI void _php_output_set_implicit_flush(int flush TSRMLS_DC); + +#define php_output_get_start_filename() _php_output_get_start_filename(TSRMLS_C) +PHPAPI char *_php_output_get_start_filename(TSRMLS_D); + +#define php_output_get_start_lineno() _php_output_get_start_lineno(TSRMLS_C) +PHPAPI int _php_output_get_start_lineno(TSRMLS_D); + + +#define php_output_handler_conflict(n, s) _php_output_handler_conflict((n), (s) TSRMLS_CC) +PHPAPI int _php_output_handler_conflict(zval *handler_new, zval *handler_set TSRMLS_DC); + +#define php_output_handler_conflict_register(n, f) _php_output_handler_conflict_register((n), (f) TSRMLS_CC) +PHPAPI int _php_output_handler_conflict_register(zval *handler_name, php_output_handler_conflict_check_t check_func TSRMLS_DC); + +#define php_output_handler_reverse_conflict_register(n, f) _php_output_handler_reverse_conflict_register((n), (f) TSRMLS_CC) +PHPAPI int _php_output_handler_reverse_conflict_register(zval *handler_name, php_output_handler_conflict_check_t check_func TSRMLS_DC); + +#define php_output_handler_alias(n) _php_output_handler_alias((n) TSRMLS_CC) +PHPAPI php_output_handler_context_func_t *_php_output_handler_alias(zval *handler_name TSRMLS_DC); + +#define php_output_handler_alias_register(n, f) _php_output_handler_alias_register((n), (f) TSRMLS_CC) +PHPAPI int _php_output_handler_alias_register(zval *handler_name, php_output_handler_context_func_t func TSRMLS_DC); + END_EXTERN_C() + PHP_FUNCTION(ob_start); PHP_FUNCTION(ob_flush); PHP_FUNCTION(ob_clean); @@ -64,51 +311,16 @@ PHP_FUNCTION(ob_implicit_flush); PHP_FUNCTION(ob_list_handlers); -typedef struct _php_ob_buffer { - char *buffer; - uint size; - uint text_length; - int block_size; - uint chunk_size; - int status; - zval *output_handler; - php_output_handler_func_t internal_output_handler; - char *internal_output_handler_buffer; - uint internal_output_handler_buffer_size; - zstr handler_name; - zend_bool erase; -} php_ob_buffer; - -typedef struct _php_output_globals { - int (*php_body_write)(const char *str, uint str_length TSRMLS_DC); /* string output */ - int (*php_header_write)(const char *str, uint str_length TSRMLS_DC); /* unbuffer string output */ - php_ob_buffer active_ob_buffer; - unsigned char implicit_flush; - char *output_start_filename; - int output_start_lineno; - zend_stack ob_buffers; - int ob_nesting_level; - zend_bool ob_lock; - zend_bool disable_output; -} php_output_globals; - -#ifdef ZTS -#define OG(v) TSRMG(output_globals_id, php_output_globals *, v) -ZEND_API extern int output_globals_id; -#else -#define OG(v) (output_globals.v) -ZEND_API extern php_output_globals output_globals; -#endif - -#define PHP_OUTPUT_HANDLER_START (1<<0) -#define PHP_OUTPUT_HANDLER_CONT (1<<1) -#define PHP_OUTPUT_HANDLER_END (1<<2) - -#define PHP_OUTPUT_HANDLER_INTERNAL 0 -#define PHP_OUTPUT_HANDLER_USER 1 - PHP_FUNCTION(output_add_rewrite_var); PHP_FUNCTION(output_reset_rewrite_vars); +#endif -#endif /* PHP_OUTPUT_H */ +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ http://cvs.php.net/viewcvs.cgi/php-src/sapi/apache/mod_php5.c?r1=1.33&r2=1.34&diff_format=u Index: php-src/sapi/apache/mod_php5.c diff -u php-src/sapi/apache/mod_php5.c:1.33 php-src/sapi/apache/mod_php5.c:1.34 --- php-src/sapi/apache/mod_php5.c:1.33 Sat May 13 21:48:14 2006 +++ php-src/sapi/apache/mod_php5.c Fri Jun 2 19:51:42 2006 @@ -17,7 +17,7 @@ | PHP 4.0 patches by Zeev Suraski <zeev@zend.com> | +----------------------------------------------------------------------+ */ -/* $Id: mod_php5.c,v 1.33 2006/05/13 21:48:14 rasmus Exp $ */ +/* $Id: mod_php5.c,v 1.34 2006/06/02 19:51:42 mike Exp $ */ #include "php_apache_http.h" #include "http_conf_globals.h" @@ -315,7 +315,7 @@ { TSRMLS_FETCH(); - php_output_set_status(0 TSRMLS_CC); + php_output_set_status(PHP_OUTPUT_DISABLED); if (AP(in_request)) { AP(in_request) = 0; php_request_shutdown(dummy); http://cvs.php.net/viewcvs.cgi/php-src/sapi/apache/php_apache.c?r1=1.94&r2=1.95&diff_format=u Index: php-src/sapi/apache/php_apache.c diff -u php-src/sapi/apache/php_apache.c:1.94 php-src/sapi/apache/php_apache.c:1.95 --- php-src/sapi/apache/php_apache.c:1.94 Wed Apr 26 09:32:11 2006 +++ php-src/sapi/apache/php_apache.c Fri Jun 2 19:51:42 2006 @@ -17,7 +17,7 @@ | David Sklar <sklar@student.net> | +----------------------------------------------------------------------+ */ -/* $Id: php_apache.c,v 1.94 2006/04/26 09:32:11 edink Exp $ */ +/* $Id: php_apache.c,v 1.95 2006/06/02 19:51:42 mike Exp $ */ #include "php_apache_http.h" @@ -329,7 +329,7 @@ RETURN_FALSE; } - php_end_ob_buffers(1 TSRMLS_CC); + php_output_end_all(); php_header(TSRMLS_C); if (run_sub_req(rr)) { http://cvs.php.net/viewcvs.cgi/php-src/sapi/apache2handler/php_functions.c?r1=1.24&r2=1.25&diff_format=u Index: php-src/sapi/apache2handler/php_functions.c diff -u php-src/sapi/apache2handler/php_functions.c:1.24 php-src/sapi/apache2handler/php_functions.c:1.25 --- php-src/sapi/apache2handler/php_functions.c:1.24 Tue Jan 3 20:13:31 2006 +++ php-src/sapi/apache2handler/php_functions.c Fri Jun 2 19:51:42 2006 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_functions.c,v 1.24 2006/01/03 20:13:31 iliaa Exp $ */ +/* $Id: php_functions.c,v 1.25 2006/06/02 19:51:42 mike Exp $ */ #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS @@ -93,7 +93,7 @@ } /* Flush everything. */ - php_end_ob_buffers(1 TSRMLS_CC); + php_output_end_all(); php_header(TSRMLS_C); /* Ensure that the ap_r* layer for the main request is flushed, to http://cvs.php.net/viewcvs.cgi/php-src/sapi/apache_hooks/mod_php5.c?r1=1.16&r2=1.17&diff_format=u Index: php-src/sapi/apache_hooks/mod_php5.c diff -u php-src/sapi/apache_hooks/mod_php5.c:1.16 php-src/sapi/apache_hooks/mod_php5.c:1.17 --- php-src/sapi/apache_hooks/mod_php5.c:1.16 Tue Mar 7 00:20:54 2006 +++ php-src/sapi/apache_hooks/mod_php5.c Fri Jun 2 19:51:43 2006 @@ -17,7 +17,7 @@ | PHP 4.0 patches by Zeev Suraski <zeev@zend.com> | +----------------------------------------------------------------------+ */ -/* $Id: mod_php5.c,v 1.16 2006/03/07 00:20:54 pajoye Exp $ */ +/* $Id: mod_php5.c,v 1.17 2006/06/02 19:51:43 mike Exp $ */ #include "php_apache_http.h" @@ -434,7 +434,7 @@ { TSRMLS_FETCH(); AP(current_hook) = AP_CLEANUP; - php_output_set_status(0 TSRMLS_CC); + php_output_set_status(PHP_OUTPUT_DISABLED); SG(server_context) = NULL; /* The server context (request) is invalid by the time run_cleanups() is called */ if(SG(sapi_started)) { php_request_shutdown(dummy); http://cvs.php.net/viewcvs.cgi/php-src/sapi/apache_hooks/php_apache.c?r1=1.24&r2=1.25&diff_format=u Index: php-src/sapi/apache_hooks/php_apache.c diff -u php-src/sapi/apache_hooks/php_apache.c:1.24 php-src/sapi/apache_hooks/php_apache.c:1.25 --- php-src/sapi/apache_hooks/php_apache.c:1.24 Tue Mar 7 14:43:16 2006 +++ php-src/sapi/apache_hooks/php_apache.c Fri Jun 2 19:51:43 2006 @@ -17,7 +17,7 @@ | David Sklar <sklar@student.net> | +----------------------------------------------------------------------+ */ -/* $Id: php_apache.c,v 1.24 2006/03/07 14:43:16 iliaa Exp $ */ +/* $Id: php_apache.c,v 1.25 2006/06/02 19:51:43 mike Exp $ */ #include "php_apache_http.h" @@ -1731,7 +1731,7 @@ RETURN_FALSE; } - php_end_ob_buffers(1 TSRMLS_CC); + php_output_end_all(); php_header(TSRMLS_C); if (run_sub_req(rr)) { http://cvs.php.net/viewcvs.cgi/php-src/sapi/cgi/cgi_main.c?r1=1.289&r2=1.290&diff_format=u Index: php-src/sapi/cgi/cgi_main.c diff -u php-src/sapi/cgi/cgi_main.c:1.289 php-src/sapi/cgi/cgi_main.c:1.290 --- php-src/sapi/cgi/cgi_main.c:1.289 Wed May 24 09:41:55 2006 +++ php-src/sapi/cgi/cgi_main.c Fri Jun 2 19:51:43 2006 @@ -21,7 +21,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: cgi_main.c,v 1.289 2006/05/24 09:41:55 dmitry Exp $ */ +/* $Id: cgi_main.c,v 1.290 2006/06/02 19:51:43 mike Exp $ */ #include "php.h" #include "php_globals.h" @@ -1266,11 +1266,10 @@ case 'h': case '?': no_headers = 1; - php_output_startup(); - php_output_activate(TSRMLS_C); + php_output_tearup(); SG(headers_sent) = 1; php_cgi_usage(argv[0]); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); exit(1); break; } @@ -1299,11 +1298,10 @@ if (!cgi && !fastcgi) { if (cgi_sapi_module.php_ini_path_override && cgi_sapi_module.php_ini_ignore) { no_headers = 1; - php_output_startup(); - php_output_activate(TSRMLS_C); + php_output_tearup(); SG(headers_sent) = 1; php_printf("You cannot use both -n and -c switch. Use -h for help.\n"); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); exit(1); } @@ -1349,7 +1347,7 @@ SG(request_info).no_headers = 1; } php_print_info(0xFFFFFFFF TSRMLS_CC); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); exit(0); break; @@ -1359,15 +1357,14 @@ break; case 'm': /* list compiled in modules */ - php_output_startup(); - php_output_activate(TSRMLS_C); + php_output_tearup(); SG(headers_sent) = 1; php_printf("[PHP Modules]\n"); print_modules(TSRMLS_C); php_printf("\n[Zend Modules]\n"); print_extensions(TSRMLS_C); php_printf("\n"); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); exit(0); break; @@ -1400,7 +1397,7 @@ #else php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2006 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); #endif - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); exit(0); break; @@ -1562,7 +1559,7 @@ if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) { zend_strip(TSRMLS_C); fclose(file_handle.handle.fp); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); } return SUCCESS; break; @@ -1574,7 +1571,7 @@ php_get_highlight_struct(&syntax_highlighter_ini); zend_highlight(&syntax_highlighter_ini TSRMLS_CC); fclose(file_handle.handle.fp); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); } return SUCCESS; } @@ -1585,6 +1582,7 @@ open_file_for_scanning(&file_handle TSRMLS_CC); zend_indent(); fclose(file_handle.handle.fp); + php_output_teardown(); return SUCCESS; break; #endif http://cvs.php.net/viewcvs.cgi/php-src/sapi/cli/php_cli.c?r1=1.153&r2=1.154&diff_format=u Index: php-src/sapi/cli/php_cli.c diff -u php-src/sapi/cli/php_cli.c:1.153 php-src/sapi/cli/php_cli.c:1.154 --- php-src/sapi/cli/php_cli.c:1.153 Thu May 11 22:08:55 2006 +++ php-src/sapi/cli/php_cli.c Fri Jun 2 19:51:43 2006 @@ -20,7 +20,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_cli.c,v 1.153 2006/05/11 22:08:55 dmitry Exp $ */ +/* $Id: php_cli.c,v 1.154 2006/06/02 19:51:43 mike Exp $ */ #include "php.h" #include "php_globals.h" @@ -719,7 +719,7 @@ goto err; } php_cli_usage(argv[0]); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_end_all(); exit_status=0; goto out; @@ -728,7 +728,7 @@ goto err; } php_print_info(0xFFFFFFFF TSRMLS_CC); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_end_all(); exit_status=0; goto out; @@ -741,7 +741,7 @@ php_printf("\n[Zend Modules]\n"); print_extensions(TSRMLS_C); php_printf("\n"); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_end_all(); exit_status=0; goto out; @@ -763,7 +763,7 @@ #endif get_zend_version() ); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_end_all(); exit_status=0; goto out; http://cvs.php.net/viewcvs.cgi/php-src/sapi/milter/php_milter.c?r1=1.16&r2=1.17&diff_format=u Index: php-src/sapi/milter/php_milter.c diff -u php-src/sapi/milter/php_milter.c:1.16 php-src/sapi/milter/php_milter.c:1.17 --- php-src/sapi/milter/php_milter.c:1.16 Sun Jan 1 13:09:58 2006 +++ php-src/sapi/milter/php_milter.c Fri Jun 2 19:51:43 2006 @@ -966,11 +966,10 @@ while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) { switch (c) { case '?': - php_output_startup(); - php_output_activate(TSRMLS_C); + php_output_tearup(); SG(headers_sent) = 1; php_milter_usage(argv[0]); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); exit(1); break; } @@ -1021,11 +1020,10 @@ case 'h': /* help & quit */ case '?': - php_output_startup(); - php_output_activate(TSRMLS_C); + php_output_tearup(); SG(headers_sent) = 1; php_milter_usage(argv[0]); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); exit(1); break; @@ -1045,7 +1043,7 @@ SG(headers_sent) = 1; SG(request_info).no_headers = 1; php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2006 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); exit(1); break; http://cvs.php.net/viewcvs.cgi/php-src/sapi/nsapi/nsapi.c?r1=1.74&r2=1.75&diff_format=u Index: php-src/sapi/nsapi/nsapi.c diff -u php-src/sapi/nsapi/nsapi.c:1.74 php-src/sapi/nsapi/nsapi.c:1.75 --- php-src/sapi/nsapi/nsapi.c:1.74 Sat Apr 29 21:50:17 2006 +++ php-src/sapi/nsapi/nsapi.c Fri Jun 2 19:51:43 2006 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: nsapi.c,v 1.74 2006/04/29 21:50:17 thetaphi Exp $ */ +/* $Id: nsapi.c,v 1.75 2006/06/02 19:51:43 mike Exp $ */ /* * PHP includes @@ -310,7 +310,7 @@ PHP_MINFO_FUNCTION(nsapi) { php_info_print_table_start(); - php_info_print_table_row(2, "NSAPI Module Revision", "$Revision: 1.74 $"); + php_info_print_table_row(2, "NSAPI Module Revision", "$Revision: 1.75 $"); php_info_print_table_row(2, "Server Software", system_version()); php_info_print_table_row(2, "Sub-requests with nsapi_virtual()", (nsapi_servact_service)?((zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0))?"not supported with zlib.output_compression":"enabled"):"not supported on this platform" ); @@ -347,7 +347,7 @@ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include uri '%s' - Sub-requests do not work with zlib.output_compression", (*uri)->value.str.val); RETURN_FALSE; } else { - php_end_ob_buffers(1 TSRMLS_CC); + php_output_end_all(); php_header(TSRMLS_C); /* do the sub-request */ http://cvs.php.net/viewcvs.cgi/php-src/README.NEW-OUTPUT-API?view=markup&rev=1.1 Index: php-src/README.NEW-OUTPUT-API +++ php-src/README.NEW-OUTPUT-API $Id: README.NEW-OUTPUT-API,v 1.1 2006/06/02 19:51:42 mike Exp $ API adjustment to the old output control code: Everything now resides beneath the php_output namespace, and there's an API call for every output handler op. However, there's a thin compatibility layer unless PHP_OUTPUT_NOCOMPAT is defined. Checking output control layers status: // Using OG() php_output_get_status(); Starting the default output handler: // php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC); php_output_start_default(); Starting an user handler by zval: // php_start_ob_buffer(zhandler, chunk_size, erase TSRMLS_CC); php_output_start_user(zhandler, chunk_size, flags); Starting an internal handler whithout context: // php_ob_set_internal_handler(my_php_output_handler_func_t, buffer_size, "output handler name", erase TSRMLS_CC); php_output_start_internal(handler_name_zval, my_php_output_handler_func_t, chunk_size, flags); Starting an internal handler with context: // not possible with old API php_output_handler *h; h = php_output_handler_create_internal(handler_name_zval, my_php_output_handler_context_func_t, chunk_size, flags); php_output_handler_set_context(h, my_context, my_context_dtor); php_output_handler_start(h); Testing whether a certain output handler has already been started: // php_ob_handler_used("output handler name" TSRMLS_CC); php_output_handler_started(handler_name_zval); Flushing one output buffer: // php_ob_end_buffer(1, 1 TSRMLS_CC); php_output_flush(); Flushing all output buffers: // not possible with old API php_output_flush_all(); Cleaning one output buffer: // php_ob_end_buffer(0, 1 TSRMLS_CC); php_output_clean(); Cleaning all output buffers: // not possible with old API php_output_clean_all(); Discarding one output buffer: // php_ob_end_buffer(0, 0 TSRMLS_CC); php_output_discard(); Discarding all output buffers: // php_ob_end_buffers(0 TSRMLS_CC); php_output_discard_all(); Stopping (and dropping) one output buffer: // php_ob_end_buffer(1, 0 TSRMLS_CC) php_output_end(); Stopping (and dropping) all output buffers: // php_ob_end_buffers(1, 0 TSRMLS_CC); php_output_end_all(); Retrieving output buffers contents: // php_ob_get_buffer(zstring TSRMLS_CC); php_output_get_contents(zstring); Retrieving output buffers length: // php_ob_get_length(zlength TSRMLS_CC); php_output_get_length(zlenght); Retrieving output buffering level: // OG(nesting_level); php_output_get_level(); Issue a warning because of an output handler conflict: // php_ob_init_conflict("to be started handler name", "to be tested if already started handler name" TSRMLS_CC); php_output_handler_conflict(new_handler_name_zval, set_handler_name_zval); Registering a conflict checking function, which will be checked prior starting the handler: // not possible with old API, unless hardcoding into output.c php_output_handler_conflict_register(handler_name_zval, my_php_output_handler_conflict_check_t); Registering a reverse conflict checking function, which will be checked prior starting the specified foreign handler: // not possible with old API php_output_handler_reverse_conflict_register(foreign_handler_name_zval, my_php_output_handler_conflict_check_t); Facilitating a context from within an output handler callable with ob_start(): // not possible with old API php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ, (void *) &custom_ctx_ptr_ptr); Disabling of the output handler by itself: //not possible with old API php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_DISABLE, NULL); Marking an output handler immutable by itself because of irreversibility of its operation: // not possible with old API php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL); Restarting the output handler because of a CLEAN operation: // not possible with old API if (flags & PHP_OUTPUT_HANDLER_CLEAN) { ... } Recognizing by the output handler itself if it gets discarded: // not possible with old API if ((flags & PHP_OUTPUT_HANDLER_CLEAN) && (flags & PHP_OUTPUT_HANDLER_FINAL)) { ... } Output handler hooks The output handler can change its abilities at runtime. Eg. the gz handler can remove the CLEANABLE and REMOVABLE bits when the first output has passed through it; or handlers implemented in C to be used with ob_start() can contain a non-global context: PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ pass a void*** pointer as second arg to receive the address of a pointer pointer to the opaque field of the output handler context PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS pass a int* pointer as second arg to receive the flags set for the output handler PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE the second arg is ignored; marks the output handler to be neither cleanable nor removable PHP_OUTPUT_HANDLER_HOOK_DISABLE the second arg is ignored; marks the output handler as disabled Open questions Should the userland API be adjusted and unified? Many bits of the manual (and very first implementation) do not comply with the behaviour of the current (to be obsoleted) code, thus should the manual or the behaviour be adjusted? END http://cvs.php.net/viewcvs.cgi/php-src/tests/output/.cvsignore?view=markup&rev=1.1 Index: php-src/tests/output/.cvsignore +++ php-src/tests/output/.cvsignore *.php *.log *.diff *.exp *.out *~ http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_001.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_001.phpt +++ php-src/tests/output/ob_001.phpt --TEST-- output buffering - nothing --FILE-- <?php echo "foo\n"; ?> --EXPECTF-- foo http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_002.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_002.phpt +++ php-src/tests/output/ob_002.phpt --TEST-- output buffering - ob_start --FILE-- <?php ob_start(); echo "foo\n"; ?> --EXPECT-- foo http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_003.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_003.phpt +++ php-src/tests/output/ob_003.phpt --TEST-- output buffering - ob_flush --FILE-- <?php ob_start(); echo "foo\n"; ob_flush(); echo "bar\n"; ob_flush(); ?> --EXPECT-- foo bar http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_004.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_004.phpt +++ php-src/tests/output/ob_004.phpt --TEST-- output buffering - ob_clean --FILE-- <?php ob_start(); echo "foo\n"; ob_clean(); echo "bar\n"; ?> --EXPECT-- bar http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_005.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_005.phpt +++ php-src/tests/output/ob_005.phpt --TEST-- output buffering - ob_end_clean --FILE-- <?php ob_start(); echo "foo\n"; ob_start(); echo "bar\n"; ob_end_clean(); echo "baz\n"; ?> --EXPECT-- foo baz http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_006.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_006.phpt +++ php-src/tests/output/ob_006.phpt --TEST-- output buffering - ob_end_flush --FILE-- <?php ob_start(); echo "foo\n"; ob_end_flush(); var_dump(ob_get_level()); ?> --EXPECT-- foo int(0) http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_007.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_007.phpt +++ php-src/tests/output/ob_007.phpt --TEST-- output buffering - ob_get_clean --FILE-- <?php ob_start(); echo "foo\n"; var_dump(ob_get_clean()); ?> --EXPECT-- string(4) "foo " http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_008.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_008.phpt +++ php-src/tests/output/ob_008.phpt --TEST-- output buffering - ob_get_contents --FILE-- <?php ob_start(); echo "foo\n"; echo ob_get_contents(); ?> --EXPECT-- foo foo http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_009.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_009.phpt +++ php-src/tests/output/ob_009.phpt --TEST-- output buffering - ob_get_flush --FILE-- <?php ob_start(); echo "foo\n"; var_dump(ob_get_flush()); ?> --EXPECT-- foo string(4) "foo " http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_010.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_010.phpt +++ php-src/tests/output/ob_010.phpt --TEST-- output buffering - fatalism --FILE-- <?php function obh($s) { print_r($s, 1); } ob_start("obh"); echo "foo\n"; ?> --EXPECTF-- Fatal error: print_r(): Cannot use output buffering in output buffering display handlers in %s/ob_010.php on line %d http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_011.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_011.phpt +++ php-src/tests/output/ob_011.phpt --TEST-- output buffering - fatalism --FILE-- <?php function obh($s) { return ob_get_flush(); } ob_start("obh"); echo "foo\n"; ?> --EXPECTF-- Fatal error: ob_get_flush(): Cannot use output buffering in output buffering display handlers in %s/ob_011.php on line %d http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_012.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_012.phpt +++ php-src/tests/output/ob_012.phpt --TEST-- output buffering - multiple --FILE-- <?php echo 0; ob_start(); ob_start(); ob_start(); ob_start(); echo 1; ob_end_flush(); echo 2; $ob = ob_get_clean(); echo 3; ob_flush(); ob_end_clean(); echo 4; ob_end_flush(); echo $ob; ?> --EXPECT-- 03412 http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_013.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_013.phpt +++ php-src/tests/output/ob_013.phpt --TEST-- output buffering - handlers/status --FILE-- <?php function a($s){return $s;} function b($s){return $s;} function c($s){return $s;} function d($s){return $s;} ob_start(); ob_start('a'); ob_start('b'); ob_start('c'); ob_start('d'); ob_start(); echo "foo\n"; ob_flush(); ob_end_clean(); ob_flush(); print_r(ob_list_handlers()); print_r(ob_get_status()); print_r(ob_get_status(true)); ?> --EXPECT-- foo Array ( [0] => default output handler [1] => a [2] => b [3] => c [4] => d ) Array ( [name] => d [type] => 1 [flags] => 4145 [level] => 4 [chunk_size] => 0 [buffer_size] => 16384 [buffer_used] => 96 ) Array ( [0] => Array ( [name] => default output handler [type] => 0 [flags] => 48 [level] => 0 [chunk_size] => 0 [buffer_size] => 16384 [buffer_used] => 0 ) [1] => Array ( [name] => a [type] => 1 [flags] => 49 [level] => 1 [chunk_size] => 0 [buffer_size] => 16384 [buffer_used] => 0 ) [2] => Array ( [name] => b [type] => 1 [flags] => 49 [level] => 2 [chunk_size] => 0 [buffer_size] => 16384 [buffer_used] => 0 ) [3] => Array ( [name] => c [type] => 1 [flags] => 49 [level] => 3 [chunk_size] => 0 [buffer_size] => 16384 [buffer_used] => 4 ) [4] => Array ( [name] => d [type] => 1 [flags] => 4145 [level] => 4 [chunk_size] => 0 [buffer_size] => 16384 [buffer_used] => 248 ) ) http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_014.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_014.phpt +++ php-src/tests/output/ob_014.phpt --TEST-- output buffering - failure --FILE-- <?php /* * apparently the error handler cannot get the current function name on shutdown */ ob_start("str_rot13"); echo "foo\n"; ?> --EXPECTF-- foo Warning: Wrong parameter count for (null)() in %s on line %d http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_015.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_015.phpt +++ php-src/tests/output/ob_015.phpt --TEST-- output buffering - failure --FILE-- <?php ob_start("str_rot13", 1); echo "foo\n"; ?> --EXPECTF-- foo Warning: Wrong parameter count for str_rot13() in %s on line %d
http://cvs.php.net/viewcvs.cgi/php-src/ext/pgsql/pgsql.c?r1=1.350&r2=1.351&diff_format=u Index: php-src/ext/pgsql/pgsql.c diff -u php-src/ext/pgsql/pgsql.c:1.350 php-src/ext/pgsql/pgsql.c:1.351 --- php-src/ext/pgsql/pgsql.c:1.350 Mon Apr 10 19:50:56 2006 +++ php-src/ext/pgsql/pgsql.c Fri Jun 2 19:51:42 2006 @@ -20,7 +20,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: pgsql.c,v 1.350 2006/04/10 19:50:56 helly Exp $ */ +/* $Id: pgsql.c,v 1.351 2006/06/02 19:51:42 mike Exp $ */ #include <stdlib.h> @@ -2858,7 +2858,7 @@ tbytes = 0; while ((nbytes = lo_read((PGconn *)pgsql->conn, pgsql->lofd, buf, PGSQL_LO_READ_BUF_SIZE))>0) { - php_body_write(buf, nbytes TSRMLS_CC); + PHPWRITE(buf, nbytes); tbytes += nbytes; } RETURN_LONG(tbytes); http://cvs.php.net/viewcvs.cgi/php-src/ext/session/session.c?r1=1.434&r2=1.435&diff_format=u Index: php-src/ext/session/session.c diff -u php-src/ext/session/session.c:1.434 php-src/ext/session/session.c:1.435 --- php-src/ext/session/session.c:1.434 Thu May 18 22:07:31 2006 +++ php-src/ext/session/session.c Fri Jun 2 19:51:42 2006 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: session.c,v 1.434 2006/05/18 22:07:31 helly Exp $ */ +/* $Id: session.c,v 1.435 2006/06/02 19:51:42 mike Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -855,8 +855,8 @@ if (PS(cache_limiter)[0] == '\0') return 0; if (SG(headers_sent)) { - char *output_start_filename = php_get_output_start_filename(TSRMLS_C); - int output_start_lineno = php_get_output_start_lineno(TSRMLS_C); + char *output_start_filename = php_output_get_start_filename(); + int output_start_lineno = php_output_get_start_lineno(); if (output_start_filename) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot send session cache limiter - headers already sent (output started at %s:%d)", @@ -889,8 +889,8 @@ char *date_fmt = NULL; if (SG(headers_sent)) { - char *output_start_filename = php_get_output_start_filename(TSRMLS_C); - int output_start_lineno = php_get_output_start_lineno(TSRMLS_C); + char *output_start_filename = php_output_get_start_filename(); + int output_start_lineno = php_output_get_start_lineno(); if (output_start_filename) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot send session cookie - headers already sent by (output started at %s:%d)", http://cvs.php.net/viewcvs.cgi/php-src/ext/soap/soap.c?r1=1.189&r2=1.190&diff_format=u Index: php-src/ext/soap/soap.c diff -u php-src/ext/soap/soap.c:1.189 php-src/ext/soap/soap.c:1.190 --- php-src/ext/soap/soap.c:1.189 Fri May 26 09:04:53 2006 +++ php-src/ext/soap/soap.c Fri Jun 2 19:51:42 2006 @@ -17,7 +17,7 @@ | Dmitry Stogov <dmitry@zend.com> | +----------------------------------------------------------------------+ */ -/* $Id: soap.c,v 1.189 2006/05/26 09:04:53 dmitry Exp $ */ +/* $Id: soap.c,v 1.190 2006/06/02 19:51:42 mike Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -1482,7 +1482,7 @@ } } - if (php_start_ob_buffer(NULL, 0, 0 TSRMLS_CC) != SUCCESS) { + if (php_output_start_default() != SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_ERROR,"ob_start failed"); } @@ -1609,7 +1609,7 @@ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error calling constructor"); } if (EG(exception)) { - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_discard(); if (Z_TYPE_P(EG(exception)) == IS_OBJECT && instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) { soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC); @@ -1642,7 +1642,7 @@ } #ifdef ZEND_ENGINE_2 if (EG(exception)) { - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_discard(); if (Z_TYPE_P(EG(exception)) == IS_OBJECT && instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) { soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC); @@ -1721,14 +1721,14 @@ Z_TYPE_PP(tmp) != IS_NULL) { headerfault = *tmp; } - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_discard(); soap_server_fault_ex(function, &h->retval, h TSRMLS_CC); efree(fn_name); if (soap_obj) {zval_ptr_dtor(&soap_obj);} goto fail; #ifdef ZEND_ENGINE_2 } else if (EG(exception)) { - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_discard(); if (Z_TYPE_P(EG(exception)) == IS_OBJECT && instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) { zval *headerfault = NULL, **tmp; @@ -1774,7 +1774,7 @@ #ifdef ZEND_ENGINE_2 if (EG(exception)) { - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_discard(); if (Z_TYPE_P(EG(exception)) == IS_OBJECT && instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) { soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC); @@ -1794,7 +1794,7 @@ if (Z_TYPE(retval) == IS_OBJECT && instanceof_function(Z_OBJCE(retval), soap_fault_class_entry TSRMLS_CC)) { - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_discard(); soap_server_fault_ex(function, &retval, NULL TSRMLS_CC); goto fail; } @@ -1815,7 +1815,7 @@ } /* Flush buffer */ - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_discard(); if (doc_return) { /* xmlDocDumpMemoryEnc(doc_return, &buf, &size, XML_CHAR_ENCODING_UTF8); */ @@ -2083,11 +2083,11 @@ code = "Server"; } /* Get output buffer and send as fault detials */ - if (php_ob_get_length(&outbuflen TSRMLS_CC) != FAILURE && Z_LVAL(outbuflen) != 0) { + if (php_output_get_length(&outbuflen) != FAILURE && Z_LVAL(outbuflen) != 0) { ALLOC_INIT_ZVAL(outbuf); - php_ob_get_buffer(outbuf TSRMLS_CC); + php_output_get_contents(outbuf TSRMLS_CC); } - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_discard(); INIT_ZVAL(fault_obj); set_soap_fault(&fault_obj, NULL, code, buffer, NULL, outbuf, NULL TSRMLS_CC); http://cvs.php.net/viewcvs.cgi/php-src/ext/standard/basic_functions.c?r1=1.775&r2=1.776&diff_format=u Index: php-src/ext/standard/basic_functions.c diff -u php-src/ext/standard/basic_functions.c:1.775 php-src/ext/standard/basic_functions.c:1.776 --- php-src/ext/standard/basic_functions.c:1.775 Tue May 30 14:51:54 2006 +++ php-src/ext/standard/basic_functions.c Fri Jun 2 19:51:42 2006 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: basic_functions.c,v 1.775 2006/05/30 14:51:54 iliaa Exp $ */ +/* $Id: basic_functions.c,v 1.776 2006/06/02 19:51:42 mike Exp $ */ #include "php.h" #include "php_streams.h" @@ -2406,7 +2406,7 @@ } if (i) { - php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC); + php_output_start_default(); } php_get_highlight_struct(&syntax_highlighter_ini); @@ -2416,8 +2416,8 @@ } if (i) { - php_ob_get_buffer (return_value TSRMLS_CC); - php_end_ob_buffer (0, 0 TSRMLS_CC); + php_output_get_contents(return_value); + php_output_discard(); } else { RETURN_TRUE; } @@ -2437,7 +2437,7 @@ RETURN_FALSE; } - php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC); + php_output_start_default(); file_handle.type = ZEND_HANDLE_FILENAME; file_handle.filename = filename; @@ -2453,8 +2453,8 @@ zend_destroy_file_handle(&file_handle TSRMLS_CC); zend_restore_lexical_state(&original_lex_state TSRMLS_CC); - php_ob_get_buffer(return_value TSRMLS_CC); - php_end_ob_buffer(0, 0 TSRMLS_CC); + php_output_get_contents(return_value); + php_output_discard(); return; } @@ -2476,7 +2476,7 @@ convert_to_string(expr); if (i) { - php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC); + php_output_start_default(); } EG(error_reporting) = E_ERROR; @@ -2494,8 +2494,8 @@ EG(error_reporting) = old_error_reporting; if (i) { - php_ob_get_buffer (return_value TSRMLS_CC); - php_end_ob_buffer (0, 0 TSRMLS_CC); + php_output_get_contents(return_value); + php_output_discard(); } else { RETURN_TRUE; } @@ -2739,14 +2739,14 @@ } if (i) { - php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC); + php_output_start_default(); } zend_print_zval_r(var, 0 TSRMLS_CC); if (i) { - php_ob_get_buffer (return_value TSRMLS_CC); - php_end_ob_buffer (0, 0 TSRMLS_CC); + php_output_get_contents(return_value); + php_output_discard(); } else { RETURN_TRUE; } http://cvs.php.net/viewcvs.cgi/php-src/ext/standard/head.c?r1=1.86&r2=1.87&diff_format=u Index: php-src/ext/standard/head.c diff -u php-src/ext/standard/head.c:1.86 php-src/ext/standard/head.c:1.87 --- php-src/ext/standard/head.c:1.86 Sun Feb 19 18:19:33 2006 +++ php-src/ext/standard/head.c Fri Jun 2 19:51:42 2006 @@ -15,7 +15,7 @@ | Author: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | +----------------------------------------------------------------------+ */ -/* $Id: head.c,v 1.86 2006/02/19 18:19:33 iliaa Exp $ */ +/* $Id: head.c,v 1.87 2006/06/02 19:51:42 mike Exp $ */ #include <stdio.h> #include "php.h" @@ -200,8 +200,8 @@ return; if (SG(headers_sent)) { - line = php_get_output_start_lineno(TSRMLS_C); - file = php_get_output_start_filename(TSRMLS_C); + line = php_output_get_start_lineno(); + file = php_output_get_start_filename(); } switch(ZEND_NUM_ARGS()) { http://cvs.php.net/viewcvs.cgi/php-src/ext/standard/info.c?r1=1.263&r2=1.264&diff_format=u Index: php-src/ext/standard/info.c diff -u php-src/ext/standard/info.c:1.263 php-src/ext/standard/info.c:1.264 --- php-src/ext/standard/info.c:1.263 Fri Mar 31 11:11:26 2006 +++ php-src/ext/standard/info.c Fri Jun 2 19:51:42 2006 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: info.c,v 1.263 2006/03/31 11:11:26 tony2001 Exp $ */ +/* $Id: info.c,v 1.264 2006/06/02 19:51:42 mike Exp $ */ #include "php.h" #include "php_ini.h" @@ -70,7 +70,7 @@ elem_esc = php_escape_html_entities((char *)str, str_length, &new_len, 0, ENT_QUOTES, NULL TSRMLS_CC); - written = php_body_write(elem_esc, new_len TSRMLS_CC); + written = PHPWRITE(elem_esc, new_len); efree(elem_esc); @@ -351,7 +351,7 @@ } #if HAVE_MBSTRING - if (php_ob_handler_used("mb_output_handler" TSRMLS_CC)) { + if (php_output_handler_started("mb_output_handler")) { if (MBSTRG(current_http_output_encoding) == mbfl_no_encoding_pass) { charset = "US-ASCII"; } else { @@ -361,7 +361,7 @@ #endif #if HAVE_ICONV - if (php_ob_handler_used("ob_iconv_handler" TSRMLS_CC)) { + if (php_output_handler_started("ob_iconv_handler")) { charset = ICONVG(output_encoding); } #endif @@ -999,9 +999,9 @@ } /* Andale! Andale! Yee-Hah! */ - php_start_ob_buffer(NULL, 4096, 0 TSRMLS_CC); + php_output_start_default(); php_print_info(flag TSRMLS_CC); - php_end_ob_buffer(1, 0 TSRMLS_CC); + php_output_end(); RETURN_TRUE; } http://cvs.php.net/viewcvs.cgi/php-src/ext/standard/url_scanner_ex.c?r1=1.101&r2=1.102&diff_format=u Index: php-src/ext/standard/url_scanner_ex.c diff -u php-src/ext/standard/url_scanner_ex.c:1.101 php-src/ext/standard/url_scanner_ex.c:1.102 --- php-src/ext/standard/url_scanner_ex.c:1.101 Tue Feb 28 14:46:29 2006 +++ php-src/ext/standard/url_scanner_ex.c Fri Jun 2 19:51:42 2006 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: url_scanner_ex.c,v 1.101 2006/02/28 14:46:29 iliaa Exp $ */ +/* $Id: url_scanner_ex.c,v 1.102 2006/06/02 19:51:42 mike Exp $ */ #include "php.h" @@ -109,51 +109,78 @@ q = (p = url->c) + url->len; scan: - -#line 114 "ext/standard/url_scanner_ex.c" { - YYCTYPE yych; - goto yy0; - ++YYCURSOR; -yy0: - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - switch(yych){ - case '#': goto yy6; - case ':': goto yy2; - case '?': goto yy4; - default: goto yy8; - } -yy2: ++YYCURSOR; - goto yy3; -yy3: + static unsigned char yybm[] = { + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 0, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 0, 128, 128, 128, 128, 0, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + }; + +#line 149 "ext/standard/url_scanner_ex.c" + { + YYCTYPE yych; + + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if(yybm[0+yych] & 128) { + goto yy8; + } + if(yych <= '9') goto yy6; + if(yych >= ';') goto yy4; + ++YYCURSOR; #line 115 "ext/standard/url_scanner_ex.re" -{ smart_str_append(dest, url); return; } -#line 133 "ext/standard/url_scanner_ex.c" -yy4: ++YYCURSOR; - goto yy5; -yy5: + { smart_str_append(dest, url); return; } +#line 163 "ext/standard/url_scanner_ex.c" +yy4: + ++YYCURSOR; #line 116 "ext/standard/url_scanner_ex.re" -{ sep = separator; goto scan; } -#line 139 "ext/standard/url_scanner_ex.c" -yy6: ++YYCURSOR; - goto yy7; -yy7: + { sep = separator; goto scan; } +#line 168 "ext/standard/url_scanner_ex.c" +yy6: + ++YYCURSOR; #line 117 "ext/standard/url_scanner_ex.re" -{ bash = p - 1; goto done; } -#line 145 "ext/standard/url_scanner_ex.c" -yy8: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy9; -yy9: switch(yych){ - case '#': case ':': case '?': goto yy10; - default: goto yy8; - } -yy10: + { bash = p - 1; goto done; } +#line 173 "ext/standard/url_scanner_ex.c" +yy8: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if(yybm[0+yych] & 128) { + goto yy8; + } #line 118 "ext/standard/url_scanner_ex.re" -{ goto scan; } -#line 157 "ext/standard/url_scanner_ex.c" + { goto scan; } +#line 183 "ext/standard/url_scanner_ex.c" + } } #line 119 "ext/standard/url_scanner_ex.re" @@ -323,176 +350,138 @@ state_plain: start = YYCURSOR; - -#line 328 "ext/standard/url_scanner_ex.c" { - YYCTYPE yych; - goto yy11; - ++YYCURSOR; -yy11: - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - switch(yych){ - case '<': goto yy13; - default: goto yy15; - } -yy13: ++YYCURSOR; - goto yy14; -yy14: + static unsigned char yybm[] = { + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 0, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + }; + +#line 390 "ext/standard/url_scanner_ex.c" + { + YYCTYPE yych; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if(yybm[0+yych] & 128) { + goto yy15; + } + ++YYCURSOR; #line 287 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); STATE = STATE_TAG; goto state_tag; } -#line 345 "ext/standard/url_scanner_ex.c" -yy15: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy16; -yy16: switch(yych){ - case '<': goto yy17; - default: goto yy15; - } -yy17: + { passthru(STD_ARGS); STATE = STATE_TAG; goto state_tag; } +#line 401 "ext/standard/url_scanner_ex.c" +yy15: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if(yybm[0+yych] & 128) { + goto yy15; + } #line 288 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); goto state_plain; } -#line 357 "ext/standard/url_scanner_ex.c" + { passthru(STD_ARGS); goto state_plain; } +#line 411 "ext/standard/url_scanner_ex.c" + } } #line 289 "ext/standard/url_scanner_ex.re" state_tag: start = YYCURSOR; - -#line 365 "ext/standard/url_scanner_ex.c" { - YYCTYPE yych; - goto yy18; - ++YYCURSOR; -yy18: - if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); - yych = *YYCURSOR; - switch(yych){ - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - case 'G': - case 'H': - case 'I': - case 'J': - case 'K': - case 'L': - case 'M': - case 'N': - case 'O': - case 'P': - case 'Q': - case 'R': - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'g': - case 'h': - case 'i': - case 'j': - case 'k': - case 'l': - case 'm': - case 'n': - case 'o': - case 'p': - case 'q': - case 'r': - case 's': - case 't': - case 'u': - case 'v': - case 'w': - case 'x': - case 'y': - case 'z': goto yy20; - default: goto yy22; - } -yy20: ++YYCURSOR; - yych = *YYCURSOR; - goto yy25; + static unsigned char yybm[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 0, 0, 0, 0, 0, + 0, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + +#line 455 "ext/standard/url_scanner_ex.c" + { + YYCTYPE yych; + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if(yych <= '@') goto yy22; + if(yych <= 'Z') goto yy20; + if(yych <= '`') goto yy22; + if(yych >= '{') goto yy22; +yy20: + ++YYCURSOR; + yych = *YYCURSOR; + goto yy25; yy21: #line 294 "ext/standard/url_scanner_ex.re" -{ handle_tag(STD_ARGS); /* Sets STATE */; passthru(STD_ARGS); if (STATE == STATE_PLAIN) goto state_plain; else goto state_next_arg; } -#line 433 "ext/standard/url_scanner_ex.c" -yy22: ++YYCURSOR; - goto yy23; -yy23: + { handle_tag(STD_ARGS); /* Sets STATE */; passthru(STD_ARGS); if (STATE == STATE_PLAIN) goto state_plain; else goto state_next_arg; } +#line 471 "ext/standard/url_scanner_ex.c" +yy22: + ++YYCURSOR; #line 295 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); goto state_plain_begin; } -#line 439 "ext/standard/url_scanner_ex.c" -yy24: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy25; -yy25: switch(yych){ - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - case 'G': - case 'H': - case 'I': - case 'J': - case 'K': - case 'L': - case 'M': - case 'N': - case 'O': - case 'P': - case 'Q': - case 'R': - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'g': - case 'h': - case 'i': - case 'j': - case 'k': - case 'l': - case 'm': - case 'n': - case 'o': - case 'p': - case 'q': - case 'r': - case 's': - case 't': - case 'u': - case 'v': - case 'w': - case 'x': - case 'y': - case 'z': goto yy24; - default: goto yy21; + { passthru(STD_ARGS); goto state_plain_begin; } +#line 476 "ext/standard/url_scanner_ex.c" +yy24: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yy25: + if(yybm[0+yych] & 128) { + goto yy24; + } + goto yy21; } } #line 296 "ext/standard/url_scanner_ex.re" @@ -503,107 +492,98 @@ state_next_arg: start = YYCURSOR; - -#line 508 "ext/standard/url_scanner_ex.c" { - YYCTYPE yych; - goto yy26; - ++YYCURSOR; -yy26: - if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); - yych = *YYCURSOR; - switch(yych){ - case 0x09: - case 0x0A: - case 0x0B: case 0x0D: case ' ': goto yy30; - case '>': goto yy28; - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - case 'G': - case 'H': - case 'I': - case 'J': - case 'K': - case 'L': - case 'M': - case 'N': - case 'O': - case 'P': - case 'Q': - case 'R': - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'g': - case 'h': - case 'i': - case 'j': - case 'k': - case 'l': - case 'm': - case 'n': - case 'o': - case 'p': - case 'q': - case 'r': - case 's': - case 't': - case 'u': - case 'v': - case 'w': - case 'x': - case 'y': - case 'z': goto yy32; - default: goto yy34; - } -yy28: ++YYCURSOR; - goto yy29; -yy29: + static unsigned char yybm[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 128, 128, 128, 0, 128, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 128, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + +#line 532 "ext/standard/url_scanner_ex.c" + { + YYCTYPE yych; + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if(yych <= ' ') { + if(yych <= 0x0C) { + if(yych <= 0x08) goto yy34; + if(yych <= 0x0B) goto yy30; + goto yy34; + } else { + if(yych <= 0x0D) goto yy30; + if(yych <= 0x1F) goto yy34; + goto yy30; + } + } else { + if(yych <= '@') { + if(yych != '>') goto yy34; + } else { + if(yych <= 'Z') goto yy32; + if(yych <= '`') goto yy34; + if(yych <= 'z') goto yy32; + goto yy34; + } + } + ++YYCURSOR; #line 304 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); handle_form(STD_ARGS); goto state_plain_begin; } -#line 579 "ext/standard/url_scanner_ex.c" -yy30: ++YYCURSOR; - yych = *YYCURSOR; - goto yy37; + { passthru(STD_ARGS); handle_form(STD_ARGS); goto state_plain_begin; } +#line 560 "ext/standard/url_scanner_ex.c" +yy30: + ++YYCURSOR; + yych = *YYCURSOR; + goto yy37; yy31: #line 305 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); goto state_next_arg; } -#line 586 "ext/standard/url_scanner_ex.c" -yy32: ++YYCURSOR; - goto yy33; -yy33: + { passthru(STD_ARGS); goto state_next_arg; } +#line 568 "ext/standard/url_scanner_ex.c" +yy32: + ++YYCURSOR; #line 306 "ext/standard/url_scanner_ex.re" -{ --YYCURSOR; STATE = STATE_ARG; goto state_arg; } -#line 592 "ext/standard/url_scanner_ex.c" -yy34: ++YYCURSOR; - goto yy35; -yy35: + { --YYCURSOR; STATE = STATE_ARG; goto state_arg; } +#line 573 "ext/standard/url_scanner_ex.c" +yy34: + ++YYCURSOR; #line 307 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); goto state_plain_begin; } -#line 598 "ext/standard/url_scanner_ex.c" -yy36: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy37; -yy37: switch(yych){ - case 0x09: - case 0x0A: - case 0x0B: case 0x0D: case ' ': goto yy36; - default: goto yy31; + { passthru(STD_ARGS); goto state_plain_begin; } +#line 578 "ext/standard/url_scanner_ex.c" +yy36: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yy37: + if(yybm[0+yych] & 128) { + goto yy36; + } + goto yy31; } } #line 308 "ext/standard/url_scanner_ex.re" @@ -611,139 +591,73 @@ state_arg: start = YYCURSOR; - -#line 616 "ext/standard/url_scanner_ex.c" { - YYCTYPE yych; - goto yy38; - ++YYCURSOR; -yy38: - if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); - yych = *YYCURSOR; - switch(yych){ - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - case 'G': - case 'H': - case 'I': - case 'J': - case 'K': - case 'L': - case 'M': - case 'N': - case 'O': - case 'P': - case 'Q': - case 'R': - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'g': - case 'h': - case 'i': - case 'j': - case 'k': - case 'l': - case 'm': - case 'n': - case 'o': - case 'p': - case 'q': - case 'r': - case 's': - case 't': - case 'u': - case 'v': - case 'w': - case 'x': - case 'y': - case 'z': goto yy40; - default: goto yy42; - } -yy40: ++YYCURSOR; - yych = *YYCURSOR; - goto yy45; + static unsigned char yybm[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 128, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 0, 0, 0, 0, 0, + 0, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + +#line 631 "ext/standard/url_scanner_ex.c" + { + YYCTYPE yych; + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if(yych <= '@') goto yy42; + if(yych <= 'Z') goto yy40; + if(yych <= '`') goto yy42; + if(yych >= '{') goto yy42; +yy40: + ++YYCURSOR; + yych = *YYCURSOR; + goto yy45; yy41: #line 313 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); handle_arg(STD_ARGS); STATE = STATE_BEFORE_VAL; goto state_before_val; } -#line 684 "ext/standard/url_scanner_ex.c" -yy42: ++YYCURSOR; - goto yy43; -yy43: + { passthru(STD_ARGS); handle_arg(STD_ARGS); STATE = STATE_BEFORE_VAL; goto state_before_val; } +#line 647 "ext/standard/url_scanner_ex.c" +yy42: + ++YYCURSOR; #line 314 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); STATE = STATE_NEXT_ARG; goto state_next_arg; } -#line 690 "ext/standard/url_scanner_ex.c" -yy44: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy45; -yy45: switch(yych){ - case '-': case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - case 'G': - case 'H': - case 'I': - case 'J': - case 'K': - case 'L': - case 'M': - case 'N': - case 'O': - case 'P': - case 'Q': - case 'R': - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'g': - case 'h': - case 'i': - case 'j': - case 'k': - case 'l': - case 'm': - case 'n': - case 'o': - case 'p': - case 'q': - case 'r': - case 's': - case 't': - case 'u': - case 'v': - case 'w': - case 'x': - case 'y': - case 'z': goto yy44; - default: goto yy41; + { passthru(STD_ARGS); STATE = STATE_NEXT_ARG; goto state_next_arg; } +#line 652 "ext/standard/url_scanner_ex.c" +yy44: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yy45: + if(yybm[0+yych] & 128) { + goto yy44; + } + goto yy41; } } #line 315 "ext/standard/url_scanner_ex.re" @@ -751,61 +665,90 @@ state_before_val: start = YYCURSOR; - -#line 756 "ext/standard/url_scanner_ex.c" { - YYCTYPE yych; - unsigned int yyaccept = 0; - goto yy46; - ++YYCURSOR; -yy46: - if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); - yych = *YYCURSOR; - switch(yych){ - case ' ': goto yy48; - case '=': goto yy50; - default: goto yy52; - } -yy48: yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - switch(yych){ - case ' ': goto yy55; - case '=': goto yy53; - default: goto yy49; - } + static unsigned char yybm[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 128, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + +#line 705 "ext/standard/url_scanner_ex.c" + { + YYCTYPE yych; + unsigned int yyaccept = 0; + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if(yych == ' ') goto yy48; + if(yych == '=') goto yy50; + goto yy52; +yy48: + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if(yych == ' ') goto yy55; + if(yych == '=') goto yy53; yy49: #line 321 "ext/standard/url_scanner_ex.re" -{ --YYCURSOR; goto state_next_arg_begin; } -#line 780 "ext/standard/url_scanner_ex.c" -yy50: ++YYCURSOR; - yych = *YYCURSOR; - goto yy54; + { --YYCURSOR; goto state_next_arg_begin; } +#line 722 "ext/standard/url_scanner_ex.c" +yy50: + ++YYCURSOR; + yych = *YYCURSOR; + goto yy54; yy51: #line 320 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); STATE = STATE_VAL; goto state_val; } -#line 787 "ext/standard/url_scanner_ex.c" -yy52: yych = *++YYCURSOR; - goto yy49; -yy53: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy54; -yy54: switch(yych){ - case ' ': goto yy53; - default: goto yy51; - } -yy55: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy56; -yy56: switch(yych){ - case ' ': goto yy55; - case '=': goto yy53; - default: goto yy57; - } -yy57: YYCURSOR = YYMARKER; - switch(yyaccept){ - case 0: goto yy49; + { passthru(STD_ARGS); STATE = STATE_VAL; goto state_val; } +#line 730 "ext/standard/url_scanner_ex.c" +yy52: + yych = *++YYCURSOR; + goto yy49; +yy53: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yy54: + if(yybm[0+yych] & 128) { + goto yy53; + } + goto yy51; +yy55: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if(yych == ' ') goto yy55; + if(yych == '=') goto yy53; + YYCURSOR = YYMARKER; + switch(yyaccept){ + case 0: goto yy49; + } } } #line 322 "ext/standard/url_scanner_ex.re" @@ -814,121 +757,161 @@ state_val: start = YYCURSOR; - -#line 819 "ext/standard/url_scanner_ex.c" { - YYCTYPE yych; - unsigned int yyaccept = 0; - goto yy58; - ++YYCURSOR; -yy58: - if((YYLIMIT - YYCURSOR) < 3) YYFILL(3); - yych = *YYCURSOR; - switch(yych){ - case 0x09: - case 0x0A: case 0x0D: case ' ': case '>': goto yy64; - case '"': goto yy60; - case '\'': goto yy62; - default: goto yy63; - } -yy60: yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - goto yy77; + static unsigned char yybm[] = { + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 160, 160, 248, 248, 160, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 160, 248, 56, 248, 248, 248, 248, 200, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 0, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + }; + +#line 797 "ext/standard/url_scanner_ex.c" + { + YYCTYPE yych; + unsigned int yyaccept = 0; + if((YYLIMIT - YYCURSOR) < 3) YYFILL(3); + yych = *YYCURSOR; + if(yych <= ' ') { + if(yych <= 0x0C) { + if(yych <= 0x08) goto yy63; + if(yych <= 0x0A) goto yy64; + goto yy63; + } else { + if(yych <= 0x0D) goto yy64; + if(yych <= 0x1F) goto yy63; + goto yy64; + } + } else { + if(yych <= '&') { + if(yych != '"') goto yy63; + } else { + if(yych <= '\'') goto yy62; + if(yych == '>') goto yy64; + goto yy63; + } + } + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + goto yy77; yy61: #line 330 "ext/standard/url_scanner_ex.re" -{ handle_val(STD_ARGS, 0, ' '); goto state_next_arg_begin; } -#line 841 "ext/standard/url_scanner_ex.c" -yy62: yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - goto yy69; -yy63: yych = *++YYCURSOR; - goto yy67; -yy64: ++YYCURSOR; - goto yy65; -yy65: + { handle_val(STD_ARGS, 0, ' '); goto state_next_arg_begin; } +#line 828 "ext/standard/url_scanner_ex.c" +yy62: + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + goto yy69; +yy63: + yych = *++YYCURSOR; + goto yy67; +yy64: + ++YYCURSOR; #line 331 "ext/standard/url_scanner_ex.re" -{ passthru(STD_ARGS); goto state_next_arg_begin; } -#line 852 "ext/standard/url_scanner_ex.c" -yy66: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy67; -yy67: switch(yych){ - case 0x09: - case 0x0A: case 0x0D: case ' ': case '>': goto yy61; - default: goto yy66; - } -yy68: yyaccept = 0; - YYMARKER = ++YYCURSOR; - if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); - yych = *YYCURSOR; - goto yy69; -yy69: switch(yych){ - case 0x09: - case 0x0A: case 0x0D: case ' ': goto yy72; - case '\'': goto yy70; - case '>': goto yy61; - default: goto yy68; - } -yy70: ++YYCURSOR; - switch((yych = *YYCURSOR)) { - case 0x09: - case 0x0A: case 0x0D: case ' ': case '>': goto yy71; - default: goto yy66; - } + { passthru(STD_ARGS); goto state_next_arg_begin; } +#line 840 "ext/standard/url_scanner_ex.c" +yy66: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yy67: + if(yybm[0+yych] & 8) { + goto yy66; + } + goto yy61; +yy68: + yyaccept = 0; + YYMARKER = ++YYCURSOR; + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; +yy69: + if(yybm[0+yych] & 16) { + goto yy68; + } + if(yych <= '&') goto yy72; + if(yych >= '(') goto yy61; + ++YYCURSOR; + if(yybm[0+(yych = *YYCURSOR)] & 8) { + goto yy66; + } yy71: #line 329 "ext/standard/url_scanner_ex.re" -{ handle_val(STD_ARGS, 1, '\''); goto state_next_arg_begin; } -#line 883 "ext/standard/url_scanner_ex.c" -yy72: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy73; -yy73: switch(yych){ - case '\'': goto yy75; - case '>': goto yy74; - default: goto yy72; - } -yy74: YYCURSOR = YYMARKER; - switch(yyaccept){ - case 0: goto yy61; - } -yy75: yych = *++YYCURSOR; - goto yy71; -yy76: yyaccept = 0; - YYMARKER = ++YYCURSOR; - if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); - yych = *YYCURSOR; - goto yy77; -yy77: switch(yych){ - case 0x09: - case 0x0A: case 0x0D: case ' ': goto yy80; - case '"': goto yy78; - case '>': goto yy61; - default: goto yy76; - } -yy78: ++YYCURSOR; - switch((yych = *YYCURSOR)) { - case 0x09: - case 0x0A: case 0x0D: case ' ': case '>': goto yy79; - default: goto yy66; - } + { handle_val(STD_ARGS, 1, '\''); goto state_next_arg_begin; } +#line 868 "ext/standard/url_scanner_ex.c" +yy72: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if(yybm[0+yych] & 32) { + goto yy72; + } + if(yych <= '=') goto yy75; +yy74: + YYCURSOR = YYMARKER; + switch(yyaccept){ + case 0: goto yy61; + } +yy75: + yych = *++YYCURSOR; + goto yy71; +yy76: + yyaccept = 0; + YYMARKER = ++YYCURSOR; + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; +yy77: + if(yybm[0+yych] & 64) { + goto yy76; + } + if(yych <= '!') goto yy80; + if(yych >= '#') goto yy61; + ++YYCURSOR; + if(yybm[0+(yych = *YYCURSOR)] & 8) { + goto yy66; + } yy79: #line 328 "ext/standard/url_scanner_ex.re" -{ handle_val(STD_ARGS, 1, '"'); goto state_next_arg_begin; } -#line 920 "ext/standard/url_scanner_ex.c" -yy80: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - goto yy81; -yy81: switch(yych){ - case '"': goto yy82; - case '>': goto yy74; - default: goto yy80; + { handle_val(STD_ARGS, 1, '"'); goto state_next_arg_begin; } +#line 903 "ext/standard/url_scanner_ex.c" +yy80: + ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if(yybm[0+yych] & 128) { + goto yy80; + } + if(yych >= '>') goto yy74; + ++YYCURSOR; + yych = *YYCURSOR; + goto yy79; } -yy82: ++YYCURSOR; - yych = *YYCURSOR; - goto yy79; } #line 332 "ext/standard/url_scanner_ex.re" @@ -1055,7 +1038,7 @@ if (! BG(url_adapt_state_ex).active) { php_url_scanner_ex_activate(TSRMLS_C); - php_ob_set_internal_handler(php_url_scanner_output_handler, 0, "URL-Rewriter", 1 TSRMLS_CC); + php_output_start_internal("URL-Rewriter", php_url_scanner_output_handler, 0, PHP_OUTPUT_HANDLER_STDFLAGS); BG(url_adapt_state_ex).active = 1; } http://cvs.php.net/viewcvs.cgi/php-src/ext/standard/url_scanner_ex.re?r1=1.78&r2=1.79&diff_format=u Index: php-src/ext/standard/url_scanner_ex.re diff -u php-src/ext/standard/url_scanner_ex.re:1.78 php-src/ext/standard/url_scanner_ex.re:1.79 --- php-src/ext/standard/url_scanner_ex.re:1.78 Tue Feb 28 14:46:29 2006 +++ php-src/ext/standard/url_scanner_ex.re Fri Jun 2 19:51:42 2006 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: url_scanner_ex.re,v 1.78 2006/02/28 14:46:29 iliaa Exp $ */ +/* $Id: url_scanner_ex.re,v 1.79 2006/06/02 19:51:42 mike Exp $ */ #include "php.h" @@ -453,7 +453,7 @@ if (! BG(url_adapt_state_ex).active) { php_url_scanner_ex_activate(TSRMLS_C); - php_ob_set_internal_handler(php_url_scanner_output_handler, 0, "URL-Rewriter", 1 TSRMLS_CC); + php_output_start_internal("URL-Rewriter", php_url_scanner_output_handler, 0, PHP_OUTPUT_HANDLER_STDFLAGS); BG(url_adapt_state_ex).active = 1; } http://cvs.php.net/viewcvs.cgi/php-src/ext/standard/var.c?r1=1.231&r2=1.232&diff_format=u Index: php-src/ext/standard/var.c diff -u php-src/ext/standard/var.c:1.231 php-src/ext/standard/var.c:1.232 --- php-src/ext/standard/var.c:1.231 Tue May 30 14:51:54 2006 +++ php-src/ext/standard/var.c Fri Jun 2 19:51:42 2006 @@ -12,13 +12,13 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Authors: Jani Lehtimäki <jkl@njet.net> | + | Authors: Jani Lehtim�i <jkl@njet.net> | | Thies C. Arntzen <thies@thieso.net> | | Sascha Schumann <sascha@schumann.cx> | +----------------------------------------------------------------------+ */ -/* $Id: var.c,v 1.231 2006/05/30 14:51:54 iliaa Exp $ */ +/* $Id: var.c,v 1.232 2006/06/02 19:51:42 mike Exp $ */ @@ -602,7 +602,7 @@ } if (return_output) { - php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC); + php_output_start_default(); } /* UTODO @@ -614,8 +614,8 @@ php_var_export(&var, 1 TSRMLS_CC); if (return_output) { - php_ob_get_buffer (return_value TSRMLS_CC); - php_end_ob_buffer (0, 0 TSRMLS_CC); + php_output_get_contents(return_value); + php_output_discard(); } } /* }}} */ http://cvs.php.net/viewcvs.cgi/php-src/ext/tidy/tidy.c?r1=1.86&r2=1.87&diff_format=u Index: php-src/ext/tidy/tidy.c diff -u php-src/ext/tidy/tidy.c:1.86 php-src/ext/tidy/tidy.c:1.87 --- php-src/ext/tidy/tidy.c:1.86 Wed May 24 21:22:27 2006 +++ php-src/ext/tidy/tidy.c Fri Jun 2 19:51:42 2006 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: tidy.c,v 1.86 2006/05/24 21:22:27 tony2001 Exp $ */ +/* $Id: tidy.c,v 1.87 2006/06/02 19:51:42 mike Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -985,9 +985,13 @@ PHP_RINIT_FUNCTION(tidy) { if (INI_BOOL("tidy.clean_output") == TRUE) { - if (php_start_ob_buffer_named("ob_tidyhandler", 0, 1 TSRMLS_CC) == FAILURE) { + zval *name; + MAKE_STD_ZVAL(name); + ZVAL_ASCII_STRINGL(name, "ob_tidyhandler", sizeof("ob_tidyhandler"), ZSTR_DUPLICATE); + if (php_output_start_user(name, 0, PHP_OUTPUT_HANDLER_STDFLAGS) == FAILURE) { zend_error(E_NOTICE, "Failure installing Tidy output buffering."); } + zval_ptr_dtor(&name); } return SUCCESS; @@ -1009,7 +1013,7 @@ php_info_print_table_start(); php_info_print_table_header(2, "Tidy support", "enabled"); php_info_print_table_row(2, "libTidy Release", (char *)tidyReleaseDate()); - php_info_print_table_row(2, "Extension Version", PHP_TIDY_MODULE_VERSION " ($Id: tidy.c,v 1.86 2006/05/24 21:22:27 tony2001 Exp $)"); + php_info_print_table_row(2, "Extension Version", PHP_TIDY_MODULE_VERSION " ($Id: tidy.c,v 1.87 2006/06/02 19:51:42 mike Exp $)"); php_info_print_table_end(); DISPLAY_INI_ENTRIES(); http://cvs.php.net/viewcvs.cgi/php-src/ext/zlib/php_zlib.h?r1=1.43&r2=1.44&diff_format=u Index: php-src/ext/zlib/php_zlib.h diff -u php-src/ext/zlib/php_zlib.h:1.43 php-src/ext/zlib/php_zlib.h:1.44 --- php-src/ext/zlib/php_zlib.h:1.43 Sun Jan 1 13:09:56 2006 +++ php-src/ext/zlib/php_zlib.h Fri Jun 2 19:51:42 2006 @@ -13,11 +13,11 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | - | Stefan Röhrich <sr@linux.de> | + | Stefan R�rich <sr@linux.de> | +----------------------------------------------------------------------+ */ -/* $Id: php_zlib.h,v 1.43 2006/01/01 13:09:56 sniper Exp $ */ +/* $Id: php_zlib.h,v 1.44 2006/06/02 19:51:42 mike Exp $ */ #ifndef PHP_ZLIB_H #define PHP_ZLIB_H @@ -55,7 +55,7 @@ PHP_FUNCTION(zlib_get_coding_type); int php_enable_output_compression(int buffer_size TSRMLS_DC); -int php_ob_gzhandler_check(TSRMLS_D); +int php_ob_gzhandler_check(zval *handler_name TSRMLS_DC); php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); extern php_stream_ops php_stream_gzio_ops; http://cvs.php.net/viewcvs.cgi/php-src/ext/zlib/zlib.c?r1=1.193&r2=1.194&diff_format=u Index: php-src/ext/zlib/zlib.c diff -u php-src/ext/zlib/zlib.c:1.193 php-src/ext/zlib/zlib.c:1.194 --- php-src/ext/zlib/zlib.c:1.193 Sat Apr 29 14:38:35 2006 +++ php-src/ext/zlib/zlib.c Fri Jun 2 19:51:42 2006 @@ -13,13 +13,13 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | - | Stefan Röhrich <sr@linux.de> | + | Stefan R�rich <sr@linux.de> | | Zeev Suraski <zeev@zend.com> | | Jade Nicoletti <nicoletti@nns.ch> | +----------------------------------------------------------------------+ */ -/* $Id: zlib.c,v 1.193 2006/04/29 14:38:35 fmk Exp $ */ +/* $Id: zlib.c,v 1.194 2006/06/02 19:51:42 mike Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -211,11 +211,15 @@ */ PHP_MINIT_FUNCTION(zlib) { + zval tmp; #ifdef ZTS ts_allocate_id(&zlib_globals_id, sizeof(zend_zlib_globals), (ts_allocate_ctor) php_zlib_init_globals, NULL); #endif 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); + INIT_PZVAL(&tmp); + ZVAL_ASCII_STRINGL(&tmp, "ob_gzhandler", sizeof("ob_gzhandler")-1, 0); + php_output_handler_conflict_register(&tmp, php_ob_gzhandler_check); REGISTER_LONG_CONSTANT("FORCE_GZIP", CODING_GZIP, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FORCE_DEFLATE", CODING_DEFLATE, CONST_CS | CONST_PERSISTENT); @@ -828,30 +832,41 @@ /* {{{ php_ob_gzhandler_check */ -int php_ob_gzhandler_check(TSRMLS_D) +int php_ob_gzhandler_check(zval *handler_name TSRMLS_DC) { /* check for wrong usages */ - if (OG(ob_nesting_level > 0)) { - if (php_ob_handler_used("ob_gzhandler" TSRMLS_CC)) { + if (php_output_get_level() > 0) { + zval tmp; + + if (php_output_handler_started(handler_name)) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used twice"); return FAILURE; } - if (php_ob_handler_used("mb_output_handler" TSRMLS_CC)) { + INIT_PZVAL(&tmp); + ZVAL_ASCII_STRINGL(&tmp, "mb_output_handler", sizeof("mb_output_handler")-1, ZSTR_DUPLICATE); + if (php_output_handler_started(&tmp)) { + zval_dtor(&tmp); 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)) { + zval_dtor(&tmp); + ZVAL_ASCII_STRINGL(&tmp, "URL-Reqriter", sizeof("URL-Rewriter")-1, ZSTR_DUPLICATE); + if (php_output_handler_started(&tmp)) { + zval_dtor(&tmp); 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)) { + zval_dtor(&tmp); + ZVAL_ASCII_STRINGL(&tmp, "zlib output compression", sizeof("zlib output compression")-1, ZSTR_DUPLICATE); + if (php_output_handler_conflict(handler_name, &tmp)) { + zval_dtor(&tmp); return FAILURE; } + zval_dtor(&tmp); } return SUCCESS; } - /* }}} */ /* {{{ proto string ob_gzhandler(string str, int mode) @@ -869,8 +884,9 @@ return; } - if(ZLIBG(ob_gzhandler_status) == -1) + if(ZLIBG(ob_gzhandler_status) == -1) { RETURN_FALSE; + } zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); @@ -878,16 +894,20 @@ || 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; + 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; + } + } + + if (ZLIBG(ob_gzhandler_status == -1)) { + /* don't call this handler any more */ + php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_DISABLE, NULL); RETURN_FALSE; } @@ -931,8 +951,13 @@ } if (return_original) { + /* don't call this handler any more */ + php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_DISABLE, NULL); /* return the original string */ RETURN_STRINGL(string, string_len, 1); + } else { + /* don't allow cleaning and removing any longer */ + php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL); } } /* }}} */ @@ -959,7 +984,7 @@ */ int php_enable_output_compression(int buffer_size TSRMLS_DC) { - zval **a_encoding; + zval **a_encoding, *output_handler; zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); @@ -979,10 +1004,16 @@ 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); + MAKE_STD_ZVAL(output_handler); + ZVAL_ASCII_STRINGL(output_handler, "zlib output compression", sizeof("zlib output compression")-1, ZSTR_DUPLICATE); + php_output_start_internal(output_handler, php_gzip_output_handler, buffer_size, PHP_OUTPUT_HANDLER_STDFLAGS); + zval_ptr_dtor(&output_handler); + + if (ZLIBG(output_handler) && *ZLIBG(output_handler)) { + MAKE_STD_ZVAL(output_handler); + ZVAL_ASCII_STRING(output_handler, ZLIBG(output_handler), ZSTR_DUPLICATE); + php_output_start_user(output_handler, 0, PHP_OUTPUT_HANDLER_STDFLAGS); + zval_ptr_dtor(&output_handler); } return SUCCESS; } http://cvs.php.net/viewcvs.cgi/php-src/main/SAPI.c?r1=1.214&r2=1.215&diff_format=u Index: php-src/main/SAPI.c diff -u php-src/main/SAPI.c:1.214 php-src/main/SAPI.c:1.215 --- php-src/main/SAPI.c:1.214 Wed May 10 21:25:01 2006 +++ php-src/main/SAPI.c Fri Jun 2 19:51:42 2006 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: SAPI.c,v 1.214 2006/05/10 21:25:01 rasmus Exp $ */ +/* $Id: SAPI.c,v 1.215 2006/06/02 19:51:42 mike Exp $ */ #include <ctype.h> #include <sys/stat.h> @@ -553,8 +553,8 @@ int http_response_code; if (SG(headers_sent) && !SG(request_info).no_headers) { - char *output_start_filename = php_get_output_start_filename(TSRMLS_C); - int output_start_lineno = php_get_output_start_lineno(TSRMLS_C); + char *output_start_filename = php_output_get_start_filename(); + int output_start_lineno = php_output_get_start_lineno(); if (output_start_filename) { sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent by (output started at %s:%d)", @@ -720,6 +720,7 @@ } #if HAVE_ZLIB + /* TODO: move to zlib.c */ /* Add output compression headers at this late stage in order to make it possible to switch it off inside the script. */ http://cvs.php.net/viewcvs.cgi/php-src/main/main.c?r1=1.692&r2=1.693&diff_format=u Index: php-src/main/main.c diff -u php-src/main/main.c:1.692 php-src/main/main.c:1.693 --- php-src/main/main.c:1.692 Sat May 27 20:53:38 2006 +++ php-src/main/main.c Fri Jun 2 19:51:42 2006 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: main.c,v 1.692 2006/05/27 20:53:38 johannes Exp $ */ +/* $Id: main.c,v 1.693 2006/06/02 19:51:42 mike Exp $ */ /* {{{ includes */ @@ -234,8 +234,8 @@ #define PHP_INI_OPTION_HEADERS_SENT(option_name) \ if (SG(headers_sent)) { \ - char *output_start_filename = php_get_output_start_filename(TSRMLS_C); \ - int output_start_lineno = php_get_output_start_lineno(TSRMLS_C); \ + char *output_start_filename = php_output_get_start_filename(); \ + int output_start_lineno = php_output_get_start_lineno(); \ if (output_start_filename) { \ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Option " #option_name " cannot be changed after headers have been sent (output started at %s:%d)", \ output_start_filename, output_start_lineno); \ @@ -870,14 +870,7 @@ php_log_err(log_buffer TSRMLS_CC); efree(log_buffer); } - if (PG(display_errors) - && ((module_initialized && !PG(during_request_startup)) - || (PG(display_startup_errors) - && (OG(php_body_write)==php_default_output_func || OG(php_body_write)==php_ub_body_write_no_header || OG(php_body_write)==php_ub_body_write) - ) - ) - ) { - + if (PG(display_errors) && ((module_initialized && !PG(during_request_startup)) || (PG(display_startup_errors)))) { if (PG(xmlrpc_errors)) { php_printf("<?xml version=\"1.0\"?><methodResponse><fault><value><struct><member><name>faultCode</name><value><int>%ld</int></value></member><member><name>faultString</name><value><string>%s:%s in %s on line %d</string></value></member></struct></value></fault></methodResponse>", PG(xmlrpc_error_number), error_type_str, buffer, error_filename, error_lineno); } else { @@ -1182,7 +1175,7 @@ zend_try { PG(during_request_startup) = 1; - php_output_activate(TSRMLS_C); + php_output_activate(); /* initialize global variables */ PG(modules_activated) = 0; @@ -1208,15 +1201,16 @@ } if (PG(output_handler) && PG(output_handler)[0]) { - php_start_ob_buffer_named(PG(output_handler), 0, 1 TSRMLS_CC); + zval *oh; + + MAKE_STD_ZVAL(oh); + ZVAL_ASCII_STRING(oh, PG(output_handler), ZSTR_DUPLICATE); + php_output_start_user(oh, 0, PHP_OUTPUT_HANDLER_STDFLAGS); + zval_ptr_dtor(&oh); } else if (PG(output_buffering)) { - if (PG(output_buffering)>1) { - php_start_ob_buffer(NULL, PG(output_buffering), 1 TSRMLS_CC); - } else { - php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC); - } + php_output_start_user(NULL, PG(output_buffering) > 1 ? PG(output_buffering) : 0, PHP_OUTPUT_HANDLER_STDFLAGS); } else if (PG(implicit_flush)) { - php_start_implicit_flush(TSRMLS_C); + php_output_set_implicit_flush(1); } /* We turn this off in php_execute_script() */ @@ -1246,13 +1240,12 @@ return FAILURE; } - php_output_activate(TSRMLS_C); + php_output_activate(); sapi_activate(TSRMLS_C); php_hash_environment(TSRMLS_C); zend_try { PG(during_request_startup) = 1; - php_output_activate(TSRMLS_C); if (PG(expose_php)) { sapi_add_header(SAPI_PHP_VERSION_HEADER, sizeof(SAPI_PHP_VERSION_HEADER)-1, 1); } @@ -1279,7 +1272,7 @@ return FAILURE; } - php_output_activate(TSRMLS_C); + php_output_activate(); sapi_activate_headers_only(TSRMLS_C); php_hash_environment(TSRMLS_C); @@ -1372,7 +1365,12 @@ /* 3. Flush all output buffers */ zend_try { - php_end_ob_buffers((zend_bool)(SG(request_info).headers_only?0:1) TSRMLS_CC); + if (SG(request_info).headers_only) { + php_output_discard_all(); + } else { + php_output_end_all(); + } + php_output_deactivate(); } zend_end_try(); /* 4. Send the set HTTP headers (note: This must be done AFTER php_end_ob_buffers() !!) */ @@ -1432,12 +1430,12 @@ /* }}} */ -/* {{{ php_body_write_wrapper +/* {{{ php_output_wrapper */ -static int php_body_write_wrapper(const char *str, uint str_length) +static int php_output_wrapper(const char *str, uint str_length) { TSRMLS_FETCH(); - return php_body_write(str, str_length TSRMLS_CC); + return php_output_write(str, str_length); } /* }}} */ @@ -1523,7 +1521,7 @@ zuf.error_function = php_error_cb; zuf.printf_function = php_printf; - zuf.write_function = php_body_write_wrapper; + zuf.write_function = php_output_wrapper; zuf.fopen_function = php_fopen_wrapper_for_zend; zuf.message_handler = php_message_handler_for_zend; zuf.block_interruptions = sapi_module.block_interruptions; @@ -1667,7 +1665,7 @@ REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS); REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MAX", LONG_MAX, CONST_PERSISTENT | CONST_CS); REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", sizeof(long), CONST_PERSISTENT | CONST_CS); - php_output_register_constants(TSRMLS_C); + php_output_register_constants(); php_rfc1867_register_constants(TSRMLS_C); if (php_startup_ticks(TSRMLS_C) == FAILURE) { @@ -1785,6 +1783,8 @@ zend_ini_global_shutdown(TSRMLS_C); #endif + php_output_shutdown(); + module_initialized = 0; if (PG(last_error_message)) { free(PG(last_error_message)); @@ -1946,7 +1946,7 @@ TSRMLS_FETCH(); PG(connection_status) = PHP_CONNECTION_ABORTED; - php_output_set_status(0 TSRMLS_CC); + php_output_set_status(PHP_OUTPUT_DISABLED); if (!PG(ignore_user_abort)) { zend_bailout(); http://cvs.php.net/viewcvs.cgi/php-src/main/output.c?r1=1.177&r2=1.178&diff_format=u Index: php-src/main/output.c diff -u php-src/main/output.c:1.177 php-src/main/output.c:1.178 --- php-src/main/output.c:1.177 Mon Mar 27 08:26:20 2006 +++ php-src/main/output.c Fri Jun 2 19:51:42 2006 @@ -1,4 +1,4 @@ -/* +/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ @@ -15,801 +15,1209 @@ | Authors: Zeev Suraski <zeev@zend.com> | | Thies C. Arntzen <thies@thieso.net> | | Marcus Boerger <helly@php.net> | + | New API: Michael Wallner <mike@php.net> | +----------------------------------------------------------------------+ */ -/* $Id: output.c,v 1.177 2006/03/27 08:26:20 tony2001 Exp $ */ +/* $Id: output.c,v 1.178 2006/06/02 19:51:42 mike Exp $ */ + +#ifndef PHP_OUTPUT_DEBUG +# define PHP_OUTPUT_DEBUG 0 +#endif +#ifndef PHP_OUTPUT_NOINLINE +# define PHP_OUTPUT_NOINLINE 0 +#endif #include "php.h" #include "ext/standard/head.h" -#include "ext/standard/basic_functions.h" #include "ext/standard/url_scanner_ex.h" -#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB) -#include "ext/zlib/php_zlib.h" -#endif #include "SAPI.h" +#include "zend_stack.h" +#include "php_output.h" -#define OB_DEFAULT_HANDLER_NAME "default output handler" - -/* output functions */ -static int php_b_body_write(const char *str, uint str_length TSRMLS_DC); +ZEND_DECLARE_MODULE_GLOBALS(output); -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); +#if PHP_OUTPUT_NOINLINE || PHP_OUTPUT_DEBUG +# undef inline +# define inline #endif -#ifdef ZTS -int output_globals_id; -#else -php_output_globals output_globals; -#endif +/* {{{ aliases, conflict and reverse conflict hash tables */ +static HashTable php_output_handler_aliases; +static HashTable php_output_handler_conflicts; +static HashTable php_output_handler_reverse_conflicts; +/* }}} */ + +/* {{{ forward declarations */ +static inline int php_output_lock_error(int op TSRMLS_DC); +static inline void php_output_op(int op, const char *str, size_t len TSRMLS_DC); + +static inline php_output_handler *php_output_handler_init(zval *name, size_t chunk_size, int flags); +static inline int php_output_handler_op(php_output_handler *handler, php_output_context *context); +static inline int php_output_handler_append(php_output_handler *handler, const php_output_buffer *buf TSRMLS_DC); +static inline zval *php_output_handler_status(php_output_handler *handler, zval *entry); + +static inline php_output_context *php_output_context_init(php_output_context *context, int op TSRMLS_DC); +static inline void php_output_context_reset(php_output_context *context); +static inline void php_output_context_swap(php_output_context *context); +static inline void php_output_context_dtor(php_output_context *context); + +static inline int php_output_stack_pop(int discard, int shutdown TSRMLS_DC); -/* {{{ php_default_output_func */ -PHPAPI int php_default_output_func(const char *str, uint str_len TSRMLS_DC) +static int php_output_stack_apply_op(void *h, void *c); +static int php_output_stack_apply_clean(void *h, void *c); +static int php_output_stack_apply_list(void *h, void *z); +static int php_output_stack_apply_status(void *h, void *z); + +static int php_output_handler_compat_func(void **handler_context, php_output_context *output_context); +static int php_output_handler_default_func(void **handler_context, php_output_context *output_context); +static int php_output_handler_devnull_func(void **handler_context, php_output_context *output_context); +/* }}} */ + +/* {{{ static void php_output_init_globals(zend_output_globals *G) + Initialize the module globals on MINIT */ +static inline void php_output_init_globals(zend_output_globals *G) { - fwrite(str, 1, str_len, stderr); - return str_len; + memset(G, 0, sizeof(*G)); } /* }}} */ -/* {{{ php_output_init_globals */ -static void php_output_init_globals(php_output_globals *output_globals_p TSRMLS_DC) +/* {{{ void php_output_startup(void) + Set up module globals and initalize the conflict and reverse conflict hash tables */ +PHPAPI void php_output_startup(void) { - OG(php_body_write) = php_default_output_func; - OG(php_header_write) = php_default_output_func; - OG(implicit_flush) = 0; - OG(output_start_filename) = NULL; - OG(output_start_lineno) = 0; + ZEND_INIT_MODULE_GLOBALS(output, php_output_init_globals, NULL); + zend_hash_init(&php_output_handler_aliases, 0, NULL, NULL, 1); + zend_hash_init(&php_output_handler_conflicts, 0, NULL, NULL, 1); + zend_hash_init(&php_output_handler_reverse_conflicts, 0, NULL, (void (*)(void *)) zend_hash_destroy, 1); } /* }}} */ +/* {{{ void php_output_shutdown(void) + Destroy module globals and the conflict and reverse conflict hash tables */ +PHPAPI void php_output_shutdown(void) +{ + zend_hash_destroy(&php_output_handler_aliases); + zend_hash_destroy(&php_output_handler_conflicts); + zend_hash_destroy(&php_output_handler_reverse_conflicts); +} +/* }}} */ -/* {{{ php_output_startup - Start output layer */ -PHPAPI void php_output_startup(void) +/* {{{ SUCCESS|FAILURE php_output_activate(TSRMLS_D) + Reset output globals and setup the output handler stack */ +PHPAPI int _php_output_activate(TSRMLS_D) { #ifdef ZTS - ts_allocate_id(&output_globals_id, sizeof(php_output_globals), (ts_allocate_ctor) php_output_init_globals, NULL); -#else - php_output_init_globals(&output_globals TSRMLS_CC); + memset((*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(output_globals_id)], 0, sizeof(zend_output_globals)); +#else + memset(&output_globals, 0, sizeof(zend_output_globals)); #endif + if (SUCCESS != zend_stack_init(&OG(handlers))) { + return FAILURE; + } + + MAKE_STD_ZVAL(OG(default_output_handler_name)); + ZVAL_ASCII_STRINGL(OG(default_output_handler_name), "default output handler", sizeof("default output handler")-1, ZSTR_DUPLICATE); + MAKE_STD_ZVAL(OG(devnull_output_handler_name)); + ZVAL_ASCII_STRINGL(OG(devnull_output_handler_name), "null output handler", sizeof("null output handler")-1, ZSTR_DUPLICATE); + + return SUCCESS; } /* }}} */ - -/* {{{ php_output_activate - Initilize output global for activation */ -PHPAPI void php_output_activate(TSRMLS_D) +/* {{{ void php_output_deactivate(TSRMLS_D) + Destroy the output handler stack */ +PHPAPI void _php_output_deactivate(TSRMLS_D) { - OG(php_body_write) = php_ub_body_write; - OG(php_header_write) = sapi_module.ub_write; - OG(ob_nesting_level) = 0; - OG(ob_lock) = 0; - OG(disable_output) = 0; - OG(output_start_filename) = NULL; - OG(output_start_lineno) = 0; + php_output_handler **handler = NULL; + + OG(active) = NULL; + OG(running) = NULL; + /* release all output handlers */ + while (SUCCESS == zend_stack_top(&OG(handlers), (void *) &handler)) { + php_output_handler_free(handler); + zend_stack_del_top(&OG(handlers)); + } + zend_stack_destroy(&OG(handlers)); + + zval_ptr_dtor(&OG(default_output_handler_name)); + zval_ptr_dtor(&OG(devnull_output_handler_name)); } /* }}} */ +/* {{{ void _php_output_register_constants() */ +PHPAPI void _php_output_register_constants(TSRMLS_D) +{ + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_START", PHP_OUTPUT_HANDLER_START, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_WRITE", PHP_OUTPUT_HANDLER_WRITE, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_FLUSH", PHP_OUTPUT_HANDLER_FLUSH, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CLEAN", PHP_OUTPUT_HANDLER_CLEAN, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_FINAL", PHP_OUTPUT_HANDLER_FINAL, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CONT", PHP_OUTPUT_HANDLER_WRITE, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_END", PHP_OUTPUT_HANDLER_FINAL, CONST_CS | CONST_PERSISTENT); + + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CLEANABLE", PHP_OUTPUT_HANDLER_CLEANABLE, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_REMOVABLE", PHP_OUTPUT_HANDLER_REMOVABLE, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_STDFLAGS", PHP_OUTPUT_HANDLER_STDFLAGS, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_STARTED", PHP_OUTPUT_HANDLER_STARTED, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_DISABLED", PHP_OUTPUT_HANDLER_DISABLED, CONST_CS | CONST_PERSISTENT); +} +/* }}} */ -/* {{{ php_output_set_status - Toggle output status. Do NOT use in application code, only in SAPIs where appropriate. */ -PHPAPI void php_output_set_status(zend_bool status TSRMLS_DC) +/* {{{ void php_output_set_status(int status) + Used by SAPIs to disable output */ +PHPAPI void _php_output_set_status(int status TSRMLS_DC) { - OG(disable_output) = !status; + OG(flags) = status & 0xf; } /* }}} */ -/* {{{ php_output_register_constants */ -void php_output_register_constants(TSRMLS_D) +/* {{{ int php_output_get_status() + Get output control status */ +PHPAPI int _php_output_get_status(TSRMLS_D) { - REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_START", PHP_OUTPUT_HANDLER_START, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CONT", PHP_OUTPUT_HANDLER_CONT, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_END", PHP_OUTPUT_HANDLER_END, CONST_CS | CONST_PERSISTENT); + return OG(flags) + | (OG(active) ? PHP_OUTPUT_ACTIVE : 0) + | (OG(running)? PHP_OUTPUT_LOCKED : 0); } /* }}} */ +/* {{{ zval *php_output_get_default_handler_name() */ +PHPAPI zval *_php_output_get_default_handler_name(TSRMLS_D) +{ + return OG(default_output_handler_name); +} +/* }}} */ -/* {{{ php_body_wirte - * Write body part */ -PHPAPI int php_body_write(const char *str, uint str_length TSRMLS_DC) +/* {{{ zval *php_output_get_devnull_handler_name() */ +PHPAPI zval *_php_output_get_devnull_handler_name(TSRMLS_D) { - return OG(php_body_write)(str, str_length TSRMLS_CC); + return OG(devnull_output_handler_name); } /* }}} */ -/* {{{ php_header_wirte - * Write HTTP header */ -PHPAPI int php_header_write(const char *str, uint str_length TSRMLS_DC) +/* {{{ int php_output_write_unbuffered(const char *str, size_t len) + Unbuffered write */ +PHPAPI int _php_output_write_unbuffered(const char *str, size_t len TSRMLS_DC) { - if (OG(disable_output)) { + if (OG(flags) & PHP_OUTPUT_DISABLED) { return 0; - } else { - return OG(php_header_write)(str, str_length TSRMLS_CC); } + return sapi_module.ub_write(str, len TSRMLS_CC); } /* }}} */ -/* {{{ php_start_ob_buffer - * Start output buffering */ -PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC) +/* {{{ int php_output_write(const char *str, size_t len) + Buffered write */ +PHPAPI int _php_output_write(const char *str, size_t len TSRMLS_DC) { - uint initial_size, block_size; - - if (OG(ob_lock)) { - 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_docref("ref.outcontrol" TSRMLS_CC, E_ERROR, "Cannot use output buffering in output buffering display handlers"); - return FAILURE; + if (OG(flags) & PHP_OUTPUT_DISABLED) { + return 0; } - if (chunk_size > 0) { - if (chunk_size==1) { - chunk_size = 4096; + php_output_op(PHP_OUTPUT_HANDLER_WRITE, str, len TSRMLS_CC); + return (int) len; +} +/* }}} */ + +/* {{{ void php_output_flush() + Flush the most recent output handlers buffer */ +PHPAPI void _php_output_flush(TSRMLS_D) +{ + php_output_context context; + + if (OG(active)) { + php_output_context_init(&context, PHP_OUTPUT_HANDLER_FLUSH TSRMLS_CC); + php_output_handler_op(OG(active), &context); + if (context.out.data && context.out.used) { + zend_stack_del_top(&OG(handlers)); + php_output_write(context.out.data, context.out.used); + zend_stack_push(&OG(handlers), &OG(active), sizeof(php_output_handler *)); } - initial_size = (chunk_size*3/2); - block_size = chunk_size/2; - } else { - initial_size = 40*1024; - block_size = 10*1024; + php_output_context_dtor(&context); } - 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) +/* {{{ void php_output_flush_all() + Flush all output buffers subsequently */ +PHPAPI void _php_output_flush_all(TSRMLS_D) { - 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; + if (OG(active)) { + php_output_op(PHP_OUTPUT_HANDLER_FLUSH, NULL, 0 TSRMLS_CC); + } } /* }}} */ -/* {{{ php_end_ob_buffer - * End output buffering (one level) */ -PHPAPI void php_end_ob_buffer(zend_bool send_buffer, zend_bool just_flush TSRMLS_DC) +/* {{{ SUCCESS|FAILURE php_output_clean() + Cleans the most recent output handlers buffer if the handler is cleanable */ +PHPAPI int _php_output_clean(TSRMLS_D) { - char *final_buffer=NULL; - unsigned int final_buffer_length=0; - zval *alternate_buffer=NULL; - char *to_be_destroyed_buffer, *to_be_destroyed_handler_name; - char *to_be_destroyed_handled_output[2] = { 0, 0 }; - int status; - php_ob_buffer *prev_ob_buffer_p=NULL; - php_ob_buffer orig_ob_buffer; - - if (OG(ob_nesting_level)==0) { - return; - } - status = 0; - if (!OG(active_ob_buffer).status & PHP_OUTPUT_HANDLER_START) { - /* our first call */ - status |= PHP_OUTPUT_HANDLER_START; - } - if (just_flush) { - status |= PHP_OUTPUT_HANDLER_CONT; - } else { - status |= PHP_OUTPUT_HANDLER_END; + php_output_context context; + + if (OG(active) && (OG(active)->flags & PHP_OUTPUT_HANDLER_CLEANABLE)) { + OG(active)->buffer.used = 0; + php_output_context_init(&context, PHP_OUTPUT_HANDLER_CLEAN TSRMLS_CC); + php_output_handler_op(OG(active), &context); + php_output_context_dtor(&context); + return SUCCESS; } + return FAILURE; +} +/* }}} */ -#if 0 - { - FILE *fp; - fp = fopen("/tmp/ob_log", "a"); - fprintf(fp, "NestLevel: %d ObStatus: %d HandlerName: %s\n", OG(ob_nesting_level), status, OG(active_ob_buffer).handler_name.s); - fclose(fp); - } -#endif +/* {{{ void php_output_clean_all() + Cleans all output handler buffers, without regard whether the handler is cleanable */ +PHPAPI void _php_output_clean_all(TSRMLS_D) +{ + php_output_context context; - if (OG(active_ob_buffer).internal_output_handler) { - final_buffer = OG(active_ob_buffer).internal_output_handler_buffer; - final_buffer_length = OG(active_ob_buffer).internal_output_handler_buffer_size; - OG(active_ob_buffer).internal_output_handler(OG(active_ob_buffer).buffer, OG(active_ob_buffer).text_length, &final_buffer, &final_buffer_length, status TSRMLS_CC); - } else if (OG(active_ob_buffer).output_handler) { - zval **params[2]; - zval *orig_buffer; - zval *z_status; - - ALLOC_INIT_ZVAL(orig_buffer); - ZVAL_U_STRINGL(ZEND_U_CONVERTER(UG(output_encoding_conv)), orig_buffer, OG(active_ob_buffer).buffer, OG(active_ob_buffer).text_length, 1); - orig_buffer->refcount=2; /* don't let call_user_function() destroy our buffer */ - orig_buffer->is_ref=1; - - ALLOC_INIT_ZVAL(z_status); - ZVAL_LONG(z_status, status); - - params[0] = &orig_buffer; - params[1] = &z_status; - OG(ob_lock) = 1; - - if (call_user_function_ex(CG(function_table), NULL, OG(active_ob_buffer).output_handler, &alternate_buffer, 2, params, 1, NULL TSRMLS_CC)==SUCCESS) { - if (alternate_buffer && !(Z_TYPE_P(alternate_buffer)==IS_BOOL && Z_BVAL_P(alternate_buffer)==0)) { - convert_to_string_ex(&alternate_buffer); - final_buffer = Z_STRVAL_P(alternate_buffer); - final_buffer_length = Z_STRLEN_P(alternate_buffer); - } - } - OG(ob_lock) = 0; - if (!just_flush) { - zval_ptr_dtor(&OG(active_ob_buffer).output_handler); - } - orig_buffer->refcount -=2; - if (orig_buffer->refcount <= 0) { /* free the zval */ - zval_dtor(orig_buffer); - FREE_ZVAL(orig_buffer); - } - zval_ptr_dtor(&z_status); + if (OG(active)) { + php_output_context_init(&context, PHP_OUTPUT_HANDLER_CLEAN TSRMLS_CC); + zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_TOPDOWN, php_output_stack_apply_clean, &context); } +} - if (!final_buffer) { - final_buffer = OG(active_ob_buffer).buffer; - final_buffer_length = OG(active_ob_buffer).text_length; +/* {{{ SUCCESS|FAILURE php_output_end() + Finalizes the most recent output handler at pops it off the stack if the handler is removable */ +PHPAPI int _php_output_end(TSRMLS_D) +{ + if (php_output_stack_pop(0, 0 TSRMLS_CC)) { + return SUCCESS; } + return FAILURE; +} +/* }}} */ - if (OG(ob_nesting_level)==1) { /* end buffering */ - 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; - } - } +/* {{{ void php_output_end_all() + Finalizes all output handlers and ends output buffering without regard whether a handler is removable */ +PHPAPI void _php_output_end_all(TSRMLS_D) +{ + while (OG(active) && php_output_stack_pop(0, 1 TSRMLS_CC)); +} +/* }}} */ - to_be_destroyed_buffer = OG(active_ob_buffer).buffer; - /* FIXME: unicode support??? */ - to_be_destroyed_handler_name = OG(active_ob_buffer).handler_name.s; - if (OG(active_ob_buffer).internal_output_handler - && (final_buffer != OG(active_ob_buffer).internal_output_handler_buffer) - && (final_buffer != OG(active_ob_buffer).buffer)) { - to_be_destroyed_handled_output[0] = final_buffer; +/* {{{ SUCCESS|FAILURE php_output_discard() + Discards the most recent output handlers buffer and pops it off the stack if the handler is removable */ +PHPAPI int _php_output_discard(TSRMLS_D) +{ + if (php_output_stack_pop(1, 0 TSRMLS_CC)) { + return SUCCESS; } + return FAILURE; +} +/* }}} */ - if (!just_flush) { - if (OG(active_ob_buffer).internal_output_handler) { - to_be_destroyed_handled_output[1] = OG(active_ob_buffer).internal_output_handler_buffer; - } - } - if (OG(ob_nesting_level)>1) { /* restore previous buffer */ - zend_stack_top(&OG(ob_buffers), (void **) &prev_ob_buffer_p); - orig_ob_buffer = OG(active_ob_buffer); - OG(active_ob_buffer) = *prev_ob_buffer_p; - zend_stack_del_top(&OG(ob_buffers)); - if (!just_flush && OG(ob_nesting_level)==2) { /* destroy the stack */ - zend_stack_destroy(&OG(ob_buffers)); - } +/* {{{ void php_output_discard_all() + Discard all output handlers and buffers without regard whether a handler is removable */ +PHPAPI void _php_output_discard_all(TSRMLS_D) +{ + while (OG(active)) { + php_output_stack_pop(1, 1 TSRMLS_CC); } - OG(ob_nesting_level)--; +} +/* }}} */ - if (send_buffer) { - if (just_flush) { /* if flush is called prior to proper end, ensure presence of NUL */ - final_buffer[final_buffer_length] = '\0'; - } - OG(php_body_write)(final_buffer, final_buffer_length TSRMLS_CC); +/* {{{ int php_output_get_level() + Get output buffering level, ie. how many output handlers the stack contains */ +PHPAPI int _php_output_get_level(TSRMLS_D) +{ + return OG(active) ? zend_stack_count(&OG(handlers)) : 0; +} +/* }}} */ + +/* {{{ SUCCESS|FAILURE php_output_get_contents(zval *z) + Get the contents of the active output handlers buffer */ +PHPAPI int _php_output_get_contents(zval *p TSRMLS_DC) +{ + if (OG(active)) { + ZVAL_STRINGL(p, OG(active)->buffer.data, OG(active)->buffer.used, 1); + return SUCCESS; + } else { + ZVAL_NULL(p); + return FAILURE; } +} - if (just_flush) { /* we restored the previous ob, return to the current */ - if (prev_ob_buffer_p) { - zend_stack_push(&OG(ob_buffers), &OG(active_ob_buffer), sizeof(php_ob_buffer)); - OG(active_ob_buffer) = orig_ob_buffer; - } - OG(ob_nesting_level)++; +/* {{{ SUCCESS|FAILURE php_output_get_length(zval *z) + Get the length of the active output handlers buffer */ +PHPAPI int _php_output_get_length(zval *p TSRMLS_DC) +{ + if (OG(active)) { + ZVAL_LONG(p, OG(active)->buffer.used); + return SUCCESS; + } else { + ZVAL_NULL(p); + return FAILURE; } +} +/* }}} */ - if (alternate_buffer) { - zval_ptr_dtor(&alternate_buffer); +/* {{{ SUCCESS|FAILURE php_output_handler_start_default() + Start a "default output handler" */ +PHPAPI int _php_output_start_default(TSRMLS_D) +{ + php_output_handler *handler; + + handler = php_output_handler_create_internal(OG(default_output_handler_name), php_output_handler_default_func, 0, PHP_OUTPUT_HANDLER_STDFLAGS); + if (SUCCESS == php_output_handler_start(handler)) { + return SUCCESS; } + php_output_handler_free(&handler); + return FAILURE; +} +/* }}} */ - if (status & PHP_OUTPUT_HANDLER_END) { - efree(to_be_destroyed_handler_name); +/* {{{ SUCCESS|FAILURE php_output_handler_start_devnull() + Start a "null output handler" */ +PHPAPI int _php_output_start_devnull(TSRMLS_D) +{ + php_output_handler *handler; + + handler = php_output_handler_create_internal(OG(devnull_output_handler_name), php_output_handler_devnull_func, PHP_OUTPUT_HANDLER_DEFAULT_SIZE, 0); + if (SUCCESS == php_output_handler_start(handler)) { + return SUCCESS; } - if (!just_flush) { - efree(to_be_destroyed_buffer); + php_output_handler_free(&handler); + return FAILURE; +} +/* }}} */ + +/* {{{ SUCCESS|FAILURE php_output_start_user(zval *handler, size_t chunk_size, int flags) + Start a user level output handler */ +PHPAPI int _php_output_start_user(zval *output_handler, size_t chunk_size, int flags TSRMLS_DC) +{ + php_output_handler *handler; + + if (output_handler) { + handler = php_output_handler_create_user(output_handler, chunk_size, flags); } else { - OG(active_ob_buffer).text_length = 0; - OG(active_ob_buffer).status |= PHP_OUTPUT_HANDLER_START; - OG(php_body_write) = php_b_body_write; + handler = php_output_handler_create_internal(OG(default_output_handler_name), php_output_handler_default_func, chunk_size, flags); } - if (to_be_destroyed_handled_output[0]) { - efree(to_be_destroyed_handled_output[0]); - } - if (to_be_destroyed_handled_output[1]) { - efree(to_be_destroyed_handled_output[1]); + if (SUCCESS == php_output_handler_start(handler)) { + return SUCCESS; } + php_output_handler_free(&handler); + return FAILURE; } /* }}} */ -/* {{{ php_end_ob_buffers - * End output buffering (all buffers) */ -PHPAPI void php_end_ob_buffers(zend_bool send_buffer TSRMLS_DC) +/* {{{ SUCCESS|FAILURE php_output_start_internal(const char *name, php_output_handler_func_t handler, size_t chunk_size, int flags) + Start an internal output handler that does not have to maintain a non-global state */ +PHPAPI int _php_output_start_internal(zval *name, php_output_handler_func_t output_handler, size_t chunk_size, int flags TSRMLS_DC) { - while (OG(ob_nesting_level)!=0) { - php_end_ob_buffer(send_buffer, 0 TSRMLS_CC); + php_output_handler *handler; + + handler = php_output_handler_create_internal(name, php_output_handler_compat_func, chunk_size, flags); + php_output_handler_set_context(handler, output_handler, NULL); + if (SUCCESS == php_output_handler_start(handler)) { + return SUCCESS; } + php_output_handler_free(&handler); + return FAILURE; } /* }}} */ -/* {{{ php_start_implicit_flush - */ -PHPAPI void php_start_implicit_flush(TSRMLS_D) +/* {{{ php_output_handler *php_output_handler_create_user(zval *handler, size_t chunk_size, int flags) + Create a user level output handler */ +PHPAPI php_output_handler *_php_output_handler_create_user(zval *output_handler, size_t chunk_size, int flags TSRMLS_DC) { - OG(implicit_flush)=1; + zval *handler_name = NULL; + php_output_handler *handler = NULL; + php_output_handler_context_func_t *internal = NULL; + + switch (Z_TYPE_P(output_handler)) { + case IS_NULL: + break; + case IS_STRING: + case IS_UNICODE: + if (Z_UNILEN_P(output_handler) && (internal = php_output_handler_alias(output_handler))) { + return php_output_handler_create_internal(output_handler, *internal, chunk_size, flags); + } + default: + MAKE_STD_ZVAL(handler_name); + ZVAL_NULL(handler_name); + if (zend_is_callable(output_handler, 0, handler_name)) { + handler = php_output_handler_init(handler_name, chunk_size, (flags & ~0xf) | PHP_OUTPUT_HANDLER_USER); + ZVAL_ADDREF(output_handler); + handler->user = output_handler; + } + zval_ptr_dtor(&handler_name); + return handler; + } + + return php_output_handler_create_internal(OG(default_output_handler_name), php_output_handler_default_func, chunk_size, flags); } /* }}} */ -/* {{{ php_end_implicit_flush - */ -PHPAPI void php_end_implicit_flush(TSRMLS_D) +/* {{{ php_output_handler *php_output_handler_create_internal(const char *name, php_output_handler_context_func_t handler, size_t chunk_size, int flags) + Create an internal output handler that can maintain a non-global state */ +PHPAPI php_output_handler *_php_output_handler_create_internal(zval *name, php_output_handler_context_func_t output_handler, size_t chunk_size, int flags TSRMLS_DC) { - OG(implicit_flush)=0; + php_output_handler *handler; + + handler = php_output_handler_init(name, chunk_size, (flags & ~0xf) | PHP_OUTPUT_HANDLER_INTERNAL); + handler->internal = output_handler; + + return handler; } -/* }}} */ -/* {{{ php_ob_set_internal_handler - */ -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) +/* {{{ void php_output_handler_set_context(php_output_handler *handler, void *opaq, void (*dtor)(void* TSRMLS_DC)) + Set the context/state of an output handler. Calls the dtor of the previous context if there is one */ +PHPAPI void _php_output_handler_set_context(php_output_handler *handler, void *opaq, void (*dtor)(void* TSRMLS_DC) TSRMLS_DC) { - /* FIXME: Unicode support??? */ - if (OG(ob_nesting_level)==0 || OG(active_ob_buffer).internal_output_handler || strcmp(OG(active_ob_buffer).handler_name.s, OB_DEFAULT_HANDLER_NAME)) { - php_start_ob_buffer(NULL, buffer_size, erase TSRMLS_CC); + if (handler->dtor && handler->opaq) { + handler->dtor(handler->opaq TSRMLS_CC); } + handler->dtor = dtor; + handler->opaq = opaq; +} +/* }}} */ - OG(active_ob_buffer).internal_output_handler = internal_output_handler; - OG(active_ob_buffer).internal_output_handler_buffer = (char *) emalloc(buffer_size); - OG(active_ob_buffer).internal_output_handler_buffer_size = buffer_size; - if (OG(active_ob_buffer).handler_name.s) { - efree(OG(active_ob_buffer).handler_name.s); +/* {{{ SUCCESS|FAILURE php_output_handler_start(php_output_handler *handler) + Starts the set up output handler and pushes it on top of the stack. Checks for any conflicts regarding the output handler to start */ +PHPAPI int _php_output_handler_start(php_output_handler *handler TSRMLS_DC) +{ + HashTable *rconflicts; + php_output_handler_conflict_check_t *conflict; + + if (php_output_lock_error(PHP_OUTPUT_HANDLER_START TSRMLS_CC) || !handler) { + return FAILURE; } - OG(active_ob_buffer).handler_name.s = estrdup(handler_name); - OG(active_ob_buffer).erase = erase; + if (SUCCESS == zend_u_hash_find(&php_output_handler_conflicts, Z_TYPE_P(handler->name), Z_UNIVAL_P(handler->name), Z_UNILEN_P(handler->name), (void *) &conflict)) { + if (SUCCESS != (*conflict)(handler->name TSRMLS_CC)) { + return FAILURE; + } + } + if (SUCCESS == zend_u_hash_find(&php_output_handler_reverse_conflicts, Z_TYPE_P(handler->name), Z_UNIVAL_P(handler->name), Z_UNILEN_P(handler->name), (void *) &rconflicts)) { + for ( zend_hash_internal_pointer_reset(rconflicts); + zend_hash_get_current_data(rconflicts, (void *) &conflict) == SUCCESS; + zend_hash_move_forward(rconflicts)) { + if (SUCCESS != (*conflict)(handler->name TSRMLS_CC)) { + return FAILURE; + } + } + } + /* zend_stack_push never returns SUCCESS but FAILURE or stack level */ + if (FAILURE == (handler->level = zend_stack_push(&OG(handlers), &handler, sizeof(php_output_handler *)))) { + return FAILURE; + } + OG(active) = handler; + return SUCCESS; } /* }}} */ -/* - * Output buffering - implementation - */ - -/* {{{ php_ob_allocate - */ -static inline void php_ob_allocate(uint text_length TSRMLS_DC) +/* {{{ int php_output_handler_started(const char *name) + Check whether a certain output handler is in use */ +PHPAPI int _php_output_handler_started(zval *name TSRMLS_DC) { - uint new_len = OG(active_ob_buffer).text_length + text_length; - - if (OG(active_ob_buffer).size < new_len) { - uint buf_size = OG(active_ob_buffer).size; - while (buf_size <= new_len) { - buf_size += OG(active_ob_buffer).block_size; + php_output_handler **handlers; + int i, count = php_output_get_level(); + + if (count) { + handlers = *(php_output_handler ***) zend_stack_base(&OG(handlers)); + + for (i = 0; i < count; ++i) { + if (!zend_binary_zval_strcmp(handlers[i]->name, name)) { + return 1; + } } - - OG(active_ob_buffer).buffer = (char *) erealloc(OG(active_ob_buffer).buffer, buf_size+1); - OG(active_ob_buffer).size = buf_size; } - OG(active_ob_buffer).text_length = new_len; + + return 0; } /* }}} */ -/* {{{ php_ob_init_conflict - * Returns 1 if handler_set is already used and generates error message - */ -PHPAPI int php_ob_init_conflict(char *handler_new, char *handler_set TSRMLS_DC) +/* {{{ int php_output_handler_conflict(const char *handler_new, const char *handler_old) + Check whether a certain handler is in use and issue a warning that the new handler would conflict with the already used one */ +PHPAPI int _php_output_handler_conflict(zval *handler_new, zval *handler_set TSRMLS_DC) { - if (php_ob_handler_used(handler_set TSRMLS_CC)) { - php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler '%s' conflicts with '%s'", handler_new, handler_set); + if (php_output_handler_started(handler_set)) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler '%v' conflicts with '%v'", Z_UNIVAL_P(handler_new), Z_UNIVAL_P(handler_set)); return 1; } return 0; } /* }}} */ -/* {{{ php_ob_init_named - */ -static int php_ob_init_named(uint initial_size, uint block_size, zend_uchar type, zstr handler_name, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC) +/* {{{ SUCCESS|FAILURE php_output_handler_conflict_register(const char name[], php_output_handler_conflict_check_t check_func) + Register a conflict checking function on MINIT */ +PHPAPI int _php_output_handler_conflict_register(zval *name, php_output_handler_conflict_check_t check_func TSRMLS_DC) { - int handler_len; + if (!EG(current_module)) { + zend_error(E_ERROR, "Cannot register an output handler conflict outside of MINIT"); + return FAILURE; + } + return zend_u_hash_update(&php_output_handler_conflicts, Z_TYPE_P(name), Z_UNIVAL_P(name), Z_UNILEN_P(name), &check_func, sizeof(php_output_handler_conflict_check_t *), NULL); +} +/* }}} */ - if (output_handler && !zend_is_callable(output_handler, 0, NULL)) { +/* {{{ SUCCESS|FAILURE php_output_handler_reverse_conflict_register(const char name[], php_output_handler_conflict_check_t check_func) + Register a reverse conflict checking function on MINIT */ +PHPAPI int _php_output_handler_reverse_conflict_register(zval *name, php_output_handler_conflict_check_t check_func TSRMLS_DC) +{ + HashTable rev, *rev_ptr = NULL; + + if (!EG(current_module)) { + zend_error(E_ERROR, "Cannot register a reverse output handler conflict outside of MINIT"); return FAILURE; } - if (type == IS_UNICODE) { - handler_len = u_strlen(handler_name.u); + if (SUCCESS == zend_u_hash_find(&php_output_handler_reverse_conflicts, Z_TYPE_P(name), Z_UNIVAL_P(name), Z_UNILEN_P(name), (void *) &rev_ptr)) { + return zend_hash_next_index_insert(rev_ptr, &check_func, sizeof(php_output_handler_conflict_check_t *), NULL); } else { - handler_len = strlen(handler_name.s); - } - if (OG(ob_nesting_level)>0) { -#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB) - if ((handler_len == sizeof("ob_gzhandler")-1) && - (ZEND_U_EQUAL(type, handler_name, handler_len, "ob_gzhandler", sizeof("ob_gzhandler"))) && - php_ob_gzhandler_check(TSRMLS_C)) { + zend_hash_init(&rev, 1, NULL, NULL, 1); + if (SUCCESS != zend_hash_next_index_insert(&rev, &check_func, sizeof(php_output_handler_conflict_check_t *), NULL)) { + zend_hash_destroy(&rev); return FAILURE; } -#endif - if (OG(ob_nesting_level)==1) { /* initialize stack */ - zend_stack_init(&OG(ob_buffers)); + if (SUCCESS != zend_u_hash_update(&php_output_handler_reverse_conflicts, Z_TYPE_P(name), Z_UNIVAL_P(name), Z_UNILEN_P(name), &rev, sizeof(HashTable), NULL)) { + zend_hash_destroy(&rev); + return FAILURE; } - zend_stack_push(&OG(ob_buffers), &OG(active_ob_buffer), sizeof(php_ob_buffer)); + return SUCCESS; } - OG(ob_nesting_level)++; - OG(active_ob_buffer).block_size = block_size; - OG(active_ob_buffer).size = initial_size; - OG(active_ob_buffer).buffer = (char *) emalloc(initial_size+1); - OG(active_ob_buffer).text_length = 0; - OG(active_ob_buffer).output_handler = output_handler; - OG(active_ob_buffer).chunk_size = chunk_size; - OG(active_ob_buffer).status = 0; - OG(active_ob_buffer).internal_output_handler = NULL; - if (type == IS_UNICODE) { - /* FIXME: Unicode support??? */ - OG(active_ob_buffer).handler_name.u = eustrdup((handler_name.u && handler_name.u[0])?handler_name.u:(UChar*)OB_DEFAULT_HANDLER_NAME); - } else { - OG(active_ob_buffer).handler_name.s = estrdup((handler_name.s && handler_name.s[0])?handler_name.s:OB_DEFAULT_HANDLER_NAME); - } - 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, int len TSRMLS_DC) +/* {{{ php_output_handler_context_func_t php_output_handler_alias(const char[] name) + Get an internal output handler for a user handler if it exists */ +PHPAPI php_output_handler_context_func_t *_php_output_handler_alias(zval *name TSRMLS_DC) { - zval *output_handler; - - ALLOC_INIT_ZVAL(output_handler); - Z_STRLEN_P(output_handler) = len; - Z_STRVAL_P(output_handler) = estrndup(handler_name, len); - Z_TYPE_P(output_handler) = IS_STRING; - return output_handler; + php_output_handler_context_func_t *func = NULL; + + zend_u_hash_find(&php_output_handler_aliases, Z_TYPE_P(name), Z_UNIVAL_P(name), Z_UNILEN_P(name), (void *) &func); + return func; } /* }}} */ -/* {{{ php_ob_handler_from_unicode - * Create zval output handler from unicode - */ -static zval* php_ob_handler_from_unicode(const UChar *handler_name, int len TSRMLS_DC) +/* {{{ SUCCESS|FAILURE php_output_handler_alias_register(const char[] name, php_output_handler_context_func_t func) + Registers an internal output handler as alias for a user handler */ +PHPAPI int _php_output_handler_alias_register_ex(zval *name, php_output_handler_context_func_t func TSRMLS_DC) { - zval *output_handler; - - ALLOC_INIT_ZVAL(output_handler); - Z_USTRLEN_P(output_handler) = len; - Z_USTRVAL_P(output_handler) = eustrndup(handler_name, len); - Z_TYPE_P(output_handler) = IS_UNICODE; - return output_handler; + if (!EG(current_module)) { + zend_error(E_ERROR, "Cannot register an output handler alias outside of MINIT"); + return FAILURE; + } + return zend_u_hash_update(&php_output_handler_aliases, Z_TYPE_P(name), Z_UNIVAL_P(name), Z_UNILEN_P(name), &func, sizeof(php_output_handler_context_func_t *), NULL); } /* }}} */ -/* {{{ 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) +/* {{{ SUCCESS|FAILURE php_output_handler_hook(int type, void *arg) + Output handler hook for output handler functions to check/modify the current handlers abilities */ +PHPAPI int _php_output_handler_hook(int type, void *arg TSRMLS_DC) { - int result = FAILURE, handler_len, len; - HashPosition pos; - zval **tmp; - zval *handler_zval; - - if (output_handler && output_handler->type == IS_STRING) { - zstr next_handler_name; - zstr handler_name = Z_UNIVAL_P(output_handler); - handler_len = Z_UNILEN_P(output_handler); - - result = SUCCESS; - if (handler_len && handler_name.s[0] != '\0') { - while ((next_handler_name.s=strchr(handler_name.s, ',')) != NULL) { - len = next_handler_name.s-handler_name.s; - next_handler_name.s = estrndup(handler_name.s, len); - handler_zval = php_ob_handler_from_string(next_handler_name.s, len TSRMLS_CC); - result = php_ob_init_named(initial_size, block_size, IS_STRING, next_handler_name, handler_zval, chunk_size, erase TSRMLS_CC); - if (result != SUCCESS) { - zval_dtor(handler_zval); - FREE_ZVAL(handler_zval); - } - handler_name.s += len+1; - handler_len -= len+1; - efree(next_handler_name.s); - } - } - if (result == SUCCESS) { - handler_zval = php_ob_handler_from_string(handler_name.s, handler_len TSRMLS_CC); - result = php_ob_init_named(initial_size, block_size, IS_STRING, handler_name, handler_zval, chunk_size, erase TSRMLS_CC); - if (result != SUCCESS) { - zval_dtor(handler_zval); - FREE_ZVAL(handler_zval); - } - } - } else if (output_handler && output_handler->type == IS_UNICODE) { - zstr next_handler_name; - zstr handler_name = Z_UNIVAL_P(output_handler); - handler_len = Z_UNILEN_P(output_handler); - - result = SUCCESS; - if (handler_len && handler_name.u[0] != 0) { - while ((next_handler_name.u=u_strchr(handler_name.u, ',')) != NULL) { - len = next_handler_name.u-handler_name.u; - next_handler_name.u = eustrndup(handler_name.u, len); - handler_zval = php_ob_handler_from_unicode(next_handler_name.u, len TSRMLS_CC); - result = php_ob_init_named(initial_size, block_size, IS_UNICODE, next_handler_name, handler_zval, chunk_size, erase TSRMLS_CC); - if (result != SUCCESS) { - zval_dtor(handler_zval); - FREE_ZVAL(handler_zval); - } - handler_name.u += len+1; - handler_len -= len+1; - efree(next_handler_name.u); - } - } - if (result == SUCCESS) { - handler_zval = php_ob_handler_from_unicode(handler_name.u, handler_len TSRMLS_CC); - result = php_ob_init_named(initial_size, block_size, IS_UNICODE, handler_name, handler_zval, chunk_size, erase TSRMLS_CC); - if (result != SUCCESS) { - zval_dtor(handler_zval); - FREE_ZVAL(handler_zval); - } - } - } else if (output_handler && output_handler->type == IS_ARRAY) { - zval handler_name; - - /* do we have array(object,method) */ - if (zend_is_callable(output_handler, 0, &handler_name)) { - SEPARATE_ZVAL(&output_handler); - output_handler->refcount++; - result = php_ob_init_named(initial_size, block_size, Z_TYPE(handler_name), Z_UNIVAL(handler_name), output_handler, chunk_size, erase TSRMLS_CC); - zval_dtor(&handler_name); - } else { - zval_dtor(&handler_name); - /* init all array elements recursively */ - 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); - if (result == FAILURE) { - break; - } - zend_hash_move_forward_ex(Z_ARRVAL_P(output_handler), &pos); - } + if (OG(running)) { + switch (type) { + case PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ: + *(void ***) arg = &OG(running)->opaq; + return SUCCESS; + case PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS: + *(int *) arg = OG(running)->flags; + return SUCCESS; + case PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE: + OG(running)->flags &= ~PHP_OUTPUT_HANDLER_STDFLAGS; + return SUCCESS; + case PHP_OUTPUT_HANDLER_HOOK_DISABLE: + OG(running)->flags |= PHP_OUTPUT_HANDLER_DISABLED; + return SUCCESS; } - } else if (output_handler && output_handler->type == IS_OBJECT) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "No method name given: use ob_start(array($object,'method')) to specify instance $object and the name of a method of class %v to use as output handler", Z_OBJCE_P(output_handler)->name); - result = FAILURE; - } else { - zstr z_name; - - z_name.s = OB_DEFAULT_HANDLER_NAME; - result = php_ob_init_named(initial_size, block_size, IS_STRING, z_name, NULL, chunk_size, erase TSRMLS_CC); } - return result; + return FAILURE; } /* }}} */ -/* {{{ php_ob_list_each - */ -static int php_ob_list_each(php_ob_buffer *ob_buffer, zval *ob_handler_array) +/* {{{ void php_output_handler_dtor(php_output_handler *handler) + Destroy an output handler */ +PHPAPI void _php_output_handler_dtor(php_output_handler *handler TSRMLS_DC) { - TSRMLS_FETCH(); - - add_next_index_text(ob_handler_array, ob_buffer->handler_name, 1); - return 0; + zval_ptr_dtor(&handler->name); + STR_FREE(handler->buffer.data); + if (handler->flags & PHP_OUTPUT_HANDLER_USER) { + zval_ptr_dtor(&handler->user); + } + if (handler->dtor && handler->opaq) { + handler->dtor(handler->opaq TSRMLS_CC); + } + memset(handler, 0, sizeof(*handler)); } /* }}} */ -/* {{{ proto false|array ob_list_handlers() - * List all output_buffers in an array - */ -PHP_FUNCTION(ob_list_handlers) +/* {{{ void php_output_handler_free(php_output_handler **handler) + Destroy and free an output handler */ +PHPAPI void _php_output_handler_free(php_output_handler **h TSRMLS_DC) { - if (ZEND_NUM_ARGS()!=0) { - ZEND_WRONG_PARAM_COUNT(); - RETURN_FALSE; + if (*h) { + php_output_handler_dtor(*h); + efree(*h); + *h = NULL; } +} +/* }}} */ - array_init(return_value); - if (OG(ob_nesting_level)) { - if (OG(ob_nesting_level)>1) { - zend_stack_apply_with_argument(&OG(ob_buffers), ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *element, void *)) php_ob_list_each, return_value); - } - php_ob_list_each(&OG(active_ob_buffer), return_value); +/* void php_output_set_implicit_flush(int enabled) + Enable or disable implicit flush */ +PHPAPI void _php_output_set_implicit_flush(int flush TSRMLS_DC) +{ + if (flush) { + OG(flags) |= PHP_OUTPUT_IMPLICITFLUSH; + } else { + OG(flags) &= ~PHP_OUTPUT_IMPLICITFLUSH; } } /* }}} */ -/* {{{ php_ob_used_each - * Sets handler_name to NULL is found - */ -static int php_ob_handler_used_each(php_ob_buffer *ob_buffer, char **handler_name) +/* {{{ char *php_output_get_start_filename() + Get the file name where output has started */ +PHPAPI char *_php_output_get_start_filename(TSRMLS_D) { - /* FIXME: Unicode support??? */ - if (!strcmp(ob_buffer->handler_name.s, *handler_name)) { - *handler_name = NULL; + return OG(output_start_filename); +} +/* }}} */ + +/* {{{ int php_output_get_start_lineno() + Get the line number where output has started */ +PHPAPI int _php_output_get_start_lineno(TSRMLS_D) +{ + return OG(output_start_lineno); +} +/* }}} */ + +/* {{{ static int php_output_lock_error(int op TSRMLS_DC) + Checks whether an unallowed operation is attempted from within the output handler and issues a fatal error */ +static inline int php_output_lock_error(int op TSRMLS_DC) +{ + /* if there's no ob active, ob has been stopped */ + if (op && OG(active) && OG(running)) { + /* fatal error */ + php_output_deactivate(); + php_error_docref("ref.outcontrol" TSRMLS_CC, E_ERROR, "Cannot use output buffering in output buffering display handlers"); return 1; } return 0; } /* }}} */ -/* {{{ php_ob_used - * returns 1 if given handler_name is used as output_handler - */ -PHPAPI int php_ob_handler_used(char *handler_name TSRMLS_DC) +/* {{{ static php_output_context *php_output_context_init(php_output_context *context, int op TSRMLS_DC) + Initialize a new output context */ +static inline php_output_context *php_output_context_init(php_output_context *context, int op TSRMLS_DC) { - /* FIXME: Unicode support??? */ - char *tmp = handler_name; - - if (OG(ob_nesting_level)) { - if (!strcmp(OG(active_ob_buffer).handler_name.s, handler_name)) { - return 1; - } - if (OG(ob_nesting_level)>1) { - zend_stack_apply_with_argument(&OG(ob_buffers), ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *element, void *)) php_ob_handler_used_each, &tmp); - } + if (!context) { + context = emalloc(sizeof(php_output_context)); } - return tmp ? 0 : 1; + + memset(context, 0, sizeof(php_output_context)); + TSRMLS_SET_CTX(context->tsrm_ls); + context->op = op; + + return context; } /* }}} */ -/* {{{ php_ob_append - */ -static inline void php_ob_append(const char *text, uint text_length TSRMLS_DC) +/* {{{ static void php_output_context_reset(php_output_context *context) + Reset an output context */ +static inline void php_output_context_reset(php_output_context *context) { - char *target; - int original_ob_text_length; - - original_ob_text_length=OG(active_ob_buffer).text_length; - - php_ob_allocate(text_length TSRMLS_CC); - target = OG(active_ob_buffer).buffer+original_ob_text_length; - memcpy(target, text, text_length); - target[text_length]=0; + int op = context->op; + php_output_context_dtor(context); + memset(context, 0, sizeof(php_output_context)); + context->op = op; +} +/* }}} */ - /* If implicit_flush is On or chunked buffering, send contents to next buffer and return. */ - if (OG(active_ob_buffer).chunk_size - && OG(active_ob_buffer).text_length >= OG(active_ob_buffer).chunk_size) { - - php_end_ob_buffer(1, 1 TSRMLS_CC); - return; +/* {{{ static void php_output_context_swap(php_output_context *context) + Swap output contexts buffers */ +static inline void php_output_context_swap(php_output_context *context) +{ + if (context->in.free && context->in.data) { + efree(context->in.data); } + context->in.data = context->out.data; + context->in.used = context->out.used; + context->in.free = context->out.free; + context->in.size = context->out.size; + context->out.data = NULL; + context->out.used = 0; + context->out.size = 0; } /* }}} */ -#if 0 -static inline void php_ob_prepend(const char *text, uint text_length) +/* {{{ static void php_output_context_pass(php_output_context *context) + Pass input to output buffer */ +static inline void php_output_context_pass(php_output_context *context) { - char *p, *start; - TSRMLS_FETCH(); - - php_ob_allocate(text_length TSRMLS_CC); - - /* php_ob_allocate() may change OG(ob_buffer), so we can't initialize p&start earlier */ - p = OG(ob_buffer)+OG(ob_text_length); - start = OG(ob_buffer); + context->out.data = context->in.data; + context->out.used = context->in.used; + context->out.size = context->in.size; + context->out.free = context->in.free; + context->in.data = NULL; + context->in.used = 0; + context->in.size = 0; +} +/* }}} */ - while (--p>=start) { - p[text_length] = *p; +/* {{{ static void php_output_context_dtor(php_output_context *context) + Destroy the contents of an output context */ +static inline void php_output_context_dtor(php_output_context *context) +{ + if (context->in.free && context->in.data) { + efree(context->in.data); + } + if (context->out.free && context->out.data) { + efree(context->out.data); } - memcpy(OG(ob_buffer), text, text_length); - OG(ob_buffer)[OG(active_ob_buffer).text_length]=0; } -#endif +/* }}} */ +/* {{{ static php_output_handler *php_output_handler_init(zval *name, size_t chunk_size, int flags) + Allocates and initializes a php_output_handler structure */ +static inline php_output_handler *php_output_handler_init(zval *name, size_t chunk_size, int flags) +{ + php_output_handler *handler; + + handler = ecalloc(1, sizeof(php_output_handler)); + ZVAL_ADDREF(name); + handler->name = name; + handler->size = chunk_size; + handler->flags = flags; + handler->buffer.size = PHP_OUTPUT_HANDLER_INITBUF_SIZE(chunk_size); + handler->buffer.data = emalloc(handler->buffer.size); + + return handler; +} +/* }}} */ -/* {{{ php_ob_get_buffer - * Return the current output buffer */ -PHPAPI int php_ob_get_buffer(zval *p TSRMLS_DC) +/* {{{ static int php_output_handler_appen(php_output_handler *handler, const php_output_buffer *buf TSRMLS_DC) + Appends input to the output handlers buffer and indicates whether the buffer does not have to be processed by the output handler */ +static inline int php_output_handler_append(php_output_handler *handler, const php_output_buffer *buf TSRMLS_DC) { - if (OG(ob_nesting_level)==0) { - return FAILURE; + /* store it away */ + if ((handler->buffer.size - handler->buffer.used) <= buf->used) { + size_t grow_int = PHP_OUTPUT_HANDLER_INITBUF_SIZE(handler->size); + size_t grow_buf = PHP_OUTPUT_HANDLER_INITBUF_SIZE(buf->used + 1 - (handler->buffer.size - handler->buffer.used)); + size_t grow_max = MAX(grow_int, grow_buf); + + handler->buffer.data = erealloc(handler->buffer.data, handler->buffer.size += grow_max); } - ZVAL_U_STRINGL(ZEND_U_CONVERTER(UG(output_encoding_conv)), p, OG(active_ob_buffer).buffer, OG(active_ob_buffer).text_length, 1); - return SUCCESS; + memcpy(handler->buffer.data + handler->buffer.used, buf->data, buf->used); + handler->buffer.used += buf->used; + handler->buffer.data[handler->buffer.used] = '\0'; + + /* chunked buffering */ + if (handler->size && (handler->buffer.used >= handler->size)) { + /* store away errors and/or any intermediate output */ + return OG(running) ? 1 : 0; + } + return 1; } /* }}} */ -/* {{{ php_ob_get_length - * Return the size of the current output buffer */ -PHPAPI int php_ob_get_length(zval *p TSRMLS_DC) +/* {{{ static PHP_OUTPUT_HANDLER_(SUCCESS|FAILURE|NO_DATA) php_output_handler_op(php_output_handler *handler, php_output_context *context) + Output handler operation dispatcher, applying context op to the php_output_handler handler */ +static inline int php_output_handler_op(php_output_handler *handler, php_output_context *context) { - if (OG(ob_nesting_level) == 0) { - return FAILURE; + int status, op; + PHP_OUTPUT_TSRMLS(context); + +#if PHP_OUTPUT_DEBUG + fprintf(stderr, ">>> op(%d, " + "handler=%p, " + "name=%s, " + "flags=%d, " + "buffer.data=%s, " + "buffer.used=%lu, " + "buffer.size=%lu, " + "in.data=%s, " + "in.used=%lu)\n", + context->op, + handler, + handler->name, + handler->flags, + handler->buffer.data, + handler->buffer.used, + handler->buffer.size, + context->in.data, + context->in.used + ); +#endif + + op = context->op; + if (php_output_lock_error(op TSRMLS_CC)) { + /* fatal error */ + return PHP_OUTPUT_HANDLER_FAILURE; } - ZVAL_LONG(p, OG(active_ob_buffer).text_length); - return SUCCESS; + + /* storable? */ + if (php_output_handler_append(handler, &context->in TSRMLS_CC) && !op) { + status = PHP_OUTPUT_HANDLER_NO_DATA; + } else { + /* need to start? */ + if (!(handler->flags & PHP_OUTPUT_HANDLER_STARTED)) { + handler->flags |= PHP_OUTPUT_HANDLER_STARTED; + op |= PHP_OUTPUT_HANDLER_START; + } + + OG(running) = handler; + if (handler->flags & PHP_OUTPUT_HANDLER_USER) { + zval *retval = NULL, **params[2], *flags, *input; + + MAKE_STD_ZVAL(input); + ZVAL_STRINGL(input, handler->buffer.data, handler->buffer.used, 1); + MAKE_STD_ZVAL(flags); + ZVAL_LONG(flags, (long) op); + params[0] = &input; + params[1] = &flags; + + if ( (SUCCESS == call_user_function_ex(CG(function_table), NULL, handler->user, &retval, 2, params, 1, NULL TSRMLS_CC)) && + retval && (Z_TYPE_P(retval) != IS_NULL) && (Z_TYPE_P(retval) != IS_BOOL || Z_BVAL_P(retval))) { + /* user handler may have returned TRUE */ + status = PHP_OUTPUT_HANDLER_NO_DATA; + if (Z_TYPE_P(retval) != IS_BOOL) { + convert_to_string_ex(&retval); + if (Z_STRLEN_P(retval)) { + context->out.data = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval)); + context->out.used = Z_STRLEN_P(retval); + context->out.free = 1; + status = PHP_OUTPUT_HANDLER_SUCCESS; + } + } + } else { + /* call failed, pass internal buffer along */ + status = PHP_OUTPUT_HANDLER_FAILURE; + } + if (retval) { + zval_ptr_dtor(&retval); + } + zval_ptr_dtor(&input); + zval_ptr_dtor(&flags); + } else { + + context->in.data = handler->buffer.data; + context->in.used = handler->buffer.used; + context->in.free = 0; + + if (SUCCESS == handler->internal(&handler->opaq, context)) { + if (context->out.used) { + status = PHP_OUTPUT_HANDLER_SUCCESS; + } else { + status = PHP_OUTPUT_HANDLER_NO_DATA; + } + } else { + status = PHP_OUTPUT_HANDLER_FAILURE; + } + } + OG(running) = NULL; + } + + switch (status) { + case PHP_OUTPUT_HANDLER_FAILURE: + /* disable this handler */ + handler->flags |= PHP_OUTPUT_HANDLER_DISABLED; + /* returns handlers buffer */ + context->out.data = handler->buffer.data; + context->out.used = handler->buffer.used; + context->out.free = 1; + handler->buffer.data = NULL; + handler->buffer.used = 0; + handler->buffer.size = 0; + break; + case PHP_OUTPUT_HANDLER_SUCCESS: + /* no more buffered data */ + handler->buffer.used = 0; + break; + case PHP_OUTPUT_HANDLER_NO_DATA: + /* handler ate all */ + php_output_context_reset(context); + break; + } + + return status; } /* }}} */ -/* - * Wrapper functions - implementation - */ +/* {{{ static void php_output_op(int op, const char *str, size_t len TSRMLS_DC) + Output op dispatcher, passes input and output handlers output through the output handler stack until it gets written to the SAPI */ +static inline void php_output_op(int op, const char *str, size_t len TSRMLS_DC) +{ + php_output_context context; + php_output_handler **active; + int obh_cnt; + + if (php_output_lock_error(op TSRMLS_CC)) { + return; + } + + php_output_context_init(&context, op TSRMLS_CC); + + /* + * broken up for better performance: + * - apply op to the one active handler; note that OG(active) might be popped off the stack on a flush + * - or apply op to the handler stack + */ + if (OG(active) && (obh_cnt = zend_stack_count(&OG(handlers)))) { + context.in.data = (char *) str; + context.in.used = len; + + if (obh_cnt > 1) { + zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_TOPDOWN, php_output_stack_apply_op, &context); + } else if ((SUCCESS == zend_stack_top(&OG(handlers), (void *) &active)) && (!((*active)->flags & PHP_OUTPUT_HANDLER_DISABLED))) { + php_output_handler_op(*active, &context); + } else { + php_output_context_pass(&context); + } + } else { + context.out.data = (char *) str; + context.out.used = len; + } + + if (context.out.data) { + if (context.out.used) { +#if PHP_OUTPUT_DEBUG + fprintf(stderr, "::: sapi_write('%s', %lu)\n", context.out.data, context.out.used); +#endif + if (!SG(headers_sent) && php_header(TSRMLS_C)) { + if (zend_is_compiling(TSRMLS_C)) { + OG(output_start_filename) = zend_get_compiled_filename(TSRMLS_C); + OG(output_start_lineno) = zend_get_compiled_lineno(TSRMLS_C); + } else if (zend_is_executing(TSRMLS_C)) { + OG(output_start_filename) = zend_get_executed_filename(TSRMLS_C); + OG(output_start_lineno) = zend_get_executed_lineno(TSRMLS_C); + } +#if PHP_OUTPUT_DEBUG + fprintf(stderr, "!!! output started at: %s (%d)\n", OG(output_start_filename), OG(output_start_lineno)); +#endif + } + sapi_module.ub_write(context.out.data, context.out.used TSRMLS_CC); + if (OG(flags) & PHP_OUTPUT_IMPLICITFLUSH) { + sapi_flush(TSRMLS_C); + } + } + } + php_output_context_dtor(&context); +} +/* }}} */ -/* buffered output function */ -static int php_b_body_write(const char *str, uint str_length TSRMLS_DC) +/* {{{ static int php_output_stack_apply_op(void *h, void *c) + Operation callback for the stack apply function */ +static int php_output_stack_apply_op(void *h, void *c) { - php_ob_append(str, str_length TSRMLS_CC); - return str_length; + int status = PHP_OUTPUT_HANDLER_FAILURE, was_disabled; + php_output_handler *handler = *(php_output_handler **) h; + php_output_context *context = (php_output_context *) c; + + if (!(was_disabled = (handler->flags & PHP_OUTPUT_HANDLER_DISABLED))) { + status = php_output_handler_op(handler, context); + } + + /* + * handler ate all => break + * handler returned data or failed resp. is disabled => continue + */ + switch (status) { + case PHP_OUTPUT_HANDLER_NO_DATA: + return 1; + + case PHP_OUTPUT_HANDLER_SUCCESS: + /* swap contexts buffers, unless this is the last handler in the stack */ + if (handler->level) { + php_output_context_swap(context); + } + return 0; + + case PHP_OUTPUT_HANDLER_FAILURE: + default: + if (was_disabled) { + /* pass input along, if it's the last handler in the stack */ + if (!handler->level) { + php_output_context_pass(context); + } + } else { + /* swap buffers, unless this is the last handler */ + if (handler->level) { + php_output_context_swap(context); + } + } + return 0; + } } +/* }}} */ -/* {{{ php_ub_body_write_no_header - */ -PHPAPI int php_ub_body_write_no_header(const char *str, uint str_length TSRMLS_DC) +/* {{{ static int php_output_stack_apply_clean(void *h, void *c) + Clean callback for the stack apply function */ +static int php_output_stack_apply_clean(void *h, void *c) { - int result; + php_output_handler *handler = *(php_output_handler **) h; + php_output_context *context = (php_output_context *) c; + + handler->buffer.used = 0; + php_output_handler_op(handler, context); + php_output_context_reset(context); + return 0; +} +/* }}} */ - if (OG(disable_output)) { - return 0; - } +/* {{{ static int php_output_stack_apply_list(void *h, void *z) + List callback for the stack apply function */ +static int php_output_stack_apply_list(void *h, void *z) +{ + php_output_handler *handler = *(php_output_handler **) h; + zval *array = (zval *) z; + + if (Z_TYPE_P(handler->name) == IS_UNICODE) { + add_next_index_unicodel(array, Z_USTRVAL_P(handler->name), Z_USTRLEN_P(handler->name), 1); + } else { + add_next_index_stringl(array, Z_STRVAL_P(handler->name), Z_STRLEN_P(handler->name), 1); + } + return 0; +} +/* }}} */ - result = OG(php_header_write)(str, str_length TSRMLS_CC); +/* {{{ static int php_output_stack_apply_status(void *h, void *z) + Status callback for the stack apply function */ +static int php_output_stack_apply_status(void *h, void *z) +{ + php_output_handler *handler = *(php_output_handler **) h; + zval *array = (zval *) z; + + add_next_index_zval(array, php_output_handler_status(handler, NULL)); + + return 0; +} +/* }}} */ - if (OG(implicit_flush)) { - sapi_flush(TSRMLS_C); +/* {{{ static zval *php_output_handler_status(php_output_handler *handler, zval *entry) + Returns an array with the status of the output handler */ +static inline zval *php_output_handler_status(php_output_handler *handler, zval *entry) +{ + if (!entry) { + MAKE_STD_ZVAL(entry); + array_init(entry); } - - return result; + + if (Z_TYPE_P(handler->name) == IS_UNICODE) { + add_assoc_unicodel(entry, "name", Z_USTRVAL_P(handler->name), Z_USTRLEN_P(handler->name), 1); + } else { + add_assoc_stringl(entry, "name", Z_STRVAL_P(handler->name), Z_STRLEN_P(handler->name), 1); + } + add_assoc_long(entry, "type", (long) (handler->flags & 0xf)); + add_assoc_long(entry, "flags", (long) handler->flags); + add_assoc_long(entry, "level", (long) handler->level); + add_assoc_long(entry, "chunk_size", (long) handler->size); + add_assoc_long(entry, "buffer_size", (long) handler->buffer.size); + add_assoc_long(entry, "buffer_used", (long) handler->buffer.used); + + return entry; } /* }}} */ -/* {{{ php_ub_body_write - */ -PHPAPI int php_ub_body_write(const char *str, uint str_length TSRMLS_DC) +/* {{{ static int php_output_stack_pop(int discard, int shutdown TSRMLS_DC) + Pops an output handler off the stack, ignores whether the handler is removable if shutdown==1, discards the handlers output if discard==1 */ +static inline int php_output_stack_pop(int discard, int shutdown TSRMLS_DC) { - int result = 0; - - if (SG(request_info).headers_only) { - if(SG(headers_sent)) { - return 0; + php_output_context context; + php_output_handler **current, *orphan = OG(active); + + if (!orphan) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer. No buffer to delete."); + return 0; + } else if (!shutdown && !(orphan->flags & PHP_OUTPUT_HANDLER_REMOVABLE)) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", orphan->name); + return 0; + } else { + php_output_context_init(&context, PHP_OUTPUT_HANDLER_FINAL TSRMLS_CC); + + /* don't run the output handler if it's disabled */ + if (!(orphan->flags & PHP_OUTPUT_HANDLER_DISABLED)) { + /* didn't it start yet? */ + if (!(orphan->flags & PHP_OUTPUT_HANDLER_STARTED)) { + context.op |= PHP_OUTPUT_HANDLER_START; + } + /* signal that we're cleaning up */ + if (discard) { + context.op |= PHP_OUTPUT_HANDLER_CLEAN; + } + php_output_handler_op(orphan, &context); } - php_header(TSRMLS_C); - zend_bailout(); - } - if (php_header(TSRMLS_C)) { - if (zend_is_compiling(TSRMLS_C)) { - OG(output_start_filename) = zend_get_compiled_filename(TSRMLS_C); - OG(output_start_lineno) = zend_get_compiled_lineno(TSRMLS_C); - } else if (zend_is_executing(TSRMLS_C)) { - OG(output_start_filename) = zend_get_executed_filename(TSRMLS_C); - OG(output_start_lineno) = zend_get_executed_lineno(TSRMLS_C); + + /* pop it off the stack */ + zend_stack_del_top(&OG(handlers)); + if (SUCCESS == zend_stack_top(&OG(handlers), (void *) ¤t)) { + OG(active) = *current; + } else { + OG(active) = NULL; + } + + /* pass output along */ + if (context.out.data && context.out.used && !discard) { + php_output_write(context.out.data, context.out.used); } + + /* destroy the handler (after write!) */ + php_output_handler_free(&orphan); + php_output_context_dtor(&context); + + return 1; + } +} +/* }}} */ - OG(php_body_write) = php_ub_body_write_no_header; - result = php_ub_body_write_no_header(str, str_length TSRMLS_CC); +/* {{{ static SUCCESS|FAILURE php_output_handler_compat_func(void *ctx, int op, const char *in, size_t in_len, char **out, size_t *out_len TSRMLS_DC) + php_output_handler_context_func_t for php_output_handler_func_t output handlers */ +static int php_output_handler_compat_func(void **handler_context, php_output_context *output_context) +{ + php_output_handler_func_t func = *(php_output_handler_func_t *) handler_context; + PHP_OUTPUT_TSRMLS(output_context); + + if (func) { + func(output_context->in.data, output_context->in.used, &output_context->out.data, &output_context->out.used, output_context->op TSRMLS_CC); + output_context->out.free = 1; + return SUCCESS; } + return FAILURE; +} +/* }}} */ + +/* {{{ static SUCCESS|FAILURE php_output_handler_default_func(void *ctx, int op, const char *in, size_t in_len, char **out, size_t *out_len TSRMLS_DC) + Default output handler */ +static int php_output_handler_default_func(void **handler_context, php_output_context *output_context) +{ + output_context->out.data = output_context->in.data; + output_context->out.used = output_context->in.used; + output_context->out.free = output_context->in.free; + output_context->in.data = NULL; + output_context->in.used = 0; + return SUCCESS; +} +/* }}} */ - return result; +/* {{{ static SUCCESS|FAILURE php_output_handler_devnull_func(void *ctx, int op, const char *in, size_t in_len, char **out, size_t *out_len TSRMLS_DC) + Null output handler */ +static int php_output_handler_devnull_func(void **handler_context, php_output_context *output_context) +{ + return SUCCESS; } /* }}} */ /* - * HEAD support + * USERLAND (nearly 1:1 of old output.c) */ -/* {{{ proto bool ob_start([ string|array user_function [, int chunk_size [, bool erase]]]) +/* {{{ proto bool ob_start([ string|array user_function [, int chunk_size [, int flags]]]) Turn on Output Buffering (specifying an optional output handler). */ PHP_FUNCTION(ob_start) { - zval *output_handler=NULL; - long chunk_size=0; - zend_bool erase=1; - int argc = ZEND_NUM_ARGS(); + zval *output_handler = NULL; + long chunk_size = 0; + long flags = PHP_OUTPUT_HANDLER_CLEANABLE|PHP_OUTPUT_HANDLER_REMOVABLE; - if (zend_parse_parameters(argc TSRMLS_CC, "|zlb", &output_handler, &chunk_size, &erase) == FAILURE) { + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|zlb", &output_handler, &chunk_size, &flags)) { RETURN_FALSE; } - - if (chunk_size < 0) + if (chunk_size < 0) { chunk_size = 0; + } - if (php_start_ob_buffer(output_handler, chunk_size, erase TSRMLS_CC)==FAILURE) { + if (SUCCESS != php_output_start_user(output_handler, chunk_size, flags)) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to create buffer."); RETURN_FALSE; } RETURN_TRUE; @@ -820,16 +1228,16 @@ Flush (send) contents of the output buffer. The last buffer content is sent to next buffer */ PHP_FUNCTION(ob_flush) { - if (ZEND_NUM_ARGS() != 0) { + if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - - if (!OG(ob_nesting_level)) { + + if (!OG(active)) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to flush buffer. No buffer to flush."); RETURN_FALSE; } - php_end_ob_buffer(1, 1 TSRMLS_CC); + php_output_flush(); RETURN_TRUE; } /* }}} */ @@ -839,21 +1247,18 @@ Clean (delete) the current output buffer */ PHP_FUNCTION(ob_clean) { - if (ZEND_NUM_ARGS() != 0) { + if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - if (!OG(ob_nesting_level)) { + if (!OG(active)) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer. No buffer to delete."); RETURN_FALSE; } - - if (!OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) { - php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active_ob_buffer).handler_name); + if (SUCCESS != php_output_clean()) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active)->name); RETURN_FALSE; } - - php_end_ob_buffer(0, 1 TSRMLS_CC); RETURN_TRUE; } /* }}} */ @@ -862,20 +1267,18 @@ Flush (send) the output buffer, and delete current output buffer */ PHP_FUNCTION(ob_end_flush) { - if (ZEND_NUM_ARGS() != 0) { + if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - if (!OG(ob_nesting_level)) { + if (!OG(active)) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete and flush buffer. No buffer to delete or flush."); RETURN_FALSE; } - if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) { - php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active_ob_buffer).handler_name); + if (SUCCESS != php_output_end()) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active)->name); RETURN_FALSE; } - - php_end_ob_buffer(1, 0 TSRMLS_CC); RETURN_TRUE; } /* }}} */ @@ -884,20 +1287,18 @@ Clean the output buffer, and delete current output buffer */ PHP_FUNCTION(ob_end_clean) { - if (ZEND_NUM_ARGS() != 0) { + if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - - if (!OG(ob_nesting_level)) { + + if (!OG(active)) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer. No buffer to delete."); RETURN_FALSE; } - if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) { - php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active_ob_buffer).handler_name); + if (SUCCESS != php_output_discard()) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active)->name); RETURN_FALSE; } - - php_end_ob_buffer(0, 0 TSRMLS_CC); RETURN_TRUE; } /* }}} */ @@ -906,25 +1307,17 @@ Get current buffer contents, flush (send) the output buffer, and delete current output buffer */ PHP_FUNCTION(ob_get_flush) { - if (ZEND_NUM_ARGS() != 0) { + if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - - /* get contents */ - if (php_ob_get_buffer(return_value TSRMLS_CC)==FAILURE) { - RETURN_FALSE; - } - /* error checks */ - if (!OG(ob_nesting_level)) { + + if (SUCCESS != php_output_get_contents(return_value)) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete and flush buffer. No buffer to delete or flush."); RETURN_FALSE; } - if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) { - php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active_ob_buffer).handler_name); - RETURN_FALSE; + if (SUCCESS != php_output_end()) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active)->name); } - /* flush */ - php_end_ob_buffer(1, 0 TSRMLS_CC); } /* }}} */ @@ -932,24 +1325,17 @@ Get current buffer contents and delete current output buffer */ PHP_FUNCTION(ob_get_clean) { - if (ZEND_NUM_ARGS() != 0) - ZEND_WRONG_PARAM_COUNT(); - - /* get contents */ - if (php_ob_get_buffer(return_value TSRMLS_CC)==FAILURE) { - RETURN_FALSE; + if (ZEND_NUM_ARGS()) { + ZEND_WRONG_PARAM_COUNT(); } - /* error checks */ - if (!OG(ob_nesting_level)) { + + if (SUCCESS != php_output_get_contents(return_value)) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer. No buffer to delete."); RETURN_FALSE; } - if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) { - php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active_ob_buffer).handler_name); - RETURN_FALSE; + if (SUCCESS != php_output_discard()) { + php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s.", OG(active)->name); } - /* delete buffer */ - php_end_ob_buffer(0, 0 TSRMLS_CC); } /* }}} */ @@ -957,11 +1343,10 @@ Return the contents of the output buffer */ PHP_FUNCTION(ob_get_contents) { - if (ZEND_NUM_ARGS() != 0) { + if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - - if (php_ob_get_buffer(return_value TSRMLS_CC)==FAILURE) { + if (SUCCESS != php_output_get_contents(return_value)) { RETURN_FALSE; } } @@ -971,11 +1356,10 @@ Return the nesting level of the output buffer */ PHP_FUNCTION(ob_get_level) { - if (ZEND_NUM_ARGS() != 0) { + if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - - RETURN_LONG (OG(ob_nesting_level)); + RETURN_LONG(php_output_get_level()); } /* }}} */ @@ -983,130 +1367,66 @@ Return the length of the output buffer */ PHP_FUNCTION(ob_get_length) { - if (ZEND_NUM_ARGS() != 0) { + if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - - if (php_ob_get_length(return_value TSRMLS_CC)==FAILURE) { + if (SUCCESS != php_output_get_length(return_value)) { RETURN_FALSE; } } /* }}} */ -/* {{{ int php_ob_buffer_status(php_ob_buffer *ob_buffer, zval *result) */ -static int php_ob_buffer_status(php_ob_buffer *ob_buffer, zval *result) +/* {{{ proto false|array ob_list_handlers() + * List all output_buffers in an array + */ +PHP_FUNCTION(ob_list_handlers) { - zval *elem; - TSRMLS_FETCH(); - - MAKE_STD_ZVAL(elem); - array_init(elem); - - add_assoc_long(elem, "chunk_size", ob_buffer->chunk_size); - if (!ob_buffer->chunk_size) { - add_assoc_long(elem, "size", ob_buffer->size); - add_assoc_long(elem, "block_size", ob_buffer->block_size); - } - if (ob_buffer->internal_output_handler) { - add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_INTERNAL); - add_assoc_long(elem, "buffer_size", ob_buffer->internal_output_handler_buffer_size); - } - else { - add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_USER); - } - add_assoc_long(elem, "status", ob_buffer->status); - add_assoc_text(elem, "name", ob_buffer->handler_name, 1); - add_assoc_bool(elem, "del", ob_buffer->erase); - add_next_index_zval(result, elem); - - return SUCCESS; + if (ZEND_NUM_ARGS()) { + ZEND_WRONG_PARAM_COUNT(); + } + if (!OG(active)) { + RETURN_FALSE; + } + + array_init(return_value); + zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_BOTTOMUP, php_output_stack_apply_list, return_value); } /* }}} */ - /* {{{ 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 ) + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &full_status)) { RETURN_FALSE; + } + if (!OG(active)) { + RETURN_FALSE; + } array_init(return_value); - if (full_status) { - 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); - } - if (OG(ob_nesting_level)>0 && php_ob_buffer_status(&OG(active_ob_buffer), return_value)==FAILURE) { - RETURN_FALSE; - } - } 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); - } else { - add_assoc_long(return_value, "type", PHP_OUTPUT_HANDLER_USER); - } - add_assoc_long(return_value, "status", OG(active_ob_buffer).status); - add_assoc_text(return_value, "name", OG(active_ob_buffer).handler_name, 1); - add_assoc_bool(return_value, "del", OG(active_ob_buffer).erase); + zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_BOTTOMUP, php_output_stack_apply_status, return_value); + } else { + php_output_handler_status(OG(active), return_value); } } /* }}} */ - /* {{{ proto void ob_implicit_flush([int flag]) Turn implicit flush on/off and is equivalent to calling flush() after every output call */ PHP_FUNCTION(ob_implicit_flush) { - zval **zv_flag; - int flag; - - switch(ZEND_NUM_ARGS()) { - case 0: - flag = 1; - break; - case 1: - if (zend_get_parameters_ex(1, &zv_flag)==FAILURE) { - RETURN_FALSE; - } - convert_to_long_ex(zv_flag); - flag = Z_LVAL_PP(zv_flag); - break; - default: - ZEND_WRONG_PARAM_COUNT(); - break; - } - if (flag) { - php_start_implicit_flush(TSRMLS_C); - } else { - php_end_implicit_flush(TSRMLS_C); + long flag = 1; + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flag)) { + php_output_set_implicit_flush(flag); } } /* }}} */ - -/* {{{ char *php_get_output_start_filename(TSRMLS_D) - Return filename start output something */ -PHPAPI char *php_get_output_start_filename(TSRMLS_D) -{ - return OG(output_start_filename); -} -/* }}} */ - - -/* {{{ char *php_get_output_start_lineno(TSRMLS_D) - Return line number start output something */ -PHPAPI int php_get_output_start_lineno(TSRMLS_D) -{ - return OG(output_start_lineno); -} -/* }}} */ - - /* {{{ proto bool output_reset_rewrite_vars(void) Reset(clear) URL rewriter values */ PHP_FUNCTION(output_reset_rewrite_vars) @@ -1119,7 +1439,6 @@ } /* }}} */ - /* {{{ proto bool output_add_rewrite_var(string name, string value) Add URL rewriter values */ PHP_FUNCTION(output_add_rewrite_var) http://cvs.php.net/viewcvs.cgi/php-src/main/php.h?r1=1.230&r2=1.231&diff_format=u Index: php-src/main/php.h diff -u php-src/main/php.h:1.230 php-src/main/php.h:1.231 --- php-src/main/php.h:1.230 Thu May 25 18:48:30 2006 +++ php-src/main/php.h Fri Jun 2 19:51:42 2006 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php.h,v 1.230 2006/05/25 18:48:30 edink Exp $ */ +/* $Id: php.h,v 1.231 2006/06/02 19:51:42 mike Exp $ */ #ifndef PHP_H #define PHP_H @@ -373,20 +373,7 @@ /* Output support */ #include "main/php_output.h" -#define PHPWRITE(str, str_len) php_body_write((str), (str_len) TSRMLS_CC) -#define PUTS(str) do { \ - const char *__str = (str); \ - php_body_write(__str, strlen(__str) TSRMLS_CC); \ -} while (0) - -#define PUTC(c) (php_body_write(&(c), 1 TSRMLS_CC), (c)) -#define PHPWRITE_H(str, str_len) php_header_write((str), (str_len) TSRMLS_CC) -#define PUTS_H(str) do { \ - const char *__str = (str); \ - php_header_write(__str, strlen(__str) TSRMLS_CC); \ -} while (0) -#define PUTC_H(c) (php_header_write(&(c), 1 TSRMLS_CC), (c)) #ifdef ZTS #define VIRTUAL_DIR http://cvs.php.net/viewcvs.cgi/php-src/main/php_output.h?r1=1.55&r2=1.56&diff_format=u Index: php-src/main/php_output.h diff -u php-src/main/php_output.h:1.55 php-src/main/php_output.h:1.56 --- php-src/main/php_output.h:1.55 Thu Mar 2 13:12:45 2006 +++ php-src/main/php_output.h Fri Jun 2 19:51:42 2006 @@ -12,44 +12,291 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Zeev Suraski <zeev@zend.com> | + | Author: Michael Wallner <mike@php.net> | +----------------------------------------------------------------------+ */ -/* $Id: php_output.h,v 1.55 2006/03/02 13:12:45 dmitry Exp $ */ +/* $Id: php_output.h,v 1.56 2006/06/02 19:51:42 mike Exp $ */ #ifndef PHP_OUTPUT_H #define PHP_OUTPUT_H +#define PHP_OUTPUT_NEWAPI 1 + +/* handler ops */ +#define PHP_OUTPUT_HANDLER_WRITE 0x00 /* standard passthru */ +#define PHP_OUTPUT_HANDLER_START 0x01 /* start */ +#define PHP_OUTPUT_HANDLER_CLEAN 0x02 /* restart */ +#define PHP_OUTPUT_HANDLER_FLUSH 0x04 /* pass along as much as possible */ +#define PHP_OUTPUT_HANDLER_FINAL 0x08 /* finalize */ +#define PHP_OUTPUT_HANDLER_CONT PHP_OUTPUT_HANDLER_WRITE +#define PHP_OUTPUT_HANDLER_END PHP_OUTPUT_HANDLER_FINAL + +/* handler types */ +#define PHP_OUTPUT_HANDLER_INTERNAL 0x0000 +#define PHP_OUTPUT_HANDLER_USER 0x0001 + +/* handler ability flags */ +#define PHP_OUTPUT_HANDLER_CLEANABLE 0x0010 +#define PHP_OUTPUT_HANDLER_REMOVABLE 0x0020 +#define PHP_OUTPUT_HANDLER_STDFLAGS 0x0030 + +/* handler status flags */ +#define PHP_OUTPUT_HANDLER_STARTED 0x1000 +#define PHP_OUTPUT_HANDLER_DISABLED 0x2000 + +/* handler op return values */ +#define PHP_OUTPUT_HANDLER_FAILURE 0 +#define PHP_OUTPUT_HANDLER_SUCCESS 1 +#define PHP_OUTPUT_HANDLER_NO_DATA 2 + +/* real global flags */ +#define PHP_OUTPUT_IMPLICITFLUSH 0x01 +#define PHP_OUTPUT_DISABLED 0x02 +/* supplementary flags for php_output_get_status() */ +#define PHP_OUTPUT_ACTIVE 0x10 +#define PHP_OUTPUT_LOCKED 0x20 + +/* handler hooks */ +#define PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ 1 +#define PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS 2 +#define PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE 3 +#define PHP_OUTPUT_HANDLER_HOOK_DISABLE 4 + +#define PHP_OUTPUT_HANDLER_INITBUF_SIZE(s) \ +( (s) ? \ + (s) + PHP_OUTPUT_HANDLER_ALIGNTO_SIZE - ((s) % (PHP_OUTPUT_HANDLER_ALIGNTO_SIZE >> 2)) : \ + PHP_OUTPUT_HANDLER_DEFAULT_SIZE \ +) +#define PHP_OUTPUT_HANDLER_ALIGNTO_SIZE 0x1000 +#define PHP_OUTPUT_HANDLER_DEFAULT_SIZE 0x4000 +#define PHP_OUTPUT_HANDLER_DEFAULT_NAME "default output handler" +#define PHP_OUTPUT_HANDLER_DEVNULL_NAME "null output handler" + +PHPAPI zval php_output_handler_default; +PHPAPI zval php_output_handler_devnull; + +typedef struct _php_output_buffer { + char *data; + size_t size; + size_t used; + uint free:1; + uint _res:31; +} php_output_buffer; + +typedef struct _php_output_context { + int op; + php_output_buffer in; + php_output_buffer out; +#ifdef ZTS + void ***tsrm_ls; +#endif +} php_output_context; + +#define PHP_OUTPUT_TSRMLS(ctx) TSRMLS_FETCH_FROM_CTX((ctx)->tsrm_ls) + +/* old-style, stateless callback */ typedef void (*php_output_handler_func_t)(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC); +/* new-style, opaque context callback */ +typedef int (*php_output_handler_context_func_t)(void **handler_context, php_output_context *output_context); +/* conflict check callback */ +typedef int (*php_output_handler_conflict_check_t)(zval *handler_name TSRMLS_DC); + +typedef struct _php_output_handler { + zval *name; + int flags; + int level; + size_t size; + php_output_buffer buffer; + + void *opaq; + void (*dtor)(void *opaq TSRMLS_DC); + + union { + zval *user; + php_output_handler_context_func_t internal; + }; +} php_output_handler; + +ZEND_BEGIN_MODULE_GLOBALS(output) + int flags; + zend_stack handlers; + php_output_handler *active; + php_output_handler *running; + char *output_start_filename; + int output_start_lineno; + zval *default_output_handler_name; + zval *devnull_output_handler_name; +ZEND_END_MODULE_GLOBALS(output); + +/* there should not be a need to use OG() from outside of output.c */ +#ifdef ZTS +#define OG(v) TSRMG(output_globals_id, zend_output_globals *, v) +#else +#define OG(v) (output_globals.v) +#endif + +/* convenience macros */ +#define PHPWRITE(str, str_len) php_output_write((str), (str_len)) +#define PHPWRITE_H(str, str_len) php_output_write_unbuffered((str), (str_len)) + +#define PUTC(c) (php_output_write(&(c), 1), (c)) +#define PUTC_H(c) (php_output_write_unbuffered(&(c), 1), (c)) + +#define PUTS(str) do { \ + const char *__str = (str); \ + php_output_write(__str, strlen(__str)); \ +} while (0) +#define PUTS_H(str) do { \ + const char *__str = (str); \ + php_output_write_unbuffered(__str, strlen(__str)); \ +} while (0) + BEGIN_EXTERN_C() +#define php_output_tearup() \ + php_output_startup(); \ + php_output_activate() +#define php_output_teardown() \ + php_output_end_all(); \ + php_output_deactivate(); \ + php_output_shutdown() + +/* MINIT */ PHPAPI void php_output_startup(void); -PHPAPI void php_output_activate(TSRMLS_D); -PHPAPI void php_output_set_status(zend_bool status TSRMLS_DC); -PHPAPI void php_output_register_constants(TSRMLS_D); -PHPAPI int php_default_output_func(const char *str, uint str_len TSRMLS_DC); -PHPAPI int php_ub_body_write(const char *str, uint str_length TSRMLS_DC); -PHPAPI int php_ub_body_write_no_header(const char *str, uint str_length TSRMLS_DC); -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); -PHPAPI int php_ob_get_length(zval *p TSRMLS_DC); -PHPAPI void php_start_implicit_flush(TSRMLS_D); -PHPAPI void php_end_implicit_flush(TSRMLS_D); -PHPAPI char *php_get_output_start_filename(TSRMLS_D); -PHPAPI int php_get_output_start_lineno(TSRMLS_D); -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); -PHPAPI int php_ob_handler_used(char *handler_name TSRMLS_DC); -PHPAPI int php_ob_init_conflict(char *handler_new, char *handler_set TSRMLS_DC); -PHPAPI int php_ob_get_buffer(zval *p TSRMLS_DC); -PHPAPI int php_ob_get_length(zval *p TSRMLS_DC); +/* MSHUTDOWN */ +PHPAPI void php_output_shutdown(void); + +#define php_output_register_constants() _php_output_register_constants(TSRMLS_C) +PHPAPI void _php_output_register_constants(TSRMLS_D); + +/* RINIT */ +#define php_output_activate() _php_output_activate(TSRMLS_C) +PHPAPI int _php_output_activate(TSRMLS_D); +/* RSHUTDOWN */ +#define php_output_deactivate() _php_output_deactivate(TSRMLS_C) +PHPAPI void _php_output_deactivate(TSRMLS_D); + + +#define php_output_get_default_handler_name() _php_output_get_default_handler_name(TSRMLS_C) +PHPAPI zval *_php_output_get_default_handler_name(TSRMLS_D); + +#define php_output_get_devnull_handler_name() _php_output_get_devnull_handler_name(TSRMLS_C) +PHPAPI zval *_php_output_get_devnull_handler_name(TSRMLS_D); + + +#define php_output_set_status(s) _php_output_set_status((s) TSRMLS_CC) +PHPAPI void _php_output_set_status(int status TSRMLS_DC); + +#define php_output_get_status() _php_output_get_status(TSRMLS_C) +PHPAPI int _php_output_get_status(TSRMLS_D); + +#define php_output_write_unbuffered(s, l) _php_output_write_unbuffered((s), (l) TSRMLS_CC) +PHPAPI int _php_output_write_unbuffered(const char *str, size_t len TSRMLS_DC); + +#define php_output_write(s, l) _php_output_write((s), (l) TSRMLS_CC) +PHPAPI int _php_output_write(const char *str, size_t len TSRMLS_DC); + +#define php_output_flush() _php_output_flush(TSRMLS_C) +PHPAPI void _php_output_flush(TSRMLS_D); + +#define php_output_flush_all() _php_output_flush_all(TSRMLS_C) +PHPAPI void _php_output_flush_all(TSRMLS_D); + +#define php_output_clean() _php_output_clean(TSRMLS_C) +PHPAPI int _php_output_clean(TSRMLS_D); + +#define php_output_clean_all() _php_output_clean_all(TSRMLS_C) +PHPAPI void _php_output_clean_all(TSRMLS_D); + +#define php_output_end() _php_output_end(TSRMLS_C) +PHPAPI int _php_output_end(TSRMLS_D); + +#define php_output_end_all() _php_output_end_all(TSRMLS_C) +PHPAPI void _php_output_end_all(TSRMLS_D); + +#define php_output_discard() _php_output_discard(TSRMLS_C) +PHPAPI int _php_output_discard(TSRMLS_D); + +#define php_output_discard_all() _php_output_discard_all(TSRMLS_C) +PHPAPI void _php_output_discard_all(TSRMLS_D); + + +#define php_output_get_contents(p) _php_output_get_contents((p) TSRMLS_CC) +PHPAPI int _php_output_get_contents(zval *p TSRMLS_DC); + +#define php_output_get_length(p) _php_output_get_length((p) TSRMLS_CC) +PHPAPI int _php_output_get_length(zval *TSRMLS_DC); + +#define php_output_get_level() _php_output_get_level(TSRMLS_C) +PHPAPI int _php_output_get_level(TSRMLS_D); + + +#define php_output_start_default() _php_output_start_default(TSRMLS_C) +PHPAPI int _php_output_start_default(TSRMLS_D); + +#define php_output_start_devnull() _php_output_start_devnull(TSRMLS_C) +PHPAPI int _php_output_start_devnull(TSRMLS_D); + +#define php_output_start_user(h, s, f) _php_output_start_user((h), (s), (f) TSRMLS_CC) +PHPAPI int _php_output_start_user(zval *output_handler, size_t chunk_size, int flags TSRMLS_DC); + +#define php_output_start_internal(n, h, s, f) _php_output_start_internal((n), (h), (s), (f) TSRMLS_CC) +PHPAPI int _php_output_start_internal(zval *name, php_output_handler_func_t output_handler, size_t chunk_size, int flags TSRMLS_DC); + +#define php_output_handler_create_user(h, s, f) _php_output_handler_create_user((h), (s), (f) TSRMLS_CC) +PHPAPI php_output_handler *_php_output_handler_create_user(zval *handler, size_t chunk_size, int flags TSRMLS_DC); + +#define php_output_handler_create_internal(n, h, s, f) _php_output_handler_create_internal((n), (h), (s), (f) TSRMLS_CC) +PHPAPI php_output_handler *_php_output_handler_create_internal(zval *name, php_output_handler_context_func_t handler, size_t chunk_size, int flags TSRMLS_DC); + +#define php_output_handler_set_context(h, c, d) _php_output_handler_set_context((h), (c), (d) TSRMLS_CC) +PHPAPI void _php_output_handler_set_context(php_output_handler *handler, void *opaq, void (*dtor)(void* TSRMLS_DC) TSRMLS_DC); + +#define php_output_handler_start(h) _php_output_handler_start((h) TSRMLS_CC) +PHPAPI int _php_output_handler_start(php_output_handler *handler TSRMLS_DC); + +#define php_output_handler_started(n) _php_output_handler_started((n) TSRMLS_CC) +PHPAPI int _php_output_handler_started(zval *name TSRMLS_DC); + +#define php_output_handler_hook(t, a) _php_output_handler_hook((t), (a) TSRMLS_CC) +PHPAPI int _php_output_handler_hook(int type, void *arg TSRMLS_DC); + +#define php_output_handler_dtor(h) _php_output_handler_dtor((h) TSRMLS_CC) +PHPAPI void _php_output_handler_dtor(php_output_handler *handler TSRMLS_DC); + +#define php_output_handler_free(h) _php_output_handler_free((h) TSRMLS_CC) +PHPAPI void _php_output_handler_free(php_output_handler **handler TSRMLS_DC); + + +#define php_output_set_implicit_flush(f) _php_output_set_implicit_flush((f) TSRMLS_CC) +PHPAPI void _php_output_set_implicit_flush(int flush TSRMLS_DC); + +#define php_output_get_start_filename() _php_output_get_start_filename(TSRMLS_C) +PHPAPI char *_php_output_get_start_filename(TSRMLS_D); + +#define php_output_get_start_lineno() _php_output_get_start_lineno(TSRMLS_C) +PHPAPI int _php_output_get_start_lineno(TSRMLS_D); + + +#define php_output_handler_conflict(n, s) _php_output_handler_conflict((n), (s) TSRMLS_CC) +PHPAPI int _php_output_handler_conflict(zval *handler_new, zval *handler_set TSRMLS_DC); + +#define php_output_handler_conflict_register(n, f) _php_output_handler_conflict_register((n), (f) TSRMLS_CC) +PHPAPI int _php_output_handler_conflict_register(zval *handler_name, php_output_handler_conflict_check_t check_func TSRMLS_DC); + +#define php_output_handler_reverse_conflict_register(n, f) _php_output_handler_reverse_conflict_register((n), (f) TSRMLS_CC) +PHPAPI int _php_output_handler_reverse_conflict_register(zval *handler_name, php_output_handler_conflict_check_t check_func TSRMLS_DC); + +#define php_output_handler_alias(n) _php_output_handler_alias((n) TSRMLS_CC) +PHPAPI php_output_handler_context_func_t *_php_output_handler_alias(zval *handler_name TSRMLS_DC); + +#define php_output_handler_alias_register(n, f) _php_output_handler_alias_register((n), (f) TSRMLS_CC) +PHPAPI int _php_output_handler_alias_register(zval *handler_name, php_output_handler_context_func_t func TSRMLS_DC); + END_EXTERN_C() + PHP_FUNCTION(ob_start); PHP_FUNCTION(ob_flush); PHP_FUNCTION(ob_clean); @@ -64,51 +311,16 @@ PHP_FUNCTION(ob_implicit_flush); PHP_FUNCTION(ob_list_handlers); -typedef struct _php_ob_buffer { - char *buffer; - uint size; - uint text_length; - int block_size; - uint chunk_size; - int status; - zval *output_handler; - php_output_handler_func_t internal_output_handler; - char *internal_output_handler_buffer; - uint internal_output_handler_buffer_size; - zstr handler_name; - zend_bool erase; -} php_ob_buffer; - -typedef struct _php_output_globals { - int (*php_body_write)(const char *str, uint str_length TSRMLS_DC); /* string output */ - int (*php_header_write)(const char *str, uint str_length TSRMLS_DC); /* unbuffer string output */ - php_ob_buffer active_ob_buffer; - unsigned char implicit_flush; - char *output_start_filename; - int output_start_lineno; - zend_stack ob_buffers; - int ob_nesting_level; - zend_bool ob_lock; - zend_bool disable_output; -} php_output_globals; - -#ifdef ZTS -#define OG(v) TSRMG(output_globals_id, php_output_globals *, v) -ZEND_API extern int output_globals_id; -#else -#define OG(v) (output_globals.v) -ZEND_API extern php_output_globals output_globals; -#endif - -#define PHP_OUTPUT_HANDLER_START (1<<0) -#define PHP_OUTPUT_HANDLER_CONT (1<<1) -#define PHP_OUTPUT_HANDLER_END (1<<2) - -#define PHP_OUTPUT_HANDLER_INTERNAL 0 -#define PHP_OUTPUT_HANDLER_USER 1 - PHP_FUNCTION(output_add_rewrite_var); PHP_FUNCTION(output_reset_rewrite_vars); +#endif -#endif /* PHP_OUTPUT_H */ +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ http://cvs.php.net/viewcvs.cgi/php-src/sapi/apache/mod_php5.c?r1=1.33&r2=1.34&diff_format=u Index: php-src/sapi/apache/mod_php5.c diff -u php-src/sapi/apache/mod_php5.c:1.33 php-src/sapi/apache/mod_php5.c:1.34 --- php-src/sapi/apache/mod_php5.c:1.33 Sat May 13 21:48:14 2006 +++ php-src/sapi/apache/mod_php5.c Fri Jun 2 19:51:42 2006 @@ -17,7 +17,7 @@ | PHP 4.0 patches by Zeev Suraski <zeev@zend.com> | +----------------------------------------------------------------------+ */ -/* $Id: mod_php5.c,v 1.33 2006/05/13 21:48:14 rasmus Exp $ */ +/* $Id: mod_php5.c,v 1.34 2006/06/02 19:51:42 mike Exp $ */ #include "php_apache_http.h" #include "http_conf_globals.h" @@ -315,7 +315,7 @@ { TSRMLS_FETCH(); - php_output_set_status(0 TSRMLS_CC); + php_output_set_status(PHP_OUTPUT_DISABLED); if (AP(in_request)) { AP(in_request) = 0; php_request_shutdown(dummy); http://cvs.php.net/viewcvs.cgi/php-src/sapi/apache/php_apache.c?r1=1.94&r2=1.95&diff_format=u Index: php-src/sapi/apache/php_apache.c diff -u php-src/sapi/apache/php_apache.c:1.94 php-src/sapi/apache/php_apache.c:1.95 --- php-src/sapi/apache/php_apache.c:1.94 Wed Apr 26 09:32:11 2006 +++ php-src/sapi/apache/php_apache.c Fri Jun 2 19:51:42 2006 @@ -17,7 +17,7 @@ | David Sklar <sklar@student.net> | +----------------------------------------------------------------------+ */ -/* $Id: php_apache.c,v 1.94 2006/04/26 09:32:11 edink Exp $ */ +/* $Id: php_apache.c,v 1.95 2006/06/02 19:51:42 mike Exp $ */ #include "php_apache_http.h" @@ -329,7 +329,7 @@ RETURN_FALSE; } - php_end_ob_buffers(1 TSRMLS_CC); + php_output_end_all(); php_header(TSRMLS_C); if (run_sub_req(rr)) { http://cvs.php.net/viewcvs.cgi/php-src/sapi/apache2handler/php_functions.c?r1=1.24&r2=1.25&diff_format=u Index: php-src/sapi/apache2handler/php_functions.c diff -u php-src/sapi/apache2handler/php_functions.c:1.24 php-src/sapi/apache2handler/php_functions.c:1.25 --- php-src/sapi/apache2handler/php_functions.c:1.24 Tue Jan 3 20:13:31 2006 +++ php-src/sapi/apache2handler/php_functions.c Fri Jun 2 19:51:42 2006 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_functions.c,v 1.24 2006/01/03 20:13:31 iliaa Exp $ */ +/* $Id: php_functions.c,v 1.25 2006/06/02 19:51:42 mike Exp $ */ #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS @@ -93,7 +93,7 @@ } /* Flush everything. */ - php_end_ob_buffers(1 TSRMLS_CC); + php_output_end_all(); php_header(TSRMLS_C); /* Ensure that the ap_r* layer for the main request is flushed, to http://cvs.php.net/viewcvs.cgi/php-src/sapi/apache_hooks/mod_php5.c?r1=1.16&r2=1.17&diff_format=u Index: php-src/sapi/apache_hooks/mod_php5.c diff -u php-src/sapi/apache_hooks/mod_php5.c:1.16 php-src/sapi/apache_hooks/mod_php5.c:1.17 --- php-src/sapi/apache_hooks/mod_php5.c:1.16 Tue Mar 7 00:20:54 2006 +++ php-src/sapi/apache_hooks/mod_php5.c Fri Jun 2 19:51:43 2006 @@ -17,7 +17,7 @@ | PHP 4.0 patches by Zeev Suraski <zeev@zend.com> | +----------------------------------------------------------------------+ */ -/* $Id: mod_php5.c,v 1.16 2006/03/07 00:20:54 pajoye Exp $ */ +/* $Id: mod_php5.c,v 1.17 2006/06/02 19:51:43 mike Exp $ */ #include "php_apache_http.h" @@ -434,7 +434,7 @@ { TSRMLS_FETCH(); AP(current_hook) = AP_CLEANUP; - php_output_set_status(0 TSRMLS_CC); + php_output_set_status(PHP_OUTPUT_DISABLED); SG(server_context) = NULL; /* The server context (request) is invalid by the time run_cleanups() is called */ if(SG(sapi_started)) { php_request_shutdown(dummy); http://cvs.php.net/viewcvs.cgi/php-src/sapi/apache_hooks/php_apache.c?r1=1.24&r2=1.25&diff_format=u Index: php-src/sapi/apache_hooks/php_apache.c diff -u php-src/sapi/apache_hooks/php_apache.c:1.24 php-src/sapi/apache_hooks/php_apache.c:1.25 --- php-src/sapi/apache_hooks/php_apache.c:1.24 Tue Mar 7 14:43:16 2006 +++ php-src/sapi/apache_hooks/php_apache.c Fri Jun 2 19:51:43 2006 @@ -17,7 +17,7 @@ | David Sklar <sklar@student.net> | +----------------------------------------------------------------------+ */ -/* $Id: php_apache.c,v 1.24 2006/03/07 14:43:16 iliaa Exp $ */ +/* $Id: php_apache.c,v 1.25 2006/06/02 19:51:43 mike Exp $ */ #include "php_apache_http.h" @@ -1731,7 +1731,7 @@ RETURN_FALSE; } - php_end_ob_buffers(1 TSRMLS_CC); + php_output_end_all(); php_header(TSRMLS_C); if (run_sub_req(rr)) { http://cvs.php.net/viewcvs.cgi/php-src/sapi/cgi/cgi_main.c?r1=1.289&r2=1.290&diff_format=u Index: php-src/sapi/cgi/cgi_main.c diff -u php-src/sapi/cgi/cgi_main.c:1.289 php-src/sapi/cgi/cgi_main.c:1.290 --- php-src/sapi/cgi/cgi_main.c:1.289 Wed May 24 09:41:55 2006 +++ php-src/sapi/cgi/cgi_main.c Fri Jun 2 19:51:43 2006 @@ -21,7 +21,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: cgi_main.c,v 1.289 2006/05/24 09:41:55 dmitry Exp $ */ +/* $Id: cgi_main.c,v 1.290 2006/06/02 19:51:43 mike Exp $ */ #include "php.h" #include "php_globals.h" @@ -1266,11 +1266,10 @@ case 'h': case '?': no_headers = 1; - php_output_startup(); - php_output_activate(TSRMLS_C); + php_output_tearup(); SG(headers_sent) = 1; php_cgi_usage(argv[0]); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); exit(1); break; } @@ -1299,11 +1298,10 @@ if (!cgi && !fastcgi) { if (cgi_sapi_module.php_ini_path_override && cgi_sapi_module.php_ini_ignore) { no_headers = 1; - php_output_startup(); - php_output_activate(TSRMLS_C); + php_output_tearup(); SG(headers_sent) = 1; php_printf("You cannot use both -n and -c switch. Use -h for help.\n"); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); exit(1); } @@ -1349,7 +1347,7 @@ SG(request_info).no_headers = 1; } php_print_info(0xFFFFFFFF TSRMLS_CC); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); exit(0); break; @@ -1359,15 +1357,14 @@ break; case 'm': /* list compiled in modules */ - php_output_startup(); - php_output_activate(TSRMLS_C); + php_output_tearup(); SG(headers_sent) = 1; php_printf("[PHP Modules]\n"); print_modules(TSRMLS_C); php_printf("\n[Zend Modules]\n"); print_extensions(TSRMLS_C); php_printf("\n"); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); exit(0); break; @@ -1400,7 +1397,7 @@ #else php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2006 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); #endif - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); exit(0); break; @@ -1562,7 +1559,7 @@ if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) { zend_strip(TSRMLS_C); fclose(file_handle.handle.fp); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); } return SUCCESS; break; @@ -1574,7 +1571,7 @@ php_get_highlight_struct(&syntax_highlighter_ini); zend_highlight(&syntax_highlighter_ini TSRMLS_CC); fclose(file_handle.handle.fp); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); } return SUCCESS; } @@ -1585,6 +1582,7 @@ open_file_for_scanning(&file_handle TSRMLS_CC); zend_indent(); fclose(file_handle.handle.fp); + php_output_teardown(); return SUCCESS; break; #endif http://cvs.php.net/viewcvs.cgi/php-src/sapi/cli/php_cli.c?r1=1.153&r2=1.154&diff_format=u Index: php-src/sapi/cli/php_cli.c diff -u php-src/sapi/cli/php_cli.c:1.153 php-src/sapi/cli/php_cli.c:1.154 --- php-src/sapi/cli/php_cli.c:1.153 Thu May 11 22:08:55 2006 +++ php-src/sapi/cli/php_cli.c Fri Jun 2 19:51:43 2006 @@ -20,7 +20,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_cli.c,v 1.153 2006/05/11 22:08:55 dmitry Exp $ */ +/* $Id: php_cli.c,v 1.154 2006/06/02 19:51:43 mike Exp $ */ #include "php.h" #include "php_globals.h" @@ -719,7 +719,7 @@ goto err; } php_cli_usage(argv[0]); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_end_all(); exit_status=0; goto out; @@ -728,7 +728,7 @@ goto err; } php_print_info(0xFFFFFFFF TSRMLS_CC); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_end_all(); exit_status=0; goto out; @@ -741,7 +741,7 @@ php_printf("\n[Zend Modules]\n"); print_extensions(TSRMLS_C); php_printf("\n"); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_end_all(); exit_status=0; goto out; @@ -763,7 +763,7 @@ #endif get_zend_version() ); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_end_all(); exit_status=0; goto out; http://cvs.php.net/viewcvs.cgi/php-src/sapi/milter/php_milter.c?r1=1.16&r2=1.17&diff_format=u Index: php-src/sapi/milter/php_milter.c diff -u php-src/sapi/milter/php_milter.c:1.16 php-src/sapi/milter/php_milter.c:1.17 --- php-src/sapi/milter/php_milter.c:1.16 Sun Jan 1 13:09:58 2006 +++ php-src/sapi/milter/php_milter.c Fri Jun 2 19:51:43 2006 @@ -966,11 +966,10 @@ while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) { switch (c) { case '?': - php_output_startup(); - php_output_activate(TSRMLS_C); + php_output_tearup(); SG(headers_sent) = 1; php_milter_usage(argv[0]); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); exit(1); break; } @@ -1021,11 +1020,10 @@ case 'h': /* help & quit */ case '?': - php_output_startup(); - php_output_activate(TSRMLS_C); + php_output_tearup(); SG(headers_sent) = 1; php_milter_usage(argv[0]); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); exit(1); break; @@ -1045,7 +1043,7 @@ SG(headers_sent) = 1; SG(request_info).no_headers = 1; php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2006 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); - php_end_ob_buffers(1 TSRMLS_CC); + php_output_teardown(); exit(1); break; http://cvs.php.net/viewcvs.cgi/php-src/sapi/nsapi/nsapi.c?r1=1.74&r2=1.75&diff_format=u Index: php-src/sapi/nsapi/nsapi.c diff -u php-src/sapi/nsapi/nsapi.c:1.74 php-src/sapi/nsapi/nsapi.c:1.75 --- php-src/sapi/nsapi/nsapi.c:1.74 Sat Apr 29 21:50:17 2006 +++ php-src/sapi/nsapi/nsapi.c Fri Jun 2 19:51:43 2006 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: nsapi.c,v 1.74 2006/04/29 21:50:17 thetaphi Exp $ */ +/* $Id: nsapi.c,v 1.75 2006/06/02 19:51:43 mike Exp $ */ /* * PHP includes @@ -310,7 +310,7 @@ PHP_MINFO_FUNCTION(nsapi) { php_info_print_table_start(); - php_info_print_table_row(2, "NSAPI Module Revision", "$Revision: 1.74 $"); + php_info_print_table_row(2, "NSAPI Module Revision", "$Revision: 1.75 $"); php_info_print_table_row(2, "Server Software", system_version()); php_info_print_table_row(2, "Sub-requests with nsapi_virtual()", (nsapi_servact_service)?((zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0))?"not supported with zlib.output_compression":"enabled"):"not supported on this platform" ); @@ -347,7 +347,7 @@ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include uri '%s' - Sub-requests do not work with zlib.output_compression", (*uri)->value.str.val); RETURN_FALSE; } else { - php_end_ob_buffers(1 TSRMLS_CC); + php_output_end_all(); php_header(TSRMLS_C); /* do the sub-request */ http://cvs.php.net/viewcvs.cgi/php-src/README.NEW-OUTPUT-API?view=markup&rev=1.1 Index: php-src/README.NEW-OUTPUT-API +++ php-src/README.NEW-OUTPUT-API $Id: README.NEW-OUTPUT-API,v 1.1 2006/06/02 19:51:42 mike Exp $ API adjustment to the old output control code: Everything now resides beneath the php_output namespace, and there's an API call for every output handler op. However, there's a thin compatibility layer unless PHP_OUTPUT_NOCOMPAT is defined. Checking output control layers status: // Using OG() php_output_get_status(); Starting the default output handler: // php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC); php_output_start_default(); Starting an user handler by zval: // php_start_ob_buffer(zhandler, chunk_size, erase TSRMLS_CC); php_output_start_user(zhandler, chunk_size, flags); Starting an internal handler whithout context: // php_ob_set_internal_handler(my_php_output_handler_func_t, buffer_size, "output handler name", erase TSRMLS_CC); php_output_start_internal(handler_name_zval, my_php_output_handler_func_t, chunk_size, flags); Starting an internal handler with context: // not possible with old API php_output_handler *h; h = php_output_handler_create_internal(handler_name_zval, my_php_output_handler_context_func_t, chunk_size, flags); php_output_handler_set_context(h, my_context, my_context_dtor); php_output_handler_start(h); Testing whether a certain output handler has already been started: // php_ob_handler_used("output handler name" TSRMLS_CC); php_output_handler_started(handler_name_zval); Flushing one output buffer: // php_ob_end_buffer(1, 1 TSRMLS_CC); php_output_flush(); Flushing all output buffers: // not possible with old API php_output_flush_all(); Cleaning one output buffer: // php_ob_end_buffer(0, 1 TSRMLS_CC); php_output_clean(); Cleaning all output buffers: // not possible with old API php_output_clean_all(); Discarding one output buffer: // php_ob_end_buffer(0, 0 TSRMLS_CC); php_output_discard(); Discarding all output buffers: // php_ob_end_buffers(0 TSRMLS_CC); php_output_discard_all(); Stopping (and dropping) one output buffer: // php_ob_end_buffer(1, 0 TSRMLS_CC) php_output_end(); Stopping (and dropping) all output buffers: // php_ob_end_buffers(1, 0 TSRMLS_CC); php_output_end_all(); Retrieving output buffers contents: // php_ob_get_buffer(zstring TSRMLS_CC); php_output_get_contents(zstring); Retrieving output buffers length: // php_ob_get_length(zlength TSRMLS_CC); php_output_get_length(zlenght); Retrieving output buffering level: // OG(nesting_level); php_output_get_level(); Issue a warning because of an output handler conflict: // php_ob_init_conflict("to be started handler name", "to be tested if already started handler name" TSRMLS_CC); php_output_handler_conflict(new_handler_name_zval, set_handler_name_zval); Registering a conflict checking function, which will be checked prior starting the handler: // not possible with old API, unless hardcoding into output.c php_output_handler_conflict_register(handler_name_zval, my_php_output_handler_conflict_check_t); Registering a reverse conflict checking function, which will be checked prior starting the specified foreign handler: // not possible with old API php_output_handler_reverse_conflict_register(foreign_handler_name_zval, my_php_output_handler_conflict_check_t); Facilitating a context from within an output handler callable with ob_start(): // not possible with old API php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ, (void *) &custom_ctx_ptr_ptr); Disabling of the output handler by itself: //not possible with old API php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_DISABLE, NULL); Marking an output handler immutable by itself because of irreversibility of its operation: // not possible with old API php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL); Restarting the output handler because of a CLEAN operation: // not possible with old API if (flags & PHP_OUTPUT_HANDLER_CLEAN) { ... } Recognizing by the output handler itself if it gets discarded: // not possible with old API if ((flags & PHP_OUTPUT_HANDLER_CLEAN) && (flags & PHP_OUTPUT_HANDLER_FINAL)) { ... } Output handler hooks The output handler can change its abilities at runtime. Eg. the gz handler can remove the CLEANABLE and REMOVABLE bits when the first output has passed through it; or handlers implemented in C to be used with ob_start() can contain a non-global context: PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ pass a void*** pointer as second arg to receive the address of a pointer pointer to the opaque field of the output handler context PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS pass a int* pointer as second arg to receive the flags set for the output handler PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE the second arg is ignored; marks the output handler to be neither cleanable nor removable PHP_OUTPUT_HANDLER_HOOK_DISABLE the second arg is ignored; marks the output handler as disabled Open questions Should the userland API be adjusted and unified? Many bits of the manual (and very first implementation) do not comply with the behaviour of the current (to be obsoleted) code, thus should the manual or the behaviour be adjusted? END http://cvs.php.net/viewcvs.cgi/php-src/tests/output/.cvsignore?view=markup&rev=1.1 Index: php-src/tests/output/.cvsignore +++ php-src/tests/output/.cvsignore *.php *.log *.diff *.exp *.out *~ http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_001.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_001.phpt +++ php-src/tests/output/ob_001.phpt --TEST-- output buffering - nothing --FILE-- <?php echo "foo\n"; ?> --EXPECTF-- foo http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_002.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_002.phpt +++ php-src/tests/output/ob_002.phpt --TEST-- output buffering - ob_start --FILE-- <?php ob_start(); echo "foo\n"; ?> --EXPECT-- foo http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_003.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_003.phpt +++ php-src/tests/output/ob_003.phpt --TEST-- output buffering - ob_flush --FILE-- <?php ob_start(); echo "foo\n"; ob_flush(); echo "bar\n"; ob_flush(); ?> --EXPECT-- foo bar http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_004.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_004.phpt +++ php-src/tests/output/ob_004.phpt --TEST-- output buffering - ob_clean --FILE-- <?php ob_start(); echo "foo\n"; ob_clean(); echo "bar\n"; ?> --EXPECT-- bar http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_005.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_005.phpt +++ php-src/tests/output/ob_005.phpt --TEST-- output buffering - ob_end_clean --FILE-- <?php ob_start(); echo "foo\n"; ob_start(); echo "bar\n"; ob_end_clean(); echo "baz\n"; ?> --EXPECT-- foo baz http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_006.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_006.phpt +++ php-src/tests/output/ob_006.phpt --TEST-- output buffering - ob_end_flush --FILE-- <?php ob_start(); echo "foo\n"; ob_end_flush(); var_dump(ob_get_level()); ?> --EXPECT-- foo int(0) http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_007.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_007.phpt +++ php-src/tests/output/ob_007.phpt --TEST-- output buffering - ob_get_clean --FILE-- <?php ob_start(); echo "foo\n"; var_dump(ob_get_clean()); ?> --EXPECT-- string(4) "foo " http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_008.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_008.phpt +++ php-src/tests/output/ob_008.phpt --TEST-- output buffering - ob_get_contents --FILE-- <?php ob_start(); echo "foo\n"; echo ob_get_contents(); ?> --EXPECT-- foo foo http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_009.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_009.phpt +++ php-src/tests/output/ob_009.phpt --TEST-- output buffering - ob_get_flush --FILE-- <?php ob_start(); echo "foo\n"; var_dump(ob_get_flush()); ?> --EXPECT-- foo string(4) "foo " http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_010.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_010.phpt +++ php-src/tests/output/ob_010.phpt --TEST-- output buffering - fatalism --FILE-- <?php function obh($s) { print_r($s, 1); } ob_start("obh"); echo "foo\n"; ?> --EXPECTF-- Fatal error: print_r(): Cannot use output buffering in output buffering display handlers in %s/ob_010.php on line %d http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_011.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_011.phpt +++ php-src/tests/output/ob_011.phpt --TEST-- output buffering - fatalism --FILE-- <?php function obh($s) { return ob_get_flush(); } ob_start("obh"); echo "foo\n"; ?> --EXPECTF-- Fatal error: ob_get_flush(): Cannot use output buffering in output buffering display handlers in %s/ob_011.php on line %d http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_012.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_012.phpt +++ php-src/tests/output/ob_012.phpt --TEST-- output buffering - multiple --FILE-- <?php echo 0; ob_start(); ob_start(); ob_start(); ob_start(); echo 1; ob_end_flush(); echo 2; $ob = ob_get_clean(); echo 3; ob_flush(); ob_end_clean(); echo 4; ob_end_flush(); echo $ob; ?> --EXPECT-- 03412 http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_013.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_013.phpt +++ php-src/tests/output/ob_013.phpt --TEST-- output buffering - handlers/status --FILE-- <?php function a($s){return $s;} function b($s){return $s;} function c($s){return $s;} function d($s){return $s;} ob_start(); ob_start('a'); ob_start('b'); ob_start('c'); ob_start('d'); ob_start(); echo "foo\n"; ob_flush(); ob_end_clean(); ob_flush(); print_r(ob_list_handlers()); print_r(ob_get_status()); print_r(ob_get_status(true)); ?> --EXPECT-- foo Array ( [0] => default output handler [1] => a [2] => b [3] => c [4] => d ) Array ( [name] => d [type] => 1 [flags] => 4145 [level] => 4 [chunk_size] => 0 [buffer_size] => 16384 [buffer_used] => 96 ) Array ( [0] => Array ( [name] => default output handler [type] => 0 [flags] => 48 [level] => 0 [chunk_size] => 0 [buffer_size] => 16384 [buffer_used] => 0 ) [1] => Array ( [name] => a [type] => 1 [flags] => 49 [level] => 1 [chunk_size] => 0 [buffer_size] => 16384 [buffer_used] => 0 ) [2] => Array ( [name] => b [type] => 1 [flags] => 49 [level] => 2 [chunk_size] => 0 [buffer_size] => 16384 [buffer_used] => 0 ) [3] => Array ( [name] => c [type] => 1 [flags] => 49 [level] => 3 [chunk_size] => 0 [buffer_size] => 16384 [buffer_used] => 4 ) [4] => Array ( [name] => d [type] => 1 [flags] => 4145 [level] => 4 [chunk_size] => 0 [buffer_size] => 16384 [buffer_used] => 248 ) ) http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_014.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_014.phpt +++ php-src/tests/output/ob_014.phpt --TEST-- output buffering - failure --FILE-- <?php /* * apparently the error handler cannot get the current function name on shutdown */ ob_start("str_rot13"); echo "foo\n"; ?> --EXPECTF-- foo Warning: Wrong parameter count for (null)() in %s on line %d http://cvs.php.net/viewcvs.cgi/php-src/tests/output/ob_015.phpt?view=markup&rev=1.1 Index: php-src/tests/output/ob_015.phpt +++ php-src/tests/output/ob_015.phpt --TEST-- output buffering - failure --FILE-- <?php ob_start("str_rot13", 1); echo "foo\n"; ?> --EXPECTF-- foo Warning: Wrong parameter count for str_rot13() in %s on line %d