1999-10-28 02:30:41 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2001-12-11 23:32:16 +08:00
| PHP Version 4 |
1999-10-28 02:30:41 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2002-12-31 23:59:15 +08:00
| Copyright ( c ) 1997 - 2003 The PHP Group |
1999-10-28 02:30:41 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2000-05-18 23:34:45 +08:00
| This source file is subject to version 2.02 of the PHP license , |
1999-10-28 02:30:41 +08:00
| that is bundled with this package in the file LICENSE , and is |
| available at through the world - wide - web at |
2000-05-18 23:34:45 +08:00
| http : //www.php.net/license/2_02.txt. |
1999-10-28 02:30:41 +08:00
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2000-06-07 02:54:00 +08:00
| Authors : Zeev Suraski < zeev @ zend . com > |
2000-10-29 17:14:55 +08:00
| Thies C . Arntzen < thies @ thieso . net > |
2002-08-10 06:29:58 +08:00
| Marcus Boerger < helly @ php . net > |
1999-10-28 02:30:41 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
2000-07-24 09:40:02 +08:00
/* $Id$ */
1999-10-28 02:30:41 +08:00
# include "php.h"
# include "ext/standard/head.h"
2001-07-20 22:40:30 +08:00
# include "ext/standard/basic_functions.h"
2002-05-03 16:00:41 +08:00
# include "ext/standard/url_scanner_ex.h"
2003-02-10 03:09:52 +08:00
# if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB)
2002-12-31 03:39:31 +08:00
# include "ext/zlib/php_zlib.h"
# endif
1999-10-28 02:30:41 +08:00
# include "SAPI.h"
2002-08-11 00:12:36 +08:00
# define OB_DEFAULT_HANDLER_NAME "default output handler"
1999-10-28 02:30:41 +08:00
/* output functions */
2001-08-05 23:29:47 +08:00
static int php_ub_body_write ( const char * str , uint str_length TSRMLS_DC ) ;
static int php_ub_body_write_no_header ( const char * str , uint str_length TSRMLS_DC ) ;
static int php_b_body_write ( const char * str , uint str_length TSRMLS_DC ) ;
1999-10-28 02:30:41 +08:00
2002-08-10 06:29:58 +08:00
static int php_ob_init ( uint initial_size , uint block_size , zval * output_handler , uint chunk_size , zend_bool erase TSRMLS_DC ) ;
2001-08-05 23:29:47 +08:00
static void php_ob_append ( const char * text , uint text_length TSRMLS_DC ) ;
1999-12-05 22:16:37 +08:00
#if 0
1999-10-28 02:30:41 +08:00
static void php_ob_prepend ( const char * text , uint text_length ) ;
1999-12-05 22:16:37 +08:00
# endif
1999-10-28 02:30:41 +08:00
# ifdef ZTS
int output_globals_id ;
# else
php_output_globals output_globals ;
# endif
2002-10-03 12:17:41 +08:00
/* {{{ php_default_output_func */
2002-10-03 10:55:19 +08:00
static inline int php_default_output_func ( const char * str , uint str_len TSRMLS_DC )
2001-05-08 06:00:13 +08:00
{
fwrite ( str , 1 , str_len , stderr ) ;
2001-05-30 04:32:57 +08:00
return str_len ;
2001-05-08 06:00:13 +08:00
}
2002-10-03 12:17:41 +08:00
/* }}} */
2001-05-08 06:00:13 +08:00
2002-10-03 12:17:41 +08:00
/* {{{ php_output_init_globals */
2001-07-28 19:36:37 +08:00
static void php_output_init_globals ( php_output_globals * output_globals_p TSRMLS_DC )
1999-10-28 02:30:41 +08:00
{
2001-05-08 06:00:13 +08:00
OG ( php_body_write ) = php_default_output_func ;
OG ( php_header_write ) = php_default_output_func ;
2000-01-14 01:37:25 +08:00
OG ( implicit_flush ) = 0 ;
2000-02-04 22:54:30 +08:00
OG ( output_start_filename ) = NULL ;
OG ( output_start_lineno ) = 0 ;
1999-10-28 02:30:41 +08:00
}
2002-10-03 12:17:41 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2002-10-03 12:17:41 +08:00
/* {{{ php_output_startup
Start output layer */
2001-07-03 02:17:10 +08:00
PHPAPI void php_output_startup ( void )
1999-10-28 02:30:41 +08:00
{
# ifdef ZTS
2001-07-27 18:16:41 +08:00
ts_allocate_id ( & output_globals_id , sizeof ( php_output_globals ) , ( ts_allocate_ctor ) php_output_init_globals , NULL ) ;
1999-11-27 02:34:27 +08:00
# else
2001-07-28 19:36:37 +08:00
php_output_init_globals ( & output_globals TSRMLS_CC ) ;
1999-10-28 02:30:41 +08:00
# endif
2001-07-03 02:17:10 +08:00
}
2002-10-03 12:17:41 +08:00
/* }}} */
2001-07-03 02:17:10 +08:00
1999-10-28 02:30:41 +08:00
2002-10-03 12:17:41 +08:00
/* {{{ php_output_activate
Initilize output global for activation */
2001-08-05 23:29:47 +08:00
PHPAPI void php_output_activate ( TSRMLS_D )
2001-07-03 02:17:10 +08:00
{
OG ( php_body_write ) = php_ub_body_write ;
OG ( php_header_write ) = sapi_module . ub_write ;
2001-07-20 21:59:00 +08:00
OG ( ob_nesting_level ) = 0 ;
OG ( ob_lock ) = 0 ;
OG ( disable_output ) = 0 ;
2002-04-25 00:53:07 +08:00
OG ( output_start_filename ) = NULL ;
OG ( output_start_lineno ) = 0 ;
2001-07-20 21:59:00 +08:00
}
2002-10-03 12:17:41 +08:00
/* }}} */
2001-07-20 21:59:00 +08:00
2002-10-03 12:17:41 +08:00
/* {{{ php_output_set_status
2002-10-06 20:02:53 +08:00
Toggle output status . Do NOT use in application code , only in SAPIs where appropriate . */
2001-08-05 23:29:47 +08:00
PHPAPI void php_output_set_status ( zend_bool status TSRMLS_DC )
2001-07-20 21:59:00 +08:00
{
OG ( disable_output ) = ! status ;
2001-03-04 09:45:19 +08:00
}
2002-10-03 12:17:41 +08:00
/* }}} */
2001-03-04 09:45:19 +08:00
2002-10-03 12:17:41 +08:00
/* {{{ php_output_register_constants */
2001-08-05 23:29:47 +08:00
void php_output_register_constants ( TSRMLS_D )
2001-03-04 09:45:19 +08:00
{
2001-03-04 09:09:36 +08:00
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 ) ;
1999-10-28 02:30:41 +08:00
}
2002-10-03 12:17:41 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2001-03-04 09:45:19 +08:00
2002-10-03 12:17:41 +08:00
/* {{{ php_body_wirte
* Write body part */
2001-08-05 23:55:43 +08:00
PHPAPI int php_body_write ( const char * str , uint str_length TSRMLS_DC )
1999-10-28 02:30:41 +08:00
{
2001-08-05 23:29:47 +08:00
return OG ( php_body_write ) ( str , str_length TSRMLS_CC ) ;
1999-10-28 02:30:41 +08:00
}
2002-10-03 12:17:41 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2002-10-03 12:17:41 +08:00
/* {{{ php_header_wirte
* Write HTTP header */
2001-08-05 23:55:43 +08:00
PHPAPI int php_header_write ( const char * str , uint str_length TSRMLS_DC )
1999-10-28 02:30:41 +08:00
{
2001-07-20 21:59:00 +08:00
if ( OG ( disable_output ) ) {
return 0 ;
} else {
2001-08-05 23:29:47 +08:00
return OG ( php_header_write ) ( str , str_length TSRMLS_CC ) ;
2001-07-20 21:59:00 +08:00
}
1999-10-28 02:30:41 +08:00
}
2002-10-03 12:17:41 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2001-06-06 21:06:12 +08:00
/* {{{ php_start_ob_buffer
* Start output buffering */
2002-03-01 11:05:50 +08:00
PHPAPI int php_start_ob_buffer ( zval * output_handler , uint chunk_size , zend_bool erase TSRMLS_DC )
1999-10-28 02:30:41 +08:00
{
2002-09-01 19:33:19 +08:00
uint initial_size , block_size ;
2002-08-10 06:29:58 +08:00
2001-07-20 21:59:00 +08:00
if ( OG ( ob_lock ) ) {
2002-09-23 22:18:42 +08:00
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 ;
2002-08-20 02:47:23 +08:00
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_ERROR , " Cannot use output buffering in output buffering display handlers " ) ;
2000-09-03 02:03:58 +08:00
return FAILURE ;
}
2002-09-01 19:33:19 +08:00
if ( chunk_size ) {
2002-10-07 19:21:06 +08:00
if ( chunk_size = = 1 ) {
2002-10-02 23:02:16 +08:00
chunk_size = 4096 ;
2002-10-07 19:21:06 +08:00
}
2002-09-01 19:33:19 +08:00
initial_size = ( chunk_size * 3 / 2 ) ;
block_size = chunk_size / 2 ;
} else {
initial_size = 40 * 1024 ;
2002-08-21 11:04:17 +08:00
block_size = 10 * 1024 ;
2002-09-01 19:33:19 +08:00
}
2002-08-21 11:04:17 +08:00
return php_ob_init ( initial_size , block_size , output_handler , chunk_size , erase TSRMLS_CC ) ;
}
/* }}} */
2002-08-10 06:29:58 +08:00
/* {{{ php_start_ob_buffer_named
* Start output buffering */
PHPAPI int php_start_ob_buffer_named ( const char * output_handler_name , uint chunk_size , zend_bool erase TSRMLS_DC )
{
zval * output_handler ;
int result ;
ALLOC_INIT_ZVAL ( output_handler ) ;
Z_STRLEN_P ( output_handler ) = strlen ( output_handler_name ) ; /* this can be optimized */
Z_STRVAL_P ( output_handler ) = estrndup ( output_handler_name , Z_STRLEN_P ( output_handler ) ) ;
Z_TYPE_P ( output_handler ) = IS_STRING ;
result = php_start_ob_buffer ( output_handler , chunk_size , erase TSRMLS_CC ) ;
zval_dtor ( output_handler ) ;
FREE_ZVAL ( output_handler ) ;
return result ;
1999-10-28 02:30:41 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2001-06-06 21:06:12 +08:00
/* {{{ php_end_ob_buffer
* End output buffering ( one level ) */
2001-08-05 23:29:47 +08:00
PHPAPI void php_end_ob_buffer ( zend_bool send_buffer , zend_bool just_flush TSRMLS_DC )
1999-10-28 02:30:41 +08:00
{
2000-09-03 02:03:58 +08:00
char * final_buffer = NULL ;
2002-03-04 18:58:00 +08:00
unsigned int final_buffer_length = 0 ;
2000-09-03 02:03:58 +08:00
zval * alternate_buffer = NULL ;
2002-05-08 19:44:14 +08:00
char * to_be_destroyed_buffer , * to_be_destroyed_handler_name ;
2001-03-07 03:38:33 +08:00
char * to_be_destroyed_handled_output [ 2 ] = { 0 , 0 } ;
2001-03-06 23:54:49 +08:00
int status ;
2001-08-31 23:56:48 +08:00
php_ob_buffer * prev_ob_buffer_p = NULL ;
php_ob_buffer orig_ob_buffer ;
1999-10-28 02:30:41 +08:00
2001-07-20 21:59:00 +08:00
if ( OG ( ob_nesting_level ) = = 0 ) {
1999-10-28 02:30:41 +08:00
return ;
}
2001-03-06 23:54:49 +08:00
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 ;
}
2000-09-03 02:03:58 +08:00
2002-05-02 21:55:05 +08:00
#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 ) ;
fclose ( fp ) ;
}
# endif
2001-03-06 23:54:49 +08:00
if ( OG ( active_ob_buffer ) . internal_output_handler ) {
2001-03-07 00:28:51 +08:00
final_buffer = OG ( active_ob_buffer ) . internal_output_handler_buffer ;
final_buffer_length = OG ( active_ob_buffer ) . internal_output_handler_buffer_size ;
2001-08-05 23:29:47 +08:00
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 ) ;
2001-03-06 23:54:49 +08:00
} else if ( OG ( active_ob_buffer ) . output_handler ) {
2001-03-04 09:09:36 +08:00
zval * * params [ 2 ] ;
2000-09-03 02:03:58 +08:00
zval * orig_buffer ;
2001-03-04 09:09:36 +08:00
zval * z_status ;
2000-09-03 02:03:58 +08:00
ALLOC_INIT_ZVAL ( orig_buffer ) ;
2002-05-04 11:02:51 +08:00
ZVAL_STRINGL ( orig_buffer , OG ( active_ob_buffer ) . buffer , OG ( active_ob_buffer ) . text_length , 1 ) ;
2000-09-03 02:03:58 +08:00
orig_buffer - > refcount = 2 ; /* don't let call_user_function() destroy our buffer */
2001-03-17 11:03:50 +08:00
orig_buffer - > is_ref = 1 ;
2000-09-03 02:03:58 +08:00
2001-03-04 09:09:36 +08:00
ALLOC_INIT_ZVAL ( z_status ) ;
2001-08-05 09:43:02 +08:00
ZVAL_LONG ( z_status , status ) ;
2001-03-04 09:09:36 +08:00
2000-09-03 02:03:58 +08:00
params [ 0 ] = & orig_buffer ;
2001-03-04 09:09:36 +08:00
params [ 1 ] = & z_status ;
2001-07-20 21:59:00 +08:00
OG ( ob_lock ) = 1 ;
2001-07-30 16:24:42 +08:00
if ( call_user_function_ex ( CG ( function_table ) , NULL , OG ( active_ob_buffer ) . output_handler , & alternate_buffer , 2 , params , 1 , NULL TSRMLS_CC ) = = SUCCESS ) {
2002-08-23 16:37:35 +08:00
if ( ! ( 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 ) ;
}
2000-09-03 02:03:58 +08:00
}
2001-07-20 21:59:00 +08:00
OG ( ob_lock ) = 0 ;
2000-09-03 02:03:58 +08:00
zval_ptr_dtor ( & OG ( active_ob_buffer ) . output_handler ) ;
2002-05-04 11:02:51 +08:00
orig_buffer - > refcount - = 2 ;
if ( orig_buffer - > refcount < = 0 ) { /* free the zval */
zval_dtor ( orig_buffer ) ;
2000-09-03 02:03:58 +08:00
FREE_ZVAL ( orig_buffer ) ;
}
2001-03-04 09:09:36 +08:00
zval_ptr_dtor ( & z_status ) ;
2000-09-03 02:03:58 +08:00
}
if ( ! final_buffer ) {
final_buffer = OG ( active_ob_buffer ) . buffer ;
final_buffer_length = OG ( active_ob_buffer ) . text_length ;
}
2000-11-03 00:46:30 +08:00
2001-07-20 21:59:00 +08:00
if ( OG ( ob_nesting_level ) = = 1 ) { /* end buffering */
2000-07-29 22:46:09 +08:00
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 ;
}
2000-09-03 02:03:58 +08:00
}
2000-11-03 00:46:30 +08:00
to_be_destroyed_buffer = OG ( active_ob_buffer ) . buffer ;
2002-05-08 19:44:14 +08:00
to_be_destroyed_handler_name = OG ( active_ob_buffer ) . handler_name ;
2001-03-07 03:38:33 +08:00
if ( OG ( active_ob_buffer ) . internal_output_handler
2001-08-31 23:16:15 +08:00
& & ( final_buffer ! = OG ( active_ob_buffer ) . internal_output_handler_buffer )
& & ( final_buffer ! = OG ( active_ob_buffer ) . buffer ) ) {
2001-03-07 03:38:33 +08:00
to_be_destroyed_handled_output [ 0 ] = final_buffer ;
}
2000-11-03 00:46:30 +08:00
2001-03-04 09:09:36 +08:00
if ( ! just_flush ) {
2001-03-07 03:38:33 +08:00
if ( OG ( active_ob_buffer ) . internal_output_handler ) {
to_be_destroyed_handled_output [ 1 ] = OG ( active_ob_buffer ) . internal_output_handler_buffer ;
}
2001-08-31 23:56:48 +08:00
}
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 ) ) ;
2000-11-03 00:46:30 +08:00
}
2001-03-04 09:09:36 +08:00
}
2001-08-31 23:56:48 +08:00
OG ( ob_nesting_level ) - - ;
2000-11-03 00:46:30 +08:00
2000-09-03 02:03:58 +08:00
if ( send_buffer ) {
2001-08-05 23:29:47 +08:00
OG ( php_body_write ) ( final_buffer , final_buffer_length TSRMLS_CC ) ;
2000-09-03 02:03:58 +08:00
}
2000-11-03 00:46:30 +08:00
2001-08-31 23:56:48 +08:00
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 ) + + ;
}
2000-09-03 02:03:58 +08:00
if ( alternate_buffer ) {
zval_ptr_dtor ( & alternate_buffer ) ;
1999-10-28 02:30:41 +08:00
}
2000-11-03 00:46:30 +08:00
2002-05-04 18:55:08 +08:00
if ( status & PHP_OUTPUT_HANDLER_END ) {
2002-05-08 19:44:14 +08:00
efree ( to_be_destroyed_handler_name ) ;
2002-05-04 18:55:08 +08:00
}
if ( ! just_flush ) {
2001-03-04 09:09:36 +08:00
efree ( to_be_destroyed_buffer ) ;
} 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 ;
2001-03-07 03:38:33 +08:00
}
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 ] ) ;
2001-03-04 09:09:36 +08:00
}
1999-10-28 02:30:41 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2001-06-06 21:06:12 +08:00
/* {{{ php_end_ob_buffers
* End output buffering ( all buffers ) */
2001-08-05 23:29:47 +08:00
PHPAPI void php_end_ob_buffers ( zend_bool send_buffer TSRMLS_DC )
2000-07-29 22:46:09 +08:00
{
2001-07-20 21:59:00 +08:00
while ( OG ( ob_nesting_level ) ! = 0 ) {
2001-08-05 23:29:47 +08:00
php_end_ob_buffer ( send_buffer , 0 TSRMLS_CC ) ;
2000-07-29 22:46:09 +08:00
}
}
2001-06-06 21:06:12 +08:00
/* }}} */
2000-07-29 22:46:09 +08:00
2001-06-06 21:06:12 +08:00
/* {{{ php_start_implicit_flush
*/
2001-08-05 23:29:47 +08:00
PHPAPI void php_start_implicit_flush ( TSRMLS_D )
2000-01-14 01:37:25 +08:00
{
2000-01-14 01:54:51 +08:00
OG ( implicit_flush ) = 1 ;
2000-01-14 01:37:25 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
2000-01-14 01:37:25 +08:00
2001-06-06 21:06:12 +08:00
/* {{{ php_end_implicit_flush
*/
2001-08-05 23:29:47 +08:00
PHPAPI void php_end_implicit_flush ( TSRMLS_D )
2000-01-14 01:37:25 +08:00
{
2000-01-14 01:54:51 +08:00
OG ( implicit_flush ) = 0 ;
2000-01-14 01:37:25 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
2000-01-14 01:37:25 +08:00
2001-06-06 21:06:12 +08:00
/* {{{ php_ob_set_internal_handler
*/
2002-03-01 11:05:50 +08:00
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 )
2001-03-06 23:54:49 +08:00
{
2002-08-11 00:12:36 +08:00
if ( OG ( ob_nesting_level ) = = 0 | | OG ( active_ob_buffer ) . internal_output_handler | | strcmp ( OG ( active_ob_buffer ) . handler_name , OB_DEFAULT_HANDLER_NAME ) ) {
php_start_ob_buffer ( NULL , buffer_size , erase TSRMLS_CC ) ;
2001-03-06 23:54:49 +08:00
}
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 ;
2002-10-07 19:21:06 +08:00
if ( OG ( active_ob_buffer ) . handler_name ) {
2002-05-05 03:06:46 +08:00
efree ( OG ( active_ob_buffer ) . handler_name ) ;
2002-10-07 19:21:06 +08:00
}
2002-05-08 19:44:14 +08:00
OG ( active_ob_buffer ) . handler_name = estrdup ( handler_name ) ;
2002-05-05 03:06:46 +08:00
OG ( active_ob_buffer ) . erase = erase ;
2001-03-06 23:54:49 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
2001-03-06 23:54:49 +08:00
1999-10-28 02:30:41 +08:00
/*
* Output buffering - implementation
*/
2001-06-06 21:06:12 +08:00
/* {{{ php_ob_allocate
*/
2001-08-05 23:29:47 +08:00
static inline void php_ob_allocate ( TSRMLS_D )
1999-10-28 02:30:41 +08:00
{
2000-07-29 22:46:09 +08:00
if ( OG ( active_ob_buffer ) . size < OG ( active_ob_buffer ) . text_length ) {
while ( OG ( active_ob_buffer ) . size < = OG ( active_ob_buffer ) . text_length ) {
OG ( active_ob_buffer ) . size + = OG ( active_ob_buffer ) . block_size ;
}
1999-10-28 02:30:41 +08:00
2000-07-29 22:46:09 +08:00
OG ( active_ob_buffer ) . buffer = ( char * ) erealloc ( OG ( active_ob_buffer ) . buffer , OG ( active_ob_buffer ) . size + 1 ) ;
1999-10-28 02:30:41 +08:00
}
}
2001-06-06 21:06:12 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2002-08-10 06:29:58 +08:00
/* {{{ php_ob_init_conflict
* Returns 1 if handler_set is already used and generates error message
2001-06-06 21:06:12 +08:00
*/
2002-10-03 11:58:12 +08:00
PHPAPI int php_ob_init_conflict ( char * handler_new , char * handler_set TSRMLS_DC )
1999-10-28 02:30:41 +08:00
{
2002-10-07 19:21:06 +08:00
if ( php_ob_handler_used ( handler_set TSRMLS_CC ) ) {
2002-08-20 02:47:23 +08:00
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_WARNING , " output handler '%s' conflicts with '%s' " , handler_new , handler_set ) ;
2002-08-10 06:29:58 +08:00
return 1 ;
}
return 0 ;
}
/* }}} */
/* {{{ php_ob_init_named
*/
static int php_ob_init_named ( uint initial_size , uint block_size , char * handler_name , zval * output_handler , uint chunk_size , zend_bool erase TSRMLS_DC )
{
2001-07-20 21:59:00 +08:00
if ( OG ( ob_nesting_level ) > 0 ) {
2003-02-10 03:09:52 +08:00
# if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB)
2002-12-31 08:04:52 +08:00
if ( ! strncmp ( handler_name , " ob_gzhandler " , sizeof ( " ob_gzhandler " ) ) & & php_ob_gzhandler_check ( TSRMLS_C ) ) {
2002-12-31 03:39:31 +08:00
return FAILURE ;
}
# endif
2001-07-20 21:59:00 +08:00
if ( OG ( ob_nesting_level ) = = 1 ) { /* initialize stack */
2000-07-29 22:46:09 +08:00
zend_stack_init ( & OG ( ob_buffers ) ) ;
}
zend_stack_push ( & OG ( ob_buffers ) , & OG ( active_ob_buffer ) , sizeof ( php_ob_buffer ) ) ;
1999-10-28 02:30:41 +08:00
}
2001-07-20 21:59:00 +08:00
OG ( ob_nesting_level ) + + ;
2000-07-29 22:46:09 +08:00
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 ;
2000-09-03 02:03:58 +08:00
OG ( active_ob_buffer ) . output_handler = output_handler ;
2000-11-24 02:43:18 +08:00
OG ( active_ob_buffer ) . chunk_size = chunk_size ;
2001-03-04 09:09:36 +08:00
OG ( active_ob_buffer ) . status = 0 ;
2001-03-06 23:54:49 +08:00
OG ( active_ob_buffer ) . internal_output_handler = NULL ;
2002-08-11 00:12:36 +08:00
OG ( active_ob_buffer ) . handler_name = estrdup ( handler_name & & handler_name [ 0 ] ? handler_name : OB_DEFAULT_HANDLER_NAME ) ;
2002-12-31 03:39:31 +08:00
OG ( active_ob_buffer ) . erase = erase ;
2002-08-10 06:29:58 +08:00
OG ( php_body_write ) = php_b_body_write ;
return SUCCESS ;
}
/* }}} */
/* {{{ php_ob_handler_from_string
* Create zval output handler from string
*/
static zval * php_ob_handler_from_string ( const char * handler_name TSRMLS_DC )
{
zval * output_handler ;
ALLOC_INIT_ZVAL ( output_handler ) ;
Z_STRLEN_P ( output_handler ) = strlen ( handler_name ) ; /* this can be optimized */
Z_STRVAL_P ( output_handler ) = estrndup ( handler_name , Z_STRLEN_P ( output_handler ) ) ;
Z_TYPE_P ( output_handler ) = IS_STRING ;
return output_handler ;
}
/* }}} */
/* {{{ php_ob_init
*/
static int php_ob_init ( uint initial_size , uint block_size , zval * output_handler , uint chunk_size , zend_bool erase TSRMLS_DC )
{
2002-12-31 03:39:31 +08:00
int result , len ;
2002-08-10 06:29:58 +08:00
char * handler_name , * next_handler_name ;
HashPosition pos ;
zval * * tmp ;
zval * handler_zval ;
2002-03-01 11:05:50 +08:00
if ( output_handler & & output_handler - > type = = IS_STRING ) {
2002-08-10 06:29:58 +08:00
handler_name = Z_STRVAL_P ( output_handler ) ;
while ( ( next_handler_name = strchr ( handler_name , ' , ' ) ) ! = NULL ) {
len = next_handler_name - handler_name ;
next_handler_name = estrndup ( handler_name , len ) ;
handler_zval = php_ob_handler_from_string ( next_handler_name TSRMLS_CC ) ;
2002-12-31 03:39:31 +08:00
result = php_ob_init_named ( initial_size , block_size , next_handler_name , handler_zval , chunk_size , erase TSRMLS_CC ) ;
if ( result ! = SUCCESS ) {
2002-08-10 06:29:58 +08:00
zval_dtor ( handler_zval ) ;
FREE_ZVAL ( handler_zval ) ;
}
handler_name + = len + 1 ;
efree ( next_handler_name ) ;
}
handler_zval = php_ob_handler_from_string ( handler_name TSRMLS_CC ) ;
2002-12-31 03:39:31 +08:00
result = php_ob_init_named ( initial_size , block_size , handler_name , handler_zval , chunk_size , erase TSRMLS_CC ) ;
if ( result ! = SUCCESS ) {
2002-08-10 06:29:58 +08:00
zval_dtor ( handler_zval ) ;
FREE_ZVAL ( handler_zval ) ;
}
2002-10-07 19:21:06 +08:00
} else if ( output_handler & & output_handler - > type = = IS_ARRAY ) {
2002-08-25 19:50:25 +08:00
/* do we have array(object,method) */
2002-08-25 20:16:48 +08:00
if ( zend_is_callable ( output_handler , 1 , & handler_name ) ) {
2002-08-25 19:50:25 +08:00
SEPARATE_ZVAL ( & output_handler ) ;
output_handler - > refcount + + ;
result = php_ob_init_named ( initial_size , block_size , handler_name , output_handler , chunk_size , erase TSRMLS_CC ) ;
efree ( handler_name ) ;
} else {
2002-08-25 20:16:48 +08:00
/* init all array elements recursively */
2002-08-25 19:50:25 +08:00
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 ) {
2002-12-31 03:39:31 +08:00
result = php_ob_init ( initial_size , block_size , * tmp , chunk_size , erase TSRMLS_CC ) ;
2002-08-25 19:50:25 +08:00
zend_hash_move_forward_ex ( Z_ARRVAL_P ( output_handler ) , & pos ) ;
}
2002-08-10 06:29:58 +08:00
}
2002-10-07 19:21:06 +08:00
} else if ( output_handler & & output_handler - > type = = IS_OBJECT ) {
2002-08-25 22:20:37 +08:00
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 %s to use as output handler " , Z_OBJCE_P ( output_handler ) - > name ) ;
result = FAILURE ;
2002-10-07 19:21:06 +08:00
} else {
2002-08-10 06:29:58 +08:00
if ( output_handler ) {
SEPARATE_ZVAL ( & output_handler ) ;
output_handler - > refcount + + ;
}
2002-08-11 00:12:36 +08:00
result = php_ob_init_named ( initial_size , block_size , OB_DEFAULT_HANDLER_NAME , output_handler , chunk_size , erase TSRMLS_CC ) ;
2002-03-01 11:05:50 +08:00
}
2002-08-10 06:29:58 +08:00
return result ;
1999-10-28 02:30:41 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2002-08-05 11:09:42 +08:00
/* {{{ php_ob_list_each
*/
static int php_ob_list_each ( php_ob_buffer * ob_buffer , zval * ob_handler_array )
{
2002-08-10 06:29:58 +08:00
add_next_index_string ( ob_handler_array , ob_buffer - > handler_name , 1 ) ;
2002-08-05 11:09:42 +08:00
return 0 ;
}
/* }}} */
2002-08-11 00:12:36 +08:00
/* {{{ proto false|array ob_list_handlers()
2002-08-10 06:29:58 +08:00
* List all output_buffers in an array
*/
2002-08-05 11:09:42 +08:00
PHP_FUNCTION ( ob_list_handlers )
{
if ( ZEND_NUM_ARGS ( ) ! = 0 ) {
2002-10-07 19:21:06 +08:00
ZEND_WRONG_PARAM_COUNT ( ) ;
2002-08-11 00:12:36 +08:00
RETURN_FALSE ;
2002-08-05 11:09:42 +08:00
}
2003-01-28 01:22:22 +08:00
array_init ( return_value ) ;
2002-08-05 11:09:42 +08:00
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 ) ;
}
}
/* }}} */
2002-08-06 02:54:53 +08:00
/* {{{ php_ob_used_each
2002-08-10 06:29:58 +08:00
* Sets handler_name to NULL is found
2002-08-06 02:54:53 +08:00
*/
static int php_ob_handler_used_each ( php_ob_buffer * ob_buffer , char * * handler_name )
{
2002-10-07 19:21:06 +08:00
if ( ! strcmp ( ob_buffer - > handler_name , * handler_name ) ) {
2002-08-06 02:54:53 +08:00
* handler_name = NULL ;
return 1 ;
}
return 0 ;
}
/* }}} */
/* {{{ php_ob_used
2002-08-10 06:29:58 +08:00
* returns 1 if given handler_name is used as output_handler
2002-08-06 02:54:53 +08:00
*/
PHPAPI int php_ob_handler_used ( char * handler_name TSRMLS_DC )
{
char * tmp = handler_name ;
if ( OG ( ob_nesting_level ) ) {
if ( ! strcmp ( OG ( active_ob_buffer ) . handler_name , 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 ) ;
}
}
return tmp ? 0 : 1 ;
}
/* }}} */
2001-06-06 21:06:12 +08:00
/* {{{ php_ob_append
*/
2002-10-03 10:55:19 +08:00
static inline void php_ob_append ( const char * text , uint text_length TSRMLS_DC )
1999-10-28 02:30:41 +08:00
{
char * target ;
int original_ob_text_length ;
2000-07-29 22:46:09 +08:00
original_ob_text_length = OG ( active_ob_buffer ) . text_length ;
2001-02-27 08:09:14 +08:00
OG ( active_ob_buffer ) . text_length = OG ( active_ob_buffer ) . text_length + text_length ;
1999-10-28 02:30:41 +08:00
2001-08-05 23:29:47 +08:00
php_ob_allocate ( TSRMLS_C ) ;
2001-02-27 08:09:14 +08:00
target = OG ( active_ob_buffer ) . buffer + original_ob_text_length ;
memcpy ( target , text , text_length ) ;
target [ text_length ] = 0 ;
2000-11-24 02:43:18 +08:00
2002-10-05 01:11:35 +08:00
/* If implicit_flush is On or chunked buffering, send contents to next buffer and return. */
2002-10-06 20:02:53 +08:00
if ( OG ( active_ob_buffer ) . chunk_size
& & OG ( active_ob_buffer ) . text_length > = OG ( active_ob_buffer ) . chunk_size ) {
2000-11-24 02:43:18 +08:00
zval * output_handler = OG ( active_ob_buffer ) . output_handler ;
2002-10-03 21:32:01 +08:00
2000-11-24 02:43:18 +08:00
if ( output_handler ) {
output_handler - > refcount + + ;
}
2001-08-05 23:29:47 +08:00
php_end_ob_buffer ( 1 , 1 TSRMLS_CC ) ;
2000-11-24 02:43:18 +08:00
return ;
}
1999-10-28 02:30:41 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
1999-12-05 22:16:37 +08:00
#if 0
2002-10-03 10:55:19 +08:00
static inline void php_ob_prepend ( const char * text , uint text_length )
1999-10-28 02:30:41 +08:00
{
char * p , * start ;
2001-07-28 19:36:37 +08:00
TSRMLS_FETCH ( ) ;
1999-10-28 02:30:41 +08:00
2000-07-29 22:46:09 +08:00
OG ( active_ob_buffer ) . text_length + = text_length ;
2001-08-05 23:29:47 +08:00
php_ob_allocate ( TSRMLS_C ) ;
1999-10-28 02:30:41 +08:00
1999-11-24 06:10:44 +08:00
/* 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 ) ;
1999-10-28 02:30:41 +08:00
while ( - - p > = start ) {
p [ text_length ] = * p ;
}
1999-11-24 06:10:44 +08:00
memcpy ( OG ( ob_buffer ) , text , text_length ) ;
2000-07-29 22:46:09 +08:00
OG ( ob_buffer ) [ OG ( active_ob_buffer ) . text_length ] = 0 ;
1999-10-28 02:30:41 +08:00
}
1999-12-05 22:16:37 +08:00
# endif
1999-10-28 02:30:41 +08:00
2001-06-06 21:06:12 +08:00
/* {{{ php_ob_get_buffer
* Return the current output buffer */
2002-10-03 11:58:12 +08:00
PHPAPI int php_ob_get_buffer ( zval * p TSRMLS_DC )
1999-10-28 02:30:41 +08:00
{
2001-07-20 21:59:00 +08:00
if ( OG ( ob_nesting_level ) = = 0 ) {
1999-10-28 02:30:41 +08:00
return FAILURE ;
}
2001-08-05 09:43:02 +08:00
ZVAL_STRINGL ( p , OG ( active_ob_buffer ) . buffer , OG ( active_ob_buffer ) . text_length , 1 ) ;
1999-10-28 02:30:41 +08:00
return SUCCESS ;
}
2001-06-06 21:06:12 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2001-06-06 21:06:12 +08:00
/* {{{ php_ob_get_length
* Return the size of the current output buffer */
2002-10-03 11:58:12 +08:00
PHPAPI int php_ob_get_length ( zval * p TSRMLS_DC )
2000-08-25 11:10:42 +08:00
{
2001-07-20 21:59:00 +08:00
if ( OG ( ob_nesting_level ) = = 0 ) {
2000-08-25 11:10:42 +08:00
return FAILURE ;
}
2001-08-05 09:43:02 +08:00
ZVAL_LONG ( p , OG ( active_ob_buffer ) . text_length ) ;
2000-08-25 11:10:42 +08:00
return SUCCESS ;
}
2001-06-06 21:06:12 +08:00
/* }}} */
2000-08-25 11:10:42 +08:00
1999-10-28 02:30:41 +08:00
/*
* Wrapper functions - implementation
*/
/* buffered output function */
2001-08-05 23:29:47 +08:00
static int php_b_body_write ( const char * str , uint str_length TSRMLS_DC )
1999-10-28 02:30:41 +08:00
{
2001-08-05 23:29:47 +08:00
php_ob_append ( str , str_length TSRMLS_CC ) ;
1999-10-28 02:30:41 +08:00
return str_length ;
}
2001-06-06 21:06:12 +08:00
/* {{{ php_ub_body_write_no_header
*/
2001-08-05 23:29:47 +08:00
static int php_ub_body_write_no_header ( const char * str , uint str_length TSRMLS_DC )
1999-10-28 02:30:41 +08:00
{
int result ;
2001-07-20 21:59:00 +08:00
if ( OG ( disable_output ) ) {
return 0 ;
2001-08-25 23:57:42 +08:00
}
1999-10-28 02:30:41 +08:00
2001-08-05 23:29:47 +08:00
result = OG ( php_header_write ) ( str , str_length TSRMLS_CC ) ;
1999-10-28 02:30:41 +08:00
2000-01-14 01:54:51 +08:00
if ( OG ( implicit_flush ) ) {
2001-07-31 14:28:05 +08:00
sapi_flush ( TSRMLS_C ) ;
2000-01-14 01:54:51 +08:00
}
2000-01-14 01:37:25 +08:00
1999-10-28 02:30:41 +08:00
return result ;
}
2001-06-06 21:06:12 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2001-06-06 21:06:12 +08:00
/* {{{ php_ub_body_write
*/
2001-08-05 23:29:47 +08:00
static int php_ub_body_write ( const char * str , uint str_length TSRMLS_DC )
1999-10-28 02:30:41 +08:00
{
int result = 0 ;
if ( SG ( request_info ) . headers_only ) {
2003-03-25 16:07:13 +08:00
php_header ( TSRMLS_C ) ;
1999-10-28 02:30:41 +08:00
zend_bailout ( ) ;
}
2003-03-25 16:07:13 +08:00
if ( php_header ( TSRMLS_C ) ) {
2001-07-30 16:24:42 +08:00
if ( zend_is_compiling ( TSRMLS_C ) ) {
2001-07-28 19:36:37 +08:00
OG ( output_start_filename ) = zend_get_compiled_filename ( TSRMLS_C ) ;
OG ( output_start_lineno ) = zend_get_compiled_lineno ( TSRMLS_C ) ;
2001-07-30 16:24:42 +08:00
} else if ( zend_is_executing ( TSRMLS_C ) ) {
2001-07-27 18:16:41 +08:00
OG ( output_start_filename ) = zend_get_executed_filename ( TSRMLS_C ) ;
OG ( output_start_lineno ) = zend_get_executed_lineno ( TSRMLS_C ) ;
2000-02-04 22:54:30 +08:00
}
1999-11-24 06:10:44 +08:00
OG ( php_body_write ) = php_ub_body_write_no_header ;
2001-08-05 23:29:47 +08:00
result = php_ub_body_write_no_header ( str , str_length TSRMLS_CC ) ;
1999-10-28 02:30:41 +08:00
}
return result ;
}
2001-06-06 21:06:12 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
/*
* HEAD support
*/
2002-08-13 12:37:28 +08:00
/* {{{ proto bool ob_start([ string|array user_function [, int chunk_size [, bool erase]]])
2000-11-13 06:13:35 +08:00
Turn on Output Buffering ( specifying an optional output handler ) . */
1999-10-28 02:30:41 +08:00
PHP_FUNCTION ( ob_start )
{
2001-08-12 06:55:00 +08:00
zval * output_handler = NULL ;
2003-03-07 07:07:28 +08:00
long chunk_size = 0 ;
2002-03-01 11:05:50 +08:00
zend_bool erase = 1 ;
int argc = ZEND_NUM_ARGS ( ) ;
2002-10-07 19:21:06 +08:00
if ( zend_parse_parameters ( argc TSRMLS_CC , " |zlb " , & output_handler , & chunk_size , & erase ) = = FAILURE ) {
2002-08-10 06:29:58 +08:00
RETURN_FALSE ;
2002-10-07 19:21:06 +08:00
}
2000-09-03 02:03:58 +08:00
2002-09-01 19:33:19 +08:00
if ( php_start_ob_buffer ( output_handler , chunk_size , erase TSRMLS_CC ) = = FAILURE ) {
2000-09-03 02:03:58 +08:00
RETURN_FALSE ;
}
RETURN_TRUE ;
1999-10-28 02:30:41 +08:00
}
2000-04-19 03:18:47 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2002-03-01 11:05:50 +08:00
/* {{{ proto bool ob_flush(void)
2002-10-03 15:17:14 +08:00
Flush ( send ) contents of the output buffer . The last buffer content is sent to next buffer */
2001-11-30 18:48:38 +08:00
PHP_FUNCTION ( ob_flush )
{
2002-10-07 19:21:06 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 0 ) {
ZEND_WRONG_PARAM_COUNT ( ) ;
}
2002-03-01 11:05:50 +08:00
if ( ! OG ( ob_nesting_level ) ) {
2002-08-20 02:47:23 +08:00
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to flush buffer. No buffer to flush. " ) ;
2002-03-01 11:05:50 +08:00
RETURN_FALSE ;
}
2002-10-03 15:17:14 +08:00
2001-11-30 18:48:38 +08:00
php_end_ob_buffer ( 1 , 1 TSRMLS_CC ) ;
2002-03-01 11:05:50 +08:00
RETURN_TRUE ;
2001-11-30 18:48:38 +08:00
}
/* }}} */
2002-10-03 15:17:14 +08:00
2002-03-01 11:05:50 +08:00
/* {{{ proto bool ob_clean(void)
Clean ( delete ) the current output buffer */
2001-11-30 18:48:38 +08:00
PHP_FUNCTION ( ob_clean )
{
2002-10-07 19:21:06 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 0 ) {
ZEND_WRONG_PARAM_COUNT ( ) ;
}
2002-03-01 11:05:50 +08:00
if ( ! OG ( ob_nesting_level ) ) {
2002-08-20 02:47:23 +08:00
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to delete buffer. No buffer to delete. " ) ;
2002-03-01 11:05:50 +08:00
RETURN_FALSE ;
}
2002-10-07 19:21:06 +08:00
2002-08-20 02:47:23 +08:00
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 ) ;
2002-03-01 11:05:50 +08:00
RETURN_FALSE ;
}
2001-11-30 18:48:38 +08:00
php_end_ob_buffer ( 0 , 1 TSRMLS_CC ) ;
2002-03-01 11:05:50 +08:00
RETURN_TRUE ;
2001-11-30 18:48:38 +08:00
}
/* }}} */
2002-03-01 11:05:50 +08:00
/* {{{ proto bool ob_end_flush(void)
Flush ( send ) the output buffer , and delete current output buffer */
1999-10-28 02:30:41 +08:00
PHP_FUNCTION ( ob_end_flush )
{
2002-10-07 19:21:06 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 0 ) {
ZEND_WRONG_PARAM_COUNT ( ) ;
}
2002-03-01 11:05:50 +08:00
if ( ! OG ( ob_nesting_level ) ) {
2002-08-20 02:47:23 +08:00
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to delete and flush buffer. No buffer to delete or flush. " ) ;
2002-03-01 11:05:50 +08:00
RETURN_FALSE ;
}
if ( OG ( ob_nesting_level ) & & ! OG ( active_ob_buffer ) . status & & ! OG ( active_ob_buffer ) . erase ) {
2002-08-20 02:47:23 +08:00
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to delete buffer %s. " , OG ( active_ob_buffer ) . handler_name ) ;
2002-03-01 11:05:50 +08:00
RETURN_FALSE ;
}
2001-08-05 23:29:47 +08:00
php_end_ob_buffer ( 1 , 0 TSRMLS_CC ) ;
2002-03-01 11:05:50 +08:00
RETURN_TRUE ;
1999-10-28 02:30:41 +08:00
}
2000-04-19 03:18:47 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2002-03-01 11:05:50 +08:00
/* {{{ proto bool ob_end_clean(void)
Clean the output buffer , and delete current output buffer */
1999-10-28 02:30:41 +08:00
PHP_FUNCTION ( ob_end_clean )
{
2002-10-07 19:21:06 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 0 ) {
ZEND_WRONG_PARAM_COUNT ( ) ;
}
2002-02-05 15:37:42 +08:00
2002-03-01 11:05:50 +08:00
if ( ! OG ( ob_nesting_level ) ) {
2002-08-20 02:47:23 +08:00
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to delete buffer. No buffer to delete. " ) ;
2002-03-01 11:05:50 +08:00
RETURN_FALSE ;
}
if ( OG ( ob_nesting_level ) & & ! OG ( active_ob_buffer ) . status & & ! OG ( active_ob_buffer ) . erase ) {
2002-08-20 02:47:23 +08:00
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to delete buffer %s. " , OG ( active_ob_buffer ) . handler_name ) ;
2002-03-01 11:05:50 +08:00
RETURN_FALSE ;
}
2001-08-05 23:29:47 +08:00
php_end_ob_buffer ( 0 , 0 TSRMLS_CC ) ;
2002-03-01 11:05:50 +08:00
RETURN_TRUE ;
1999-10-28 02:30:41 +08:00
}
2000-04-19 03:18:47 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2002-10-03 09:36:44 +08:00
/* {{{ proto bool ob_get_flush(void)
Get current buffer contents , flush ( send ) the output buffer , and delete current output buffer */
PHP_FUNCTION ( ob_get_flush )
{
2002-10-07 19:21:06 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 0 ) {
ZEND_WRONG_PARAM_COUNT ( ) ;
}
2002-10-03 09:36:44 +08:00
/* get contents */
if ( php_ob_get_buffer ( return_value TSRMLS_CC ) = = FAILURE ) {
RETURN_FALSE ;
}
/* error checks */
if ( ! OG ( ob_nesting_level ) ) {
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 ;
}
/* flush */
php_end_ob_buffer ( 1 , 0 TSRMLS_CC ) ;
}
/* }}} */
/* {{{ proto bool ob_get_clean(void)
Get current buffer contents and delete current output buffer */
PHP_FUNCTION ( ob_get_clean )
{
if ( ZEND_NUM_ARGS ( ) ! = 0 )
2002-10-07 19:21:06 +08:00
ZEND_WRONG_PARAM_COUNT ( ) ;
2002-10-03 09:36:44 +08:00
/* get contents */
if ( php_ob_get_buffer ( return_value TSRMLS_CC ) = = FAILURE ) {
RETURN_FALSE ;
}
/* error checks */
if ( ! OG ( ob_nesting_level ) ) {
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 ;
}
/* delete buffer */
php_end_ob_buffer ( 0 , 0 TSRMLS_CC ) ;
}
/* }}} */
2000-05-24 07:13:02 +08:00
/* {{{ proto string ob_get_contents(void)
2000-04-19 03:18:47 +08:00
Return the contents of the output buffer */
1999-10-28 02:30:41 +08:00
PHP_FUNCTION ( ob_get_contents )
{
2002-10-07 19:21:06 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 0 ) {
ZEND_WRONG_PARAM_COUNT ( ) ;
}
2002-02-05 15:37:42 +08:00
2001-08-05 23:29:47 +08:00
if ( php_ob_get_buffer ( return_value TSRMLS_CC ) = = FAILURE ) {
1999-10-28 02:30:41 +08:00
RETURN_FALSE ;
}
}
2000-04-19 03:18:47 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2002-08-13 12:31:59 +08:00
/* {{{ proto int ob_get_level(void)
2001-12-03 15:43:53 +08:00
Return the nesting level of the output buffer */
PHP_FUNCTION ( ob_get_level )
{
2002-10-07 19:21:06 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 0 ) {
ZEND_WRONG_PARAM_COUNT ( ) ;
}
2002-02-05 15:37:42 +08:00
2001-12-03 15:43:53 +08:00
RETURN_LONG ( OG ( ob_nesting_level ) ) ;
}
/* }}} */
2003-02-04 07:36:19 +08:00
/* {{{ proto int ob_get_length(void)
2000-08-25 11:10:42 +08:00
Return the length of the output buffer */
PHP_FUNCTION ( ob_get_length )
{
2002-10-07 19:21:06 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 0 ) {
ZEND_WRONG_PARAM_COUNT ( ) ;
}
2002-02-05 15:37:42 +08:00
2001-08-05 23:29:47 +08:00
if ( php_ob_get_length ( return_value TSRMLS_CC ) = = FAILURE ) {
2000-08-25 11:10:42 +08:00
RETURN_FALSE ;
}
}
/* }}} */
2002-10-03 12:17:41 +08:00
/* {{{ int php_ob_buffer_status(php_ob_buffer *ob_buffer, zval *result) */
2002-03-01 11:05:50 +08:00
static int php_ob_buffer_status ( php_ob_buffer * ob_buffer , zval * result )
{
zval * elem ;
MAKE_STD_ZVAL ( elem ) ;
2003-01-28 01:22:22 +08:00
array_init ( elem ) ;
2002-03-01 17:29:32 +08:00
2002-10-02 23:10:11 +08:00
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 ) ;
}
2002-03-01 11:05:50 +08:00
if ( ob_buffer - > internal_output_handler ) {
add_assoc_long ( elem , " type " , PHP_OUTPUT_HANDLER_INTERNAL ) ;
2002-08-20 02:47:23 +08:00
add_assoc_long ( elem , " buffer_size " , ob_buffer - > internal_output_handler_buffer_size ) ;
2002-03-01 11:05:50 +08:00
}
else {
add_assoc_long ( elem , " type " , PHP_OUTPUT_HANDLER_USER ) ;
}
add_assoc_long ( elem , " status " , ob_buffer - > status ) ;
add_assoc_string ( elem , " name " , ob_buffer - > handler_name , 1 ) ;
add_assoc_bool ( elem , " del " , ob_buffer - > erase ) ;
add_next_index_zval ( result , elem ) ;
return SUCCESS ;
}
2002-10-03 12:17:41 +08:00
/* }}} */
2002-03-01 11:05:50 +08:00
2002-08-10 06:29:58 +08:00
/* {{{ proto false|array ob_get_status([bool full_status])
Return the status of the active or all output buffers */
2002-03-01 11:05:50 +08:00
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 )
2002-08-10 06:29:58 +08:00
RETURN_FALSE ;
2002-03-01 11:05:50 +08:00
2003-01-28 01:22:22 +08:00
array_init ( return_value ) ;
2002-03-01 11:05:50 +08:00
if ( full_status ) {
2002-08-10 06:29:58 +08:00
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 ) ;
2002-03-01 11:05:50 +08:00
}
2002-08-10 06:29:58 +08:00
if ( OG ( ob_nesting_level ) > 0 & & php_ob_buffer_status ( & OG ( active_ob_buffer ) , return_value ) = = FAILURE ) {
RETURN_FALSE ;
2002-03-01 11:05:50 +08:00
}
2002-10-07 19:21:06 +08:00
} else if ( OG ( ob_nesting_level ) > 0 ) {
2002-03-01 11:05:50 +08:00
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 ) ;
2002-10-07 19:21:06 +08:00
} else {
2002-03-01 11:05:50 +08:00
add_assoc_long ( return_value , " type " , PHP_OUTPUT_HANDLER_USER ) ;
}
add_assoc_long ( return_value , " status " , OG ( active_ob_buffer ) . status ) ;
add_assoc_string ( return_value , " name " , OG ( active_ob_buffer ) . handler_name , 1 ) ;
add_assoc_bool ( return_value , " del " , OG ( active_ob_buffer ) . erase ) ;
}
}
/* }}} */
2000-04-19 04:00:21 +08:00
/* {{{ proto void ob_implicit_flush([int flag])
Turn implicit flush on / off and is equivalent to calling flush ( ) after every output call */
2000-01-14 01:37:25 +08:00
PHP_FUNCTION ( ob_implicit_flush )
{
zval * * zv_flag ;
2000-01-16 01:23:18 +08:00
int flag ;
2000-01-14 01:37:25 +08:00
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 ) ;
2001-09-26 05:58:48 +08:00
flag = Z_LVAL_PP ( zv_flag ) ;
2000-01-14 01:37:25 +08:00
break ;
2000-01-16 01:23:18 +08:00
default :
2002-10-07 19:21:06 +08:00
ZEND_WRONG_PARAM_COUNT ( ) ;
2000-01-16 01:23:18 +08:00
break ;
2000-01-14 01:37:25 +08:00
}
2000-01-14 01:54:51 +08:00
if ( flag ) {
2001-08-05 23:29:47 +08:00
php_start_implicit_flush ( TSRMLS_C ) ;
2000-01-14 01:54:51 +08:00
} else {
2001-08-05 23:29:47 +08:00
php_end_implicit_flush ( TSRMLS_C ) ;
2000-01-14 01:54:51 +08:00
}
2000-01-14 01:37:25 +08:00
}
2000-04-19 03:18:47 +08:00
/* }}} */
2000-01-14 01:37:25 +08:00
2002-10-03 12:17:41 +08:00
/* {{{ char *php_get_output_start_filename(TSRMLS_D)
Return filename start output something */
2001-08-05 23:29:47 +08:00
PHPAPI char * php_get_output_start_filename ( TSRMLS_D )
2000-02-04 22:54:30 +08:00
{
return OG ( output_start_filename ) ;
}
2002-10-03 12:17:41 +08:00
/* }}} */
2000-02-04 22:54:30 +08:00
2002-10-03 12:17:41 +08:00
/* {{{ char *php_get_output_start_lineno(TSRMLS_D)
Return line number start output something */
2001-08-05 23:29:47 +08:00
PHPAPI int php_get_output_start_lineno ( TSRMLS_D )
2000-02-04 22:54:30 +08:00
{
return OG ( output_start_lineno ) ;
}
2002-10-03 12:17:41 +08:00
/* }}} */
2000-02-04 22:54:30 +08:00
2002-10-03 12:17:41 +08:00
/* {{{ proto bool output_reset_rewrite_vars(void)
Reset ( clear ) URL rewriter values */
2002-05-05 02:33:13 +08:00
PHP_FUNCTION ( output_reset_rewrite_vars )
2002-05-03 16:00:41 +08:00
{
2002-05-05 02:33:13 +08:00
if ( php_url_scanner_reset_vars ( TSRMLS_C ) = = SUCCESS ) {
2002-05-03 16:00:41 +08:00
RETURN_TRUE ;
} else {
RETURN_FALSE ;
}
}
2002-10-03 12:17:41 +08:00
/* }}} */
2002-05-03 16:00:41 +08:00
2002-10-03 12:17:41 +08:00
/* {{{ proto bool output_add_rewrite_var(string name, string value)
Add URL rewriter values */
2002-05-03 16:00:41 +08:00
PHP_FUNCTION ( output_add_rewrite_var )
{
char * name , * value ;
int name_len , value_len ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " ss " , & name , & name_len , & value , & value_len ) = = FAILURE ) {
RETURN_FALSE ;
}
if ( php_url_scanner_add_var ( name , name_len , value , value_len , 1 TSRMLS_CC ) = = SUCCESS ) {
RETURN_TRUE ;
} else {
RETURN_FALSE ;
}
}
2002-10-03 12:17:41 +08:00
/* }}} */
2002-05-03 16:00:41 +08:00
1999-10-28 02:30:41 +08:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* End :
2001-09-09 21:29:31 +08:00
* vim600 : sw = 4 ts = 4 fdm = marker
* vim < 600 : sw = 4 ts = 4
1999-10-28 02:30:41 +08:00
*/