- 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
This commit is contained in:
Michael Wallner 2006-06-02 19:51:43 +00:00
parent 653007cea0
commit 4ce0141713
42 changed files with 2544 additions and 1592 deletions

140
README.NEW-OUTPUT-API Normal file
View File

@ -0,0 +1,140 @@
$Id$
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

View File

@ -2858,7 +2858,7 @@ PHP_FUNCTION(pg_lo_read_all)
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);

View File

@ -855,8 +855,8 @@ static int php_session_cache_limiter(TSRMLS_D)
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 @@ static void php_session_send_cookie(TSRMLS_D)
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)",

View File

@ -1482,7 +1482,7 @@ PHP_METHOD(SoapServer, handle)
}
}
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_METHOD(SoapServer, handle)
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 @@ PHP_METHOD(SoapServer, handle)
}
#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 @@ PHP_METHOD(SoapServer, handle)
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 @@ PHP_METHOD(SoapServer, handle)
#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 @@ PHP_METHOD(SoapServer, handle)
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 @@ PHP_METHOD(SoapServer, handle)
}
/* 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 @@ static void soap_error_handler(int error_num, const char *error_filename, const
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);

View File

@ -2406,7 +2406,7 @@ PHP_FUNCTION(highlight_file)
}
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 @@ PHP_FUNCTION(highlight_file)
}
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 @@ PHP_FUNCTION(php_strip_whitespace)
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 @@ PHP_FUNCTION(php_strip_whitespace)
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 @@ PHP_FUNCTION(highlight_string)
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 @@ PHP_FUNCTION(highlight_string)
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 @@ PHP_FUNCTION(print_r)
}
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;
}

View File

@ -200,8 +200,8 @@ PHP_FUNCTION(headers_sent)
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()) {

View File

@ -70,7 +70,7 @@ static int php_info_write_wrapper(const char *str, uint str_length)
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 @@ PHPAPI void php_print_info_htmlhead(TSRMLS_D)
}
#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 @@ PHPAPI void php_print_info_htmlhead(TSRMLS_D)
#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 @@ PHP_FUNCTION(phpinfo)
}
/* 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;
}

File diff suppressed because it is too large Load Diff

View File

@ -453,7 +453,7 @@ int php_url_scanner_add_var(char *name, int name_len, char *value, int value_len
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;
}

View File

@ -12,7 +12,7 @@
| 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<EFBFBD>i <jkl@njet.net> |
| Thies C. Arntzen <thies@thieso.net> |
| Sascha Schumann <sascha@schumann.cx> |
+----------------------------------------------------------------------+
@ -602,7 +602,7 @@ PHP_FUNCTION(var_export)
}
if (return_output) {
php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC);
php_output_start_default();
}
/* UTODO
@ -614,8 +614,8 @@ PHP_FUNCTION(var_export)
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();
}
}
/* }}} */

View File

@ -985,9 +985,13 @@ PHP_MINIT_FUNCTION(tidy)
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;

View File

@ -13,7 +13,7 @@
| 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<EFBFBD>rich <sr@linux.de> |
+----------------------------------------------------------------------+
*/
@ -55,7 +55,7 @@ PHP_FUNCTION(ob_gzhandler);
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;

View File

@ -13,7 +13,7 @@
| 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<EFBFBD>rich <sr@linux.de> |
| Zeev Suraski <zeev@zend.com> |
| Jade Nicoletti <nicoletti@nns.ch> |
+----------------------------------------------------------------------+
@ -211,11 +211,15 @@ static void php_zlib_init_globals(zend_zlib_globals *zlib_globals_p TSRMLS_DC)
*/
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_FUNCTION(gzencode)
/* {{{ 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 @@ PHP_FUNCTION(ob_gzhandler)
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 @@ PHP_FUNCTION(ob_gzhandler)
|| 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 @@ PHP_FUNCTION(ob_gzhandler)
}
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 @@ static void php_gzip_output_handler(char *output, uint output_len, char **handle
*/
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 @@ int php_enable_output_compression(int buffer_size TSRMLS_DC)
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;
}

View File

@ -553,8 +553,8 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
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 @@ SAPI_API int sapi_send_headers(TSRMLS_D)
}
#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. */

View File

@ -234,8 +234,8 @@ static ZEND_INI_MH(OnUpdateOutputEncoding)
#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 @@ static void php_error_cb(int type, const char *error_filename, const uint error_
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 @@ int php_request_startup(TSRMLS_D)
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 @@ int php_request_startup(TSRMLS_D)
}
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 @@ int php_request_startup(TSRMLS_D)
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 @@ int php_request_startup_for_hook(TSRMLS_D)
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 @@ void php_request_shutdown(void *dummy)
/* 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 @@ void php_request_shutdown(void *dummy)
/* }}} */
/* {{{ 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 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
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 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
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 @@ void php_module_shutdown(TSRMLS_D)
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 @@ PHPAPI void php_handle_aborted_connection(void)
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();

File diff suppressed because it is too large Load Diff

View File

@ -373,20 +373,7 @@ END_EXTERN_C()
/* 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

View File

@ -12,7 +12,7 @@
| 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> |
+----------------------------------------------------------------------+
*/
@ -21,35 +21,282 @@
#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_get_status);
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
*/

View File

@ -315,7 +315,7 @@ static void php_apache_request_shutdown(void *dummy)
{
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);

View File

@ -329,7 +329,7 @@ PHP_FUNCTION(virtual)
RETURN_FALSE;
}
php_end_ob_buffers(1 TSRMLS_CC);
php_output_end_all();
php_header(TSRMLS_C);
if (run_sub_req(rr)) {

View File

@ -93,7 +93,7 @@ PHP_FUNCTION(virtual)
}
/* 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

View File

@ -434,7 +434,7 @@ static void php_apache_request_shutdown(void *dummy)
{
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);

View File

@ -1731,7 +1731,7 @@ PHP_FUNCTION(virtual)
RETURN_FALSE;
}
php_end_ob_buffers(1 TSRMLS_CC);
php_output_end_all();
php_header(TSRMLS_C);
if (run_sub_req(rr)) {

View File

@ -1266,11 +1266,10 @@ consult the installation file that came with this distribution, or visit \n\
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 @@ consult the installation file that came with this distribution, or visit \n\
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 @@ consult the installation file that came with this distribution, or visit \n\
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 @@ consult the installation file that came with this distribution, or visit \n\
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 @@ consult the installation file that came with this distribution, or visit \n\
#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 @@ consult the installation file that came with this distribution, or visit \n\
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 @@ consult the installation file that came with this distribution, or visit \n\
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 @@ consult the installation file that came with this distribution, or visit \n\
open_file_for_scanning(&file_handle TSRMLS_CC);
zend_indent();
fclose(file_handle.handle.fp);
php_output_teardown();
return SUCCESS;
break;
#endif

View File

@ -719,7 +719,7 @@ int main(int argc, char *argv[])
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 @@ int main(int argc, char *argv[])
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 @@ int main(int argc, char *argv[])
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 @@ int main(int argc, char *argv[])
#endif
get_zend_version()
);
php_end_ob_buffers(1 TSRMLS_CC);
php_output_end_all();
exit_status=0;
goto out;

View File

@ -966,11 +966,10 @@ int main(int argc, char *argv[])
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 @@ int main(int argc, char *argv[])
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 @@ int main(int argc, char *argv[])
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;

View File

@ -347,7 +347,7 @@ PHP_FUNCTION(nsapi_virtual)
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 */

8
tests/output/ob_001.phpt Normal file
View File

@ -0,0 +1,8 @@
--TEST--
output buffering - nothing
--FILE--
<?php
echo "foo\n";
?>
--EXPECTF--
foo

9
tests/output/ob_002.phpt Normal file
View File

@ -0,0 +1,9 @@
--TEST--
output buffering - ob_start
--FILE--
<?php
ob_start();
echo "foo\n";
?>
--EXPECT--
foo

13
tests/output/ob_003.phpt Normal file
View File

@ -0,0 +1,13 @@
--TEST--
output buffering - ob_flush
--FILE--
<?php
ob_start();
echo "foo\n";
ob_flush();
echo "bar\n";
ob_flush();
?>
--EXPECT--
foo
bar

11
tests/output/ob_004.phpt Normal file
View File

@ -0,0 +1,11 @@
--TEST--
output buffering - ob_clean
--FILE--
<?php
ob_start();
echo "foo\n";
ob_clean();
echo "bar\n";
?>
--EXPECT--
bar

14
tests/output/ob_005.phpt Normal file
View File

@ -0,0 +1,14 @@
--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

12
tests/output/ob_006.phpt Normal file
View File

@ -0,0 +1,12 @@
--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)

11
tests/output/ob_007.phpt Normal file
View File

@ -0,0 +1,11 @@
--TEST--
output buffering - ob_get_clean
--FILE--
<?php
ob_start();
echo "foo\n";
var_dump(ob_get_clean());
?>
--EXPECT--
string(4) "foo
"

11
tests/output/ob_008.phpt Normal file
View File

@ -0,0 +1,11 @@
--TEST--
output buffering - ob_get_contents
--FILE--
<?php
ob_start();
echo "foo\n";
echo ob_get_contents();
?>
--EXPECT--
foo
foo

12
tests/output/ob_009.phpt Normal file
View File

@ -0,0 +1,12 @@
--TEST--
output buffering - ob_get_flush
--FILE--
<?php
ob_start();
echo "foo\n";
var_dump(ob_get_flush());
?>
--EXPECT--
foo
string(4) "foo
"

13
tests/output/ob_010.phpt Normal file
View File

@ -0,0 +1,13 @@
--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

13
tests/output/ob_011.phpt Normal file
View File

@ -0,0 +1,13 @@
--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

22
tests/output/ob_012.phpt Normal file
View File

@ -0,0 +1,22 @@
--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

105
tests/output/ob_013.phpt Normal file
View File

@ -0,0 +1,105 @@
--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
)
)

14
tests/output/ob_014.phpt Normal file
View File

@ -0,0 +1,14 @@
--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

11
tests/output/ob_015.phpt Normal file
View File

@ -0,0 +1,11 @@
--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