2010-05-31 18:29:43 +08:00
/*
1999-10-28 02:30:41 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2004-01-08 16:18:22 +08:00
| PHP Version 5 |
1999-10-28 02:30:41 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2011-01-01 10:17:06 +08:00
| Copyright ( c ) 1997 - 2011 The PHP Group |
1999-10-28 02:30:41 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 20:51:34 +08:00
| This source file is subject to version 3.01 of the PHP license , |
1999-10-28 02:30:41 +08:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-11 04:04:29 +08:00
| available through the world - wide - web at the following url : |
2006-01-01 20:51:34 +08:00
| http : //www.php.net/license/3_01.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 > |
2010-05-31 18:29:43 +08:00
| New API : Michael Wallner < mike @ 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
2010-05-31 18:29:43 +08:00
# ifndef PHP_OUTPUT_DEBUG
# define PHP_OUTPUT_DEBUG 0
# endif
# ifndef PHP_OUTPUT_NOINLINE
# define PHP_OUTPUT_NOINLINE 0
# endif
1999-10-28 02:30:41 +08:00
# include "php.h"
# include "ext/standard/head.h"
2002-05-03 16:00:41 +08:00
# include "ext/standard/url_scanner_ex.h"
2010-03-12 18:28:59 +08:00
# include "SAPI.h"
2010-05-31 18:29:43 +08:00
# include "zend_stack.h"
# include "php_output.h"
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
ZEND_DECLARE_MODULE_GLOBALS ( output ) ;
2010-03-11 18:24:29 +08:00
2010-06-02 20:49:12 +08:00
const char php_output_default_handler_name [ sizeof ( " default output handler " ) ] = " default output handler " ;
const char php_output_devnull_handler_name [ sizeof ( " null output handler " ) ] = " null output handler " ;
2010-03-11 18:24:29 +08:00
2010-05-31 18:29:43 +08:00
# if PHP_OUTPUT_NOINLINE || PHP_OUTPUT_DEBUG
# undef inline
# define inline
2010-03-12 18:28:59 +08:00
# endif
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ aliases, conflict and reverse conflict hash tables */
static HashTable php_output_handler_aliases ;
static HashTable php_output_handler_conflicts ;
static HashTable php_output_handler_reverse_conflicts ;
/* }}} */
/* {{{ forward declarations */
static inline int php_output_lock_error ( int op TSRMLS_DC ) ;
static inline void php_output_op ( int op , const char * str , size_t len TSRMLS_DC ) ;
static inline php_output_handler * php_output_handler_init ( const char * name , size_t name_len , size_t chunk_size , int flags TSRMLS_DC ) ;
static inline php_output_handler_status_t php_output_handler_op ( php_output_handler * handler , php_output_context * context ) ;
static inline int php_output_handler_append ( php_output_handler * handler , const php_output_buffer * buf TSRMLS_DC ) ;
static inline zval * php_output_handler_status ( php_output_handler * handler , zval * entry ) ;
static inline php_output_context * php_output_context_init ( php_output_context * context , int op TSRMLS_DC ) ;
static inline void php_output_context_reset ( php_output_context * context ) ;
static inline void php_output_context_swap ( php_output_context * context ) ;
static inline void php_output_context_dtor ( php_output_context * context ) ;
static inline int php_output_stack_pop ( int flags TSRMLS_DC ) ;
static int php_output_stack_apply_op ( void * h , void * c ) ;
static int php_output_stack_apply_clean ( void * h , void * c ) ;
static int php_output_stack_apply_list ( void * h , void * z ) ;
static int php_output_stack_apply_status ( void * h , void * z ) ;
2010-03-11 18:24:29 +08:00
2010-05-31 18:29:43 +08:00
static int php_output_handler_compat_func ( void * * handler_context , php_output_context * output_context ) ;
static int php_output_handler_default_func ( void * * handler_context , php_output_context * output_context ) ;
static int php_output_handler_devnull_func ( void * * handler_context , php_output_context * output_context ) ;
/* }}} */
/* {{{ static void php_output_init_globals(zend_output_globals *G)
2010-12-03 23:34:24 +08:00
* Initialize the module globals on MINIT */
2010-05-31 18:29:43 +08:00
static inline void php_output_init_globals ( zend_output_globals * G )
2001-05-08 06:00:13 +08:00
{
2010-05-31 18:29:43 +08:00
memset ( G , 0 , sizeof ( * G ) ) ;
2001-05-08 06:00:13 +08:00
}
2002-10-03 12:17:41 +08:00
/* }}} */
2001-05-08 06:00:13 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ void php_output_startup(void)
2010-12-03 23:34:24 +08:00
* Set up module globals and initalize the conflict and reverse conflict hash tables */
2010-05-31 18:29:43 +08:00
PHPAPI void php_output_startup ( void )
1999-10-28 02:30:41 +08:00
{
2010-05-31 18:29:43 +08:00
ZEND_INIT_MODULE_GLOBALS ( output , php_output_init_globals , NULL ) ;
zend_hash_init ( & php_output_handler_aliases , 0 , NULL , NULL , 1 ) ;
zend_hash_init ( & php_output_handler_conflicts , 0 , NULL , NULL , 1 ) ;
zend_hash_init ( & php_output_handler_reverse_conflicts , 0 , NULL , ( void ( * ) ( void * ) ) zend_hash_destroy , 1 ) ;
1999-10-28 02:30:41 +08:00
}
2002-10-03 12:17:41 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ void php_output_shutdown(void)
2010-12-03 23:34:24 +08:00
* Destroy module globals and the conflict and reverse conflict hash tables */
2010-05-31 18:29:43 +08:00
PHPAPI void php_output_shutdown ( void )
{
zend_hash_destroy ( & php_output_handler_aliases ) ;
zend_hash_destroy ( & php_output_handler_conflicts ) ;
zend_hash_destroy ( & php_output_handler_reverse_conflicts ) ;
}
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ SUCCESS|FAILURE php_output_activate(TSRMLS_D)
2010-12-03 23:34:24 +08:00
* Reset output globals and setup the output handler stack */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_activate ( TSRMLS_D )
1999-10-28 02:30:41 +08:00
{
# ifdef ZTS
2010-05-31 18:29:43 +08:00
memset ( ( * ( ( void * * * ) tsrm_ls ) ) [ TSRM_UNSHUFFLE_RSRC_ID ( output_globals_id ) ] , 0 , sizeof ( zend_output_globals ) ) ;
# else
memset ( & output_globals , 0 , sizeof ( zend_output_globals ) ) ;
1999-10-28 02:30:41 +08:00
# endif
2010-12-03 23:34:24 +08:00
2010-08-27 14:09:18 +08:00
zend_stack_init ( & OG ( handlers ) ) ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
return SUCCESS ;
2001-07-03 02:17:10 +08:00
}
2002-10-03 12:17:41 +08:00
/* }}} */
2001-07-03 02:17:10 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ void php_output_deactivate(TSRMLS_D)
2010-12-03 23:34:24 +08:00
* Destroy the output handler stack */
2010-05-31 18:29:43 +08:00
PHPAPI void php_output_deactivate ( TSRMLS_D )
2010-03-11 18:24:29 +08:00
{
2010-05-31 18:29:43 +08:00
php_output_handler * * handler = NULL ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
OG ( active ) = NULL ;
OG ( running ) = NULL ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
/* release all output handlers */
2010-08-27 14:09:18 +08:00
if ( OG ( handlers ) . elements ) {
while ( SUCCESS = = zend_stack_top ( & OG ( handlers ) , ( void * ) & handler ) ) {
2010-05-31 18:29:43 +08:00
php_output_handler_free ( handler TSRMLS_CC ) ;
2010-08-27 14:09:18 +08:00
zend_stack_del_top ( & OG ( handlers ) ) ;
2010-05-31 18:29:43 +08:00
}
2010-08-27 14:09:18 +08:00
zend_stack_destroy ( & OG ( handlers ) ) ;
2010-05-31 18:29:43 +08:00
}
2010-03-11 18:24:29 +08:00
}
/* }}} */
2001-07-20 21:59:00 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ void php_output_register_constants() */
PHPAPI void php_output_register_constants ( TSRMLS_D )
2001-03-04 09:45:19 +08:00
{
2010-05-31 18:29:43 +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_WRITE " , PHP_OUTPUT_HANDLER_WRITE , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_MAIN_LONG_CONSTANT ( " PHP_OUTPUT_HANDLER_FLUSH " , PHP_OUTPUT_HANDLER_FLUSH , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_MAIN_LONG_CONSTANT ( " PHP_OUTPUT_HANDLER_CLEAN " , PHP_OUTPUT_HANDLER_CLEAN , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_MAIN_LONG_CONSTANT ( " PHP_OUTPUT_HANDLER_FINAL " , PHP_OUTPUT_HANDLER_FINAL , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_MAIN_LONG_CONSTANT ( " PHP_OUTPUT_HANDLER_CONT " , PHP_OUTPUT_HANDLER_WRITE , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_MAIN_LONG_CONSTANT ( " PHP_OUTPUT_HANDLER_END " , PHP_OUTPUT_HANDLER_FINAL , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_MAIN_LONG_CONSTANT ( " PHP_OUTPUT_HANDLER_CLEANABLE " , PHP_OUTPUT_HANDLER_CLEANABLE , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_MAIN_LONG_CONSTANT ( " PHP_OUTPUT_HANDLER_FLUSHABLE " , PHP_OUTPUT_HANDLER_FLUSHABLE , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_MAIN_LONG_CONSTANT ( " PHP_OUTPUT_HANDLER_REMOVABLE " , PHP_OUTPUT_HANDLER_REMOVABLE , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_MAIN_LONG_CONSTANT ( " PHP_OUTPUT_HANDLER_STDFLAGS " , PHP_OUTPUT_HANDLER_STDFLAGS , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_MAIN_LONG_CONSTANT ( " PHP_OUTPUT_HANDLER_STARTED " , PHP_OUTPUT_HANDLER_STARTED , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_MAIN_LONG_CONSTANT ( " PHP_OUTPUT_HANDLER_DISABLED " , PHP_OUTPUT_HANDLER_DISABLED , CONST_CS | CONST_PERSISTENT ) ;
1999-10-28 02:30:41 +08:00
}
2002-10-03 12:17:41 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ void php_output_set_status(int status TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Used by SAPIs to disable output */
2010-05-31 18:29:43 +08:00
PHPAPI void php_output_set_status ( int status TSRMLS_DC )
2010-03-11 18:24:29 +08:00
{
2010-05-31 18:29:43 +08:00
OG ( flags ) = status & 0xf ;
2010-03-11 18:24:29 +08:00
}
/* }}} */
2001-03-04 09:45:19 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ int php_output_get_status(TSRMLS_C)
2010-12-03 23:34:24 +08:00
* Get output control status */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_get_status ( TSRMLS_D )
1999-10-28 02:30:41 +08:00
{
2010-05-31 18:29:43 +08:00
return OG ( flags )
| ( OG ( active ) ? PHP_OUTPUT_ACTIVE : 0 )
| ( OG ( running ) ? PHP_OUTPUT_LOCKED : 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
2010-05-31 18:29:43 +08:00
/* {{{ int php_output_write_unbuffered(const char *str, size_t len TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Unbuffered write */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_write_unbuffered ( const char * str , size_t len TSRMLS_DC )
1999-10-28 02:30:41 +08:00
{
2010-05-31 18:29:43 +08:00
if ( OG ( flags ) & PHP_OUTPUT_DISABLED ) {
2010-03-11 18:24:29 +08:00
return 0 ;
2000-09-03 02:03:58 +08:00
}
2010-05-31 18:29:43 +08:00
return sapi_module . ub_write ( str , len TSRMLS_CC ) ;
2010-03-11 18:24:29 +08:00
}
/* }}} */
2010-05-31 18:29:43 +08:00
/* {{{ int php_output_write(const char *str, size_t len TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Buffered write */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_write ( const char * str , size_t len TSRMLS_DC )
2010-03-11 18:24:29 +08:00
{
2010-05-31 18:29:43 +08:00
if ( OG ( flags ) & PHP_OUTPUT_DISABLED ) {
return 0 ;
2002-09-01 19:33:19 +08:00
}
2010-05-31 18:29:43 +08:00
php_output_op ( PHP_OUTPUT_HANDLER_WRITE , str , len TSRMLS_CC ) ;
return ( int ) len ;
}
/* }}} */
/* {{{ SUCCESS|FAILURE php_output_flush(TSRMLS_D)
2010-12-03 23:34:24 +08:00
* Flush the most recent output handlers buffer */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_flush ( TSRMLS_D )
{
php_output_context context ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( OG ( active ) & & ( OG ( active ) - > flags & PHP_OUTPUT_HANDLER_FLUSHABLE ) ) {
php_output_context_init ( & context , PHP_OUTPUT_HANDLER_FLUSH TSRMLS_CC ) ;
php_output_handler_op ( OG ( active ) , & context ) ;
if ( context . out . data & & context . out . used ) {
2010-08-27 14:09:18 +08:00
zend_stack_del_top ( & OG ( handlers ) ) ;
2010-05-31 18:29:43 +08:00
php_output_write ( context . out . data , context . out . used TSRMLS_CC ) ;
2010-08-27 14:09:18 +08:00
zend_stack_push ( & OG ( handlers ) , & OG ( active ) , sizeof ( php_output_handler * ) ) ;
2010-03-12 18:28:59 +08:00
}
2010-05-31 18:29:43 +08:00
php_output_context_dtor ( & context ) ;
return SUCCESS ;
2010-03-11 18:24:29 +08:00
}
2010-05-31 18:29:43 +08:00
return FAILURE ;
1999-10-28 02:30:41 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ void php_output_flush_all(TSRMLS_C)
2010-12-03 23:34:24 +08:00
* Flush all output buffers subsequently */
2010-05-31 18:29:43 +08:00
PHPAPI void php_output_flush_all ( TSRMLS_D )
1999-10-28 02:30:41 +08:00
{
2010-05-31 18:29:43 +08:00
if ( OG ( active ) ) {
php_output_op ( PHP_OUTPUT_HANDLER_FLUSH , NULL , 0 TSRMLS_CC ) ;
}
2010-03-11 18:24:29 +08:00
}
/* }}} */
2000-09-03 02:03:58 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ SUCCESS|FAILURE php_output_clean(TSRMLS_D)
2010-12-03 23:34:24 +08:00
* Cleans the most recent output handlers buffer if the handler is cleanable */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_clean ( TSRMLS_D )
2010-03-11 18:24:29 +08:00
{
2010-05-31 18:29:43 +08:00
php_output_context context ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( OG ( active ) & & ( OG ( active ) - > flags & PHP_OUTPUT_HANDLER_CLEANABLE ) ) {
OG ( active ) - > buffer . used = 0 ;
php_output_context_init ( & context , PHP_OUTPUT_HANDLER_CLEAN TSRMLS_CC ) ;
php_output_handler_op ( OG ( active ) , & context ) ;
php_output_context_dtor ( & context ) ;
return SUCCESS ;
}
return FAILURE ;
}
/* }}} */
2000-11-03 00:46:30 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ void php_output_clean_all(TSRMLS_D)
2010-12-03 23:34:24 +08:00
* Cleans all output handler buffers , without regard whether the handler is cleanable */
2010-05-31 18:29:43 +08:00
PHPAPI void php_output_clean_all ( TSRMLS_D )
{
php_output_context context ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( OG ( active ) ) {
php_output_context_init ( & context , PHP_OUTPUT_HANDLER_CLEAN TSRMLS_CC ) ;
2010-08-27 14:09:18 +08:00
zend_stack_apply_with_argument ( & OG ( handlers ) , ZEND_STACK_APPLY_TOPDOWN , php_output_stack_apply_clean , & context ) ;
2010-03-12 18:28:59 +08:00
}
2010-05-31 18:29:43 +08:00
}
2000-11-03 00:46:30 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ SUCCESS|FAILURE php_output_end(TSRMLS_D)
2010-12-03 23:34:24 +08:00
* Finalizes the most recent output handler at pops it off the stack if the handler is removable */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_end ( TSRMLS_D )
{
if ( php_output_stack_pop ( PHP_OUTPUT_POP_TRY TSRMLS_CC ) ) {
return SUCCESS ;
2001-03-07 03:38:33 +08:00
}
2010-05-31 18:29:43 +08:00
return FAILURE ;
}
/* }}} */
2000-11-03 00:46:30 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ void php_output_end_all(TSRMLS_D)
2010-12-03 23:34:24 +08:00
* Finalizes all output handlers and ends output buffering without regard whether a handler is removable */
2010-05-31 18:29:43 +08:00
PHPAPI void php_output_end_all ( TSRMLS_D )
{
while ( OG ( active ) & & php_output_stack_pop ( PHP_OUTPUT_POP_FORCE TSRMLS_CC ) ) ;
}
/* }}} */
2000-11-03 00:46:30 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ SUCCESS|FAILURE php_output_discard(TSRMLS_D)
2010-12-03 23:34:24 +08:00
* Discards the most recent output handlers buffer and pops it off the stack if the handler is removable */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_discard ( TSRMLS_D )
{
if ( php_output_stack_pop ( PHP_OUTPUT_POP_DISCARD | PHP_OUTPUT_POP_TRY TSRMLS_CC ) ) {
return SUCCESS ;
2010-03-12 18:28:59 +08:00
}
2010-05-31 18:29:43 +08:00
return FAILURE ;
}
/* }}} */
2010-03-11 18:24:29 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ void php_output_discard_all(TSRMLS_D)
2010-12-03 23:34:24 +08:00
* Discard all output handlers and buffers without regard whether a handler is removable */
2010-05-31 18:29:43 +08:00
PHPAPI void php_output_discard_all ( TSRMLS_D )
{
while ( OG ( active ) ) {
php_output_stack_pop ( PHP_OUTPUT_POP_DISCARD | PHP_OUTPUT_POP_FORCE TSRMLS_CC ) ;
2010-03-12 18:28:59 +08:00
}
2010-05-31 18:29:43 +08:00
}
/* }}} */
2000-11-03 00:46:30 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ int php_output_get_level(TSRMLS_D)
2010-12-03 23:34:24 +08:00
* Get output buffering level , ie . how many output handlers the stack contains */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_get_level ( TSRMLS_D )
{
2010-08-27 14:09:18 +08:00
return OG ( active ) ? zend_stack_count ( & OG ( handlers ) ) : 0 ;
2010-05-31 18:29:43 +08:00
}
/* }}} */
/* {{{ SUCCESS|FAILURE php_output_get_contents(zval *z TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Get the contents of the active output handlers buffer */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_get_contents ( zval * p TSRMLS_DC )
{
if ( OG ( active ) ) {
ZVAL_STRINGL ( p , OG ( active ) - > buffer . data , OG ( active ) - > buffer . used , 1 ) ;
return SUCCESS ;
} else {
ZVAL_NULL ( p ) ;
return FAILURE ;
2001-08-31 23:56:48 +08:00
}
2010-05-31 18:29:43 +08:00
}
2001-08-31 23:56:48 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ SUCCESS|FAILURE php_output_get_length(zval *z TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Get the length of the active output handlers buffer */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_get_length ( zval * p TSRMLS_DC )
{
if ( OG ( active ) ) {
ZVAL_LONG ( p , OG ( active ) - > buffer . used ) ;
return SUCCESS ;
} else {
ZVAL_NULL ( p ) ;
return FAILURE ;
1999-10-28 02:30:41 +08:00
}
2010-05-31 18:29:43 +08:00
}
/* }}} */
2000-11-03 00:46:30 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ SUCCESS|FAILURE php_output_handler_start_default(TSRMLS_D)
2010-12-03 23:34:24 +08:00
* Start a " default output handler " */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_start_default ( TSRMLS_D )
{
php_output_handler * handler ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
handler = php_output_handler_create_internal ( ZEND_STRL ( php_output_default_handler_name ) , php_output_handler_default_func , 0 , PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC ) ;
if ( SUCCESS = = php_output_handler_start ( handler TSRMLS_CC ) ) {
return SUCCESS ;
2002-05-04 18:55:08 +08:00
}
2010-05-31 18:29:43 +08:00
php_output_handler_free ( & handler TSRMLS_CC ) ;
return FAILURE ;
}
/* }}} */
2010-03-11 18:24:29 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ SUCCESS|FAILURE php_output_handler_start_devnull(TSRMLS_D)
2010-12-03 23:34:24 +08:00
* Start a " null output handler " */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_start_devnull ( TSRMLS_D )
{
php_output_handler * handler ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
handler = php_output_handler_create_internal ( ZEND_STRL ( php_output_devnull_handler_name ) , php_output_handler_devnull_func , PHP_OUTPUT_HANDLER_DEFAULT_SIZE , 0 TSRMLS_CC ) ;
if ( SUCCESS = = php_output_handler_start ( handler TSRMLS_CC ) ) {
return SUCCESS ;
2010-03-12 18:28:59 +08:00
}
2010-05-31 18:29:43 +08:00
php_output_handler_free ( & handler TSRMLS_CC ) ;
return FAILURE ;
}
/* }}} */
/* {{{ SUCCESS|FAILURE php_output_start_user(zval *handler, size_t chunk_size, int flags TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Start a user level output handler */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_start_user ( zval * output_handler , size_t chunk_size , int flags TSRMLS_DC )
{
php_output_handler * handler ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( output_handler ) {
handler = php_output_handler_create_user ( output_handler , chunk_size , flags TSRMLS_CC ) ;
2001-03-04 09:09:36 +08:00
} else {
2010-05-31 18:29:43 +08:00
handler = php_output_handler_create_internal ( ZEND_STRL ( php_output_default_handler_name ) , php_output_handler_default_func , chunk_size , flags TSRMLS_CC ) ;
2001-03-07 03:38:33 +08:00
}
2010-05-31 18:29:43 +08:00
if ( SUCCESS = = php_output_handler_start ( handler TSRMLS_CC ) ) {
return SUCCESS ;
2000-07-29 22:46:09 +08:00
}
2010-05-31 18:29:43 +08:00
php_output_handler_free ( & handler TSRMLS_CC ) ;
return FAILURE ;
2000-07-29 22:46:09 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
2000-07-29 22:46:09 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ SUCCESS|FAILURE php_output_start_internal(zval *name, php_output_handler_func_t handler, size_t chunk_size, int flags TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Start an internal output handler that does not have to maintain a non - global state */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_start_internal ( const char * name , size_t name_len , php_output_handler_func_t output_handler , size_t chunk_size , int flags TSRMLS_DC )
2000-01-14 01:37:25 +08:00
{
2010-05-31 18:29:43 +08:00
php_output_handler * handler ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
handler = php_output_handler_create_internal ( name , name_len , php_output_handler_compat_func , chunk_size , flags TSRMLS_CC ) ;
php_output_handler_set_context ( handler , output_handler , NULL TSRMLS_CC ) ;
if ( SUCCESS = = php_output_handler_start ( handler TSRMLS_CC ) ) {
return SUCCESS ;
2010-03-11 18:24:29 +08:00
}
2010-05-31 18:29:43 +08:00
php_output_handler_free ( & handler TSRMLS_CC ) ;
return FAILURE ;
2000-01-14 01:37:25 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
2000-01-14 01:37:25 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ php_output_handler *php_output_handler_create_user(zval *handler, size_t chunk_size, int flags TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Create a user level output handler */
2010-05-31 18:29:43 +08:00
PHPAPI php_output_handler * php_output_handler_create_user ( zval * output_handler , size_t chunk_size , int flags TSRMLS_DC )
2000-01-14 01:37:25 +08:00
{
2010-06-01 21:16:33 +08:00
char * handler_name = NULL , * error = NULL ;
2010-05-31 18:29:43 +08:00
php_output_handler * handler = NULL ;
php_output_handler_alias_ctor_t * alias = NULL ;
php_output_handler_user_func_t * user = NULL ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
switch ( Z_TYPE_P ( output_handler ) ) {
case IS_NULL :
handler = php_output_handler_create_internal ( ZEND_STRL ( php_output_default_handler_name ) , php_output_handler_default_func , chunk_size , flags TSRMLS_CC ) ;
break ;
case IS_STRING :
if ( Z_STRLEN_P ( output_handler ) & & ( alias = php_output_handler_alias ( Z_STRVAL_P ( output_handler ) , Z_STRLEN_P ( output_handler ) TSRMLS_CC ) ) ) {
handler = ( * alias ) ( Z_STRVAL_P ( output_handler ) , Z_STRLEN_P ( output_handler ) , chunk_size , flags TSRMLS_CC ) ;
break ;
}
default :
user = ecalloc ( 1 , sizeof ( php_output_handler_user_func_t ) ) ;
2010-06-01 21:16:33 +08:00
if ( SUCCESS = = zend_fcall_info_init ( output_handler , 0 , & user - > fci , & user - > fcc , & handler_name , & error TSRMLS_CC ) ) {
2010-05-31 18:29:43 +08:00
handler = php_output_handler_init ( handler_name , strlen ( handler_name ) , chunk_size , ( flags & ~ 0xf ) | PHP_OUTPUT_HANDLER_USER TSRMLS_CC ) ;
Z_ADDREF_P ( output_handler ) ;
user - > zoh = output_handler ;
handler - > func . user = user ;
} else {
efree ( user ) ;
2010-06-09 19:04:03 +08:00
}
if ( error ) {
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_WARNING , " %s " , error ) ;
efree ( error ) ;
2010-05-31 18:29:43 +08:00
}
if ( handler_name ) {
efree ( handler_name ) ;
}
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
return handler ;
2000-01-14 01:37:25 +08:00
}
2010-03-12 18:28:59 +08:00
/* }}} */
2000-01-14 01:37:25 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ 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)
2010-12-03 23:34:24 +08:00
* Create an internal output handler that can maintain a non - global state */
2010-05-31 18:29:43 +08:00
PHPAPI php_output_handler * php_output_handler_create_internal ( const char * name , size_t name_len , php_output_handler_context_func_t output_handler , size_t chunk_size , int flags TSRMLS_DC )
2001-03-06 23:54:49 +08:00
{
2010-05-31 18:29:43 +08:00
php_output_handler * handler ;
handler = php_output_handler_init ( name , name_len , chunk_size , ( flags & ~ 0xf ) | PHP_OUTPUT_HANDLER_INTERNAL TSRMLS_CC ) ;
handler - > func . internal = output_handler ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
return handler ;
2010-03-11 18:24:29 +08:00
}
/* }}} */
2001-03-06 23:54:49 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ void php_output_handler_set_context(php_output_handler *handler, void *opaq, void (*dtor)(void* TSRMLS_DC) TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Set the context / state of an output handler . Calls the dtor of the previous context if there is one */
2010-05-31 18:29:43 +08:00
PHPAPI void php_output_handler_set_context ( php_output_handler * handler , void * opaq , void ( * dtor ) ( void * TSRMLS_DC ) TSRMLS_DC )
2010-03-11 18:24:29 +08:00
{
2010-05-31 18:29:43 +08:00
if ( handler - > dtor & & handler - > opaq ) {
handler - > dtor ( handler - > opaq TSRMLS_CC ) ;
2002-10-07 19:21:06 +08:00
}
2010-05-31 18:29:43 +08:00
handler - > dtor = dtor ;
handler - > opaq = opaq ;
}
/* }}} */
2010-03-12 18:28:59 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ SUCCESS|FAILURE php_output_handler_start(php_output_handler *handler TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Starts the set up output handler and pushes it on top of the stack . Checks for any conflicts regarding the output handler to start */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_handler_start ( php_output_handler * handler TSRMLS_DC )
{
HashPosition pos ;
HashTable * rconflicts ;
php_output_handler_conflict_check_t * conflict ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( php_output_lock_error ( PHP_OUTPUT_HANDLER_START TSRMLS_CC ) | | ! handler ) {
return FAILURE ;
}
if ( SUCCESS = = zend_hash_find ( & php_output_handler_conflicts , handler - > name , handler - > name_len + 1 , ( void * ) & conflict ) ) {
if ( SUCCESS ! = ( * conflict ) ( handler - > name , handler - > name_len TSRMLS_CC ) ) {
return FAILURE ;
}
}
if ( SUCCESS = = zend_hash_find ( & php_output_handler_reverse_conflicts , handler - > name , handler - > name_len + 1 , ( void * ) & rconflicts ) ) {
2010-12-03 23:34:24 +08:00
for ( zend_hash_internal_pointer_reset_ex ( rconflicts , & pos ) ;
zend_hash_get_current_data_ex ( rconflicts , ( void * ) & conflict , & pos ) = = SUCCESS ;
zend_hash_move_forward_ex ( rconflicts , & pos )
) {
2010-05-31 18:29:43 +08:00
if ( SUCCESS ! = ( * conflict ) ( handler - > name , handler - > name_len TSRMLS_CC ) ) {
return FAILURE ;
}
}
2010-03-11 18:24:29 +08:00
}
2010-05-31 18:29:43 +08:00
/* zend_stack_push never returns SUCCESS but FAILURE or stack level */
2010-08-27 14:09:18 +08:00
if ( FAILURE = = ( handler - > level = zend_stack_push ( & OG ( handlers ) , & handler , sizeof ( php_output_handler * ) ) ) ) {
2010-05-31 18:29:43 +08:00
return FAILURE ;
}
OG ( active ) = handler ;
return SUCCESS ;
2001-03-06 23:54:49 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
2001-03-06 23:54:49 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ int php_output_handler_started(zval *name TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Check whether a certain output handler is in use */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_handler_started ( const char * name , size_t name_len TSRMLS_DC )
1999-10-28 02:30:41 +08:00
{
2011-11-13 12:11:57 +08:00
php_output_handler * * * handlers ;
2010-05-31 18:29:43 +08:00
int i , count = php_output_get_level ( TSRMLS_C ) ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( count ) {
2011-11-13 12:11:57 +08:00
handlers = ( php_output_handler * * * ) zend_stack_base ( & OG ( handlers ) ) ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
for ( i = 0 ; i < count ; + + i ) {
2011-11-13 12:11:57 +08:00
if ( name_len = = ( * ( handlers [ i ] ) ) - > name_len & & ! memcmp ( ( * ( handlers [ i ] ) ) - > name , name , name_len ) ) {
2010-05-31 18:29:43 +08:00
return 1 ;
}
2000-07-29 22:46:09 +08:00
}
1999-10-28 02:30:41 +08:00
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
return 0 ;
1999-10-28 02:30:41 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ int php_output_handler_conflict(zval *handler_new, zval *handler_old TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Check whether a certain handler is in use and issue a warning that the new handler would conflict with the already used one */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_handler_conflict ( const char * handler_new , size_t handler_new_len , const char * handler_set , size_t handler_set_len TSRMLS_DC )
1999-10-28 02:30:41 +08:00
{
2010-05-31 18:29:43 +08:00
if ( php_output_handler_started ( handler_set , handler_set_len TSRMLS_CC ) ) {
if ( handler_new_len ! = handler_set_len | | memcmp ( handler_new , handler_set , handler_set_len ) ) {
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_WARNING , " output handler '%s' conflicts with '%s' " , handler_new , handler_set ) ;
} else {
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_WARNING , " output handler '%s' cannot be used twice " , handler_new ) ;
}
2002-08-10 06:29:58 +08:00
return 1 ;
}
return 0 ;
}
/* }}} */
2010-05-31 18:29:43 +08:00
/* {{{ SUCCESS|FAILURE php_output_handler_conflict_register(zval *name, php_output_handler_conflict_check_t check_func TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Register a conflict checking function on MINIT */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_handler_conflict_register ( const char * name , size_t name_len , php_output_handler_conflict_check_t check_func TSRMLS_DC )
2002-08-10 06:29:58 +08:00
{
2010-05-31 18:29:43 +08:00
if ( ! EG ( current_module ) ) {
zend_error ( E_ERROR , " Cannot register an output handler conflict outside of MINIT " ) ;
return FAILURE ;
}
return zend_hash_update ( & php_output_handler_conflicts , name , name_len + 1 , & check_func , sizeof ( php_output_handler_conflict_check_t * ) , NULL ) ;
}
/* }}} */
2010-03-11 18:24:29 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ SUCCESS|FAILURE php_output_handler_reverse_conflict_register(zval *name, php_output_handler_conflict_check_t check_func TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Register a reverse conflict checking function on MINIT */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_handler_reverse_conflict_register ( const char * name , size_t name_len , php_output_handler_conflict_check_t check_func TSRMLS_DC )
{
HashTable rev , * rev_ptr = NULL ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( ! EG ( current_module ) ) {
zend_error ( E_ERROR , " Cannot register a reverse output handler conflict outside of MINIT " ) ;
2010-03-11 18:24:29 +08:00
return FAILURE ;
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( SUCCESS = = zend_hash_find ( & php_output_handler_reverse_conflicts , name , name_len + 1 , ( void * ) & rev_ptr ) ) {
return zend_hash_next_index_insert ( rev_ptr , & check_func , sizeof ( php_output_handler_conflict_check_t * ) , NULL ) ;
} else {
zend_hash_init ( & rev , 1 , NULL , NULL , 1 ) ;
if ( SUCCESS ! = zend_hash_next_index_insert ( & rev , & check_func , sizeof ( php_output_handler_conflict_check_t * ) , NULL ) ) {
zend_hash_destroy ( & rev ) ;
return FAILURE ;
2010-11-03 16:35:16 +08:00
}
2010-05-31 18:29:43 +08:00
if ( SUCCESS ! = zend_hash_update ( & php_output_handler_reverse_conflicts , name , name_len + 1 , & rev , sizeof ( HashTable ) , NULL ) ) {
zend_hash_destroy ( & rev ) ;
2002-12-31 03:39:31 +08:00
return FAILURE ;
}
2010-05-31 18:29:43 +08:00
return SUCCESS ;
1999-10-28 02:30:41 +08:00
}
2002-08-10 06:29:58 +08:00
}
/* }}} */
2010-05-31 18:29:43 +08:00
/* {{{ php_output_handler_alias_ctor_t php_output_handler_alias(zval *name TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Get an internal output handler for a user handler if it exists */
2010-05-31 18:29:43 +08:00
PHPAPI php_output_handler_alias_ctor_t * php_output_handler_alias ( const char * name , size_t name_len TSRMLS_DC )
2002-08-10 06:29:58 +08:00
{
2010-05-31 18:29:43 +08:00
php_output_handler_alias_ctor_t * func = NULL ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
zend_hash_find ( & php_output_handler_aliases , name , name_len + 1 , ( void * ) & func ) ;
return func ;
1999-10-28 02:30:41 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ SUCCESS|FAILURE php_output_handler_alias_register(zval *name, php_output_handler_alias_ctor_t func TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Registers an internal output handler as alias for a user handler */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_handler_alias_register ( const char * name , size_t name_len , php_output_handler_alias_ctor_t func TSRMLS_DC )
2002-08-05 11:09:42 +08:00
{
2010-05-31 18:29:43 +08:00
if ( ! EG ( current_module ) ) {
zend_error ( E_ERROR , " Cannot register an output handler alias outside of MINIT " ) ;
return FAILURE ;
2010-03-11 18:24:29 +08:00
}
2010-05-31 18:29:43 +08:00
return zend_hash_update ( & php_output_handler_aliases , name , name_len + 1 , & func , sizeof ( php_output_handler_alias_ctor_t * ) , NULL ) ;
2002-08-05 11:09:42 +08:00
}
/* }}} */
2010-05-31 18:29:43 +08:00
/* {{{ SUCCESS|FAILURE php_output_handler_hook(php_output_handler_hook_t type, void *arg TSMRLS_DC)
2010-12-03 23:34:24 +08:00
* Output handler hook for output handler functions to check / modify the current handlers abilities */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_handler_hook ( php_output_handler_hook_t type , void * arg TSRMLS_DC )
2002-08-05 11:09:42 +08:00
{
2010-05-31 18:29:43 +08:00
if ( OG ( running ) ) {
switch ( type ) {
case PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ :
* ( void * * * ) arg = & OG ( running ) - > opaq ;
return SUCCESS ;
case PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS :
* ( int * ) arg = OG ( running ) - > flags ;
return SUCCESS ;
case PHP_OUTPUT_HANDLER_HOOK_GET_LEVEL :
* ( int * ) arg = OG ( running ) - > level ;
2011-08-10 19:01:09 +08:00
return SUCCESS ;
2010-05-31 18:29:43 +08:00
case PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE :
OG ( running ) - > flags & = ~ ( PHP_OUTPUT_HANDLER_REMOVABLE | PHP_OUTPUT_HANDLER_CLEANABLE ) ;
return SUCCESS ;
case PHP_OUTPUT_HANDLER_HOOK_DISABLE :
OG ( running ) - > flags | = PHP_OUTPUT_HANDLER_DISABLED ;
return SUCCESS ;
default :
2010-12-03 23:34:24 +08:00
break ;
2010-05-31 18:29:43 +08:00
}
}
return FAILURE ;
2002-08-05 11:09:42 +08:00
}
/* }}} */
2010-05-31 18:29:43 +08:00
/* {{{ void php_output_handler_dtor(php_output_handler *handler TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Destroy an output handler */
2010-05-31 18:29:43 +08:00
PHPAPI void php_output_handler_dtor ( php_output_handler * handler TSRMLS_DC )
2002-08-06 02:54:53 +08:00
{
2010-05-31 18:29:43 +08:00
STR_FREE ( handler - > name ) ;
STR_FREE ( handler - > buffer . data ) ;
if ( handler - > flags & PHP_OUTPUT_HANDLER_USER ) {
zval_ptr_dtor ( & handler - > func . user - > zoh ) ;
efree ( handler - > func . user ) ;
2002-08-06 02:54:53 +08:00
}
2010-05-31 18:29:43 +08:00
if ( handler - > dtor & & handler - > opaq ) {
handler - > dtor ( handler - > opaq TSRMLS_CC ) ;
2002-08-06 02:54:53 +08:00
}
2010-05-31 18:29:43 +08:00
memset ( handler , 0 , sizeof ( * handler ) ) ;
2002-08-06 02:54:53 +08:00
}
/* }}} */
2010-05-31 18:29:43 +08:00
/* {{{ void php_output_handler_free(php_output_handler **handler TSMRLS_DC)
2010-12-03 23:34:24 +08:00
* Destroy and free an output handler */
2010-05-31 18:29:43 +08:00
PHPAPI void php_output_handler_free ( php_output_handler * * h TSRMLS_DC )
2010-03-11 18:24:29 +08:00
{
2010-05-31 18:29:43 +08:00
if ( * h ) {
php_output_handler_dtor ( * h TSRMLS_CC ) ;
efree ( * h ) ;
* h = NULL ;
2010-03-11 18:24:29 +08:00
}
}
/* }}} */
2000-11-24 02:43:18 +08:00
2010-05-31 18:29:43 +08:00
/* void php_output_set_implicit_flush(int enabled TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Enable or disable implicit flush */
2010-05-31 18:29:43 +08:00
PHPAPI void php_output_set_implicit_flush ( int flush TSRMLS_DC )
2010-03-11 18:24:29 +08:00
{
2010-05-31 18:29:43 +08:00
if ( flush ) {
OG ( flags ) | = PHP_OUTPUT_IMPLICITFLUSH ;
} else {
OG ( flags ) & = ~ PHP_OUTPUT_IMPLICITFLUSH ;
2000-11-24 02:43:18 +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
2010-05-31 18:29:43 +08:00
/* {{{ char *php_output_get_start_filename(TSRMLS_D)
2010-12-03 23:34:24 +08:00
* Get the file name where output has started */
2011-09-13 21:29:35 +08:00
PHPAPI const char * php_output_get_start_filename ( TSRMLS_D )
1999-10-28 02:30:41 +08:00
{
2010-05-31 18:29:43 +08:00
return OG ( output_start_filename ) ;
}
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ int php_output_get_start_lineno(TSRMLS_D)
2010-12-03 23:34:24 +08:00
* Get the line number where output has started */
2010-05-31 18:29:43 +08:00
PHPAPI int php_output_get_start_lineno ( TSRMLS_D )
{
return OG ( output_start_lineno ) ;
}
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static int php_output_lock_error(int op TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Checks whether an unallowed operation is attempted from within the output handler and issues a fatal error */
2010-05-31 18:29:43 +08:00
static inline int php_output_lock_error ( int op TSRMLS_DC )
{
/* if there's no ob active, ob has been stopped */
if ( op & & OG ( active ) & & OG ( running ) ) {
/* fatal error */
php_output_deactivate ( TSRMLS_C ) ;
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_ERROR , " Cannot use output buffering in output buffering display handlers " ) ;
return 1 ;
}
return 0 ;
}
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static php_output_context *php_output_context_init(php_output_context *context, int op TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Initialize a new output context */
2010-05-31 18:29:43 +08:00
static inline php_output_context * php_output_context_init ( php_output_context * context , int op TSRMLS_DC )
{
if ( ! context ) {
context = emalloc ( sizeof ( php_output_context ) ) ;
1999-10-28 02:30:41 +08:00
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
memset ( context , 0 , sizeof ( php_output_context ) ) ;
TSRMLS_SET_CTX ( context - > tsrm_ls ) ;
context - > op = op ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
return context ;
1999-10-28 02:30:41 +08:00
}
2010-03-11 18:24:29 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static void php_output_context_reset(php_output_context *context)
2010-12-03 23:34:24 +08:00
* Reset an output context */
2010-05-31 18:29:43 +08:00
static inline void php_output_context_reset ( php_output_context * context )
2010-03-11 18:24:29 +08:00
{
2010-05-31 18:29:43 +08:00
int op = context - > op ;
php_output_context_dtor ( context ) ;
memset ( context , 0 , sizeof ( php_output_context ) ) ;
context - > op = op ;
}
/* }}} */
1999-10-28 02:30:41 +08:00
2010-12-03 23:34:24 +08:00
/* {{{ static void php_output_context_feed(php_output_context *context, char *, size_t, size_t)
* Feed output contexts input buffer */
2010-11-03 16:35:16 +08:00
static inline void php_output_context_feed ( php_output_context * context , char * data , size_t size , size_t used , zend_bool free )
{
if ( context - > in . free & & context - > in . data ) {
efree ( context - > in . data ) ;
}
context - > in . data = data ;
context - > in . used = used ;
context - > in . free = free ;
context - > in . size = size ;
}
/* }}} */
2010-05-31 18:29:43 +08:00
/* {{{ static void php_output_context_swap(php_output_context *context)
2010-12-03 23:34:24 +08:00
* Swap output contexts buffers */
2010-05-31 18:29:43 +08:00
static inline void php_output_context_swap ( php_output_context * context )
{
if ( context - > in . free & & context - > in . data ) {
efree ( context - > in . data ) ;
}
context - > in . data = context - > out . data ;
context - > in . used = context - > out . used ;
context - > in . free = context - > out . free ;
context - > in . size = context - > out . size ;
context - > out . data = NULL ;
context - > out . used = 0 ;
2010-11-03 16:35:16 +08:00
context - > out . free = 0 ;
2010-05-31 18:29:43 +08:00
context - > out . size = 0 ;
}
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static void php_output_context_pass(php_output_context *context)
2010-12-03 23:34:24 +08:00
* Pass input to output buffer */
2010-05-31 18:29:43 +08:00
static inline void php_output_context_pass ( php_output_context * context )
{
context - > out . data = context - > in . data ;
context - > out . used = context - > in . used ;
context - > out . size = context - > in . size ;
context - > out . free = context - > in . free ;
context - > in . data = NULL ;
context - > in . used = 0 ;
2010-11-03 16:35:16 +08:00
context - > in . free = 0 ;
2010-05-31 18:29:43 +08:00
context - > in . size = 0 ;
}
/* }}} */
2010-03-12 18:28:59 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static void php_output_context_dtor(php_output_context *context)
2010-12-03 23:34:24 +08:00
* Destroy the contents of an output context */
2010-05-31 18:29:43 +08:00
static inline void php_output_context_dtor ( php_output_context * context )
{
if ( context - > in . free & & context - > in . data ) {
efree ( context - > in . data ) ;
context - > in . data = NULL ;
}
if ( context - > out . free & & context - > out . data ) {
efree ( context - > out . data ) ;
context - > out . data = NULL ;
2010-03-11 18:24:29 +08:00
}
2000-08-25 11:10:42 +08:00
}
2010-05-31 18:29:43 +08:00
/* }}} */
2000-08-25 11:10:42 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static php_output_handler *php_output_handler_init(zval *name, size_t chunk_size, int flags TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Allocates and initializes a php_output_handler structure */
2010-05-31 18:29:43 +08:00
static inline php_output_handler * php_output_handler_init ( const char * name , size_t name_len , size_t chunk_size , int flags TSRMLS_DC )
{
php_output_handler * handler ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
handler = ecalloc ( 1 , sizeof ( php_output_handler ) ) ;
handler - > name = estrndup ( name , name_len ) ;
handler - > name_len = name_len ;
handler - > size = chunk_size ;
handler - > flags = flags ;
handler - > buffer . size = PHP_OUTPUT_HANDLER_INITBUF_SIZE ( chunk_size ) ;
handler - > buffer . data = emalloc ( handler - > buffer . size ) ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
return handler ;
}
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static int php_output_handler_appen(php_output_handler *handler, const php_output_buffer *buf TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Appends input to the output handlers buffer and indicates whether the buffer does not have to be processed by the output handler */
2010-05-31 18:29:43 +08:00
static inline int php_output_handler_append ( php_output_handler * handler , const php_output_buffer * buf TSRMLS_DC )
2010-03-11 18:24:29 +08:00
{
2010-05-31 18:29:43 +08:00
if ( buf - > used ) {
OG ( flags ) | = PHP_OUTPUT_WRITTEN ;
/* store it away */
if ( ( handler - > buffer . size - handler - > buffer . used ) < = buf - > used ) {
size_t grow_int = PHP_OUTPUT_HANDLER_INITBUF_SIZE ( handler - > size ) ;
size_t grow_buf = PHP_OUTPUT_HANDLER_INITBUF_SIZE ( buf - > used - ( handler - > buffer . size - handler - > buffer . used ) ) ;
size_t grow_max = MAX ( grow_int , grow_buf ) ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
handler - > buffer . data = erealloc ( handler - > buffer . data , handler - > buffer . size + grow_max ) ;
handler - > buffer . size + = grow_max ;
}
memcpy ( handler - > buffer . data + handler - > buffer . used , buf - > data , buf - > used ) ;
handler - > buffer . used + = buf - > used ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
/* chunked buffering */
if ( handler - > size & & ( handler - > buffer . used > = handler - > size ) ) {
/* store away errors and/or any intermediate output */
return OG ( running ) ? 1 : 0 ;
}
2010-03-11 18:24:29 +08:00
}
2010-05-31 18:29:43 +08:00
return 1 ;
2010-03-11 18:24:29 +08:00
}
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static php_output_handler_status_t php_output_handler_op(php_output_handler *handler, php_output_context *context)
2010-12-03 23:34:24 +08:00
* Output handler operation dispatcher , applying context op to the php_output_handler handler */
2010-05-31 18:29:43 +08:00
static inline php_output_handler_status_t php_output_handler_op ( php_output_handler * handler , php_output_context * context )
1999-10-28 02:30:41 +08:00
{
2010-05-31 18:29:43 +08:00
php_output_handler_status_t status ;
int original_op = context - > op ;
PHP_OUTPUT_TSRMLS ( context ) ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
# if PHP_OUTPUT_DEBUG
fprintf ( stderr , " >>> op(%d, "
" handler=%p, "
" name=%s, "
" flags=%d, "
" buffer.data=%s, "
" buffer.used=%zu, "
" buffer.size=%zu, "
" in.data=%s, "
" in.used=%zu) \n " ,
context - > op ,
handler ,
handler - > name ,
handler - > flags ,
handler - > buffer . used ? handler - > buffer . data : " " ,
handler - > buffer . used ,
handler - > buffer . size ,
context - > in . used ? context - > in . data : " " ,
context - > in . used
) ;
# endif
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( php_output_lock_error ( context - > op TSRMLS_CC ) ) {
/* fatal error */
return PHP_OUTPUT_HANDLER_FAILURE ;
2010-03-11 18:24:29 +08:00
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
/* storable? */
if ( php_output_handler_append ( handler , & context - > in TSRMLS_CC ) & & ! context - > op ) {
status = PHP_OUTPUT_HANDLER_NO_DATA ;
} else {
/* need to start? */
if ( ! ( handler - > flags & PHP_OUTPUT_HANDLER_STARTED ) ) {
context - > op | = PHP_OUTPUT_HANDLER_START ;
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
OG ( running ) = handler ;
if ( handler - > flags & PHP_OUTPUT_HANDLER_USER ) {
zval * retval = NULL , * ob_data , * ob_mode ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
MAKE_STD_ZVAL ( ob_data ) ;
ZVAL_STRINGL ( ob_data , handler - > buffer . data , handler - > buffer . used , 1 ) ;
MAKE_STD_ZVAL ( ob_mode ) ;
ZVAL_LONG ( ob_mode , ( long ) context - > op ) ;
zend_fcall_info_argn ( & handler - > func . user - > fci TSRMLS_CC , 2 , & ob_data , & ob_mode ) ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
# define PHP_OUTPUT_USER_SUCCESS(retval) (retval && !(Z_TYPE_P(retval) == IS_BOOL && Z_BVAL_P(retval)==0))
if ( SUCCESS = = zend_fcall_info_call ( & handler - > func . user - > fci , & handler - > func . user - > fcc , & retval , NULL TSRMLS_CC ) & & PHP_OUTPUT_USER_SUCCESS ( retval ) ) {
/* user handler may have returned TRUE */
status = PHP_OUTPUT_HANDLER_NO_DATA ;
if ( Z_TYPE_P ( retval ) ! = IS_BOOL ) {
convert_to_string_ex ( & retval ) ;
if ( Z_STRLEN_P ( retval ) ) {
context - > out . data = estrndup ( Z_STRVAL_P ( retval ) , Z_STRLEN_P ( retval ) ) ;
context - > out . used = Z_STRLEN_P ( retval ) ;
context - > out . free = 1 ;
status = PHP_OUTPUT_HANDLER_SUCCESS ;
}
}
} else {
/* call failed, pass internal buffer along */
status = PHP_OUTPUT_HANDLER_FAILURE ;
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
zend_fcall_info_argn ( & handler - > func . user - > fci TSRMLS_CC , 0 ) ;
zval_ptr_dtor ( & ob_data ) ;
zval_ptr_dtor ( & ob_mode ) ;
if ( retval ) {
zval_ptr_dtor ( & retval ) ;
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
} else {
2010-11-03 16:35:16 +08:00
php_output_context_feed ( context , handler - > buffer . data , handler - > buffer . size , handler - > buffer . used , 0 ) ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( SUCCESS = = handler - > func . internal ( & handler - > opaq , context ) ) {
if ( context - > out . used ) {
status = PHP_OUTPUT_HANDLER_SUCCESS ;
} else {
status = PHP_OUTPUT_HANDLER_NO_DATA ;
}
} else {
status = PHP_OUTPUT_HANDLER_FAILURE ;
}
}
handler - > flags | = PHP_OUTPUT_HANDLER_STARTED ;
OG ( running ) = NULL ;
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
switch ( status ) {
case PHP_OUTPUT_HANDLER_FAILURE :
/* disable this handler */
handler - > flags | = PHP_OUTPUT_HANDLER_DISABLED ;
/* discard any output */
if ( context - > out . data & & context - > out . free ) {
efree ( context - > out . data ) ;
}
/* returns handlers buffer */
context - > out . data = handler - > buffer . data ;
context - > out . used = handler - > buffer . used ;
context - > out . free = 1 ;
handler - > buffer . data = NULL ;
handler - > buffer . used = 0 ;
handler - > buffer . size = 0 ;
break ;
case PHP_OUTPUT_HANDLER_SUCCESS :
/* no more buffered data */
handler - > buffer . used = 0 ;
break ;
case PHP_OUTPUT_HANDLER_NO_DATA :
/* handler ate all */
php_output_context_reset ( context ) ;
break ;
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
context - > op = original_op ;
return status ;
1999-10-28 02:30:41 +08:00
}
2010-03-11 18:24:29 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static void php_output_op(int op, const char *str, size_t len TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Output op dispatcher , passes input and output handlers output through the output handler stack until it gets written to the SAPI */
2010-05-31 18:29:43 +08:00
static inline void php_output_op ( int op , const char * str , size_t len TSRMLS_DC )
2010-03-11 18:24:29 +08:00
{
2010-05-31 18:29:43 +08:00
php_output_context context ;
php_output_handler * * active ;
int obh_cnt ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( php_output_lock_error ( op TSRMLS_CC ) ) {
return ;
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
php_output_context_init ( & context , op TSRMLS_CC ) ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
/*
* broken up for better performance :
* - apply op to the one active handler ; note that OG ( active ) might be popped off the stack on a flush
* - or apply op to the handler stack
*/
2010-08-27 14:09:18 +08:00
if ( OG ( active ) & & ( obh_cnt = zend_stack_count ( & OG ( handlers ) ) ) ) {
2010-05-31 18:29:43 +08:00
context . in . data = ( char * ) str ;
context . in . used = len ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( obh_cnt > 1 ) {
2010-08-27 14:09:18 +08:00
zend_stack_apply_with_argument ( & OG ( handlers ) , ZEND_STACK_APPLY_TOPDOWN , php_output_stack_apply_op , & context ) ;
} else if ( ( SUCCESS = = zend_stack_top ( & OG ( handlers ) , ( void * ) & active ) ) & & ( ! ( ( * active ) - > flags & PHP_OUTPUT_HANDLER_DISABLED ) ) ) {
2010-05-31 18:29:43 +08:00
php_output_handler_op ( * active , & context ) ;
} else {
php_output_context_pass ( & context ) ;
}
} else {
context . out . data = ( char * ) str ;
context . out . used = len ;
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( context . out . data & & context . out . used ) {
# if PHP_OUTPUT_DEBUG
fprintf ( stderr , " ::: sapi_write('%s', %zu) \n " , context . out . data , context . out . used ) ;
# endif
if ( ! SG ( headers_sent ) & & php_header ( TSRMLS_C ) ) {
if ( zend_is_compiling ( TSRMLS_C ) ) {
OG ( output_start_filename ) = zend_get_compiled_filename ( TSRMLS_C ) ;
OG ( output_start_lineno ) = zend_get_compiled_lineno ( TSRMLS_C ) ;
} else if ( zend_is_executing ( TSRMLS_C ) ) {
OG ( output_start_filename ) = zend_get_executed_filename ( TSRMLS_C ) ;
OG ( output_start_lineno ) = zend_get_executed_lineno ( TSRMLS_C ) ;
}
# if PHP_OUTPUT_DEBUG
fprintf ( stderr , " !!! output started at: %s (%d) \n " , OG ( output_start_filename ) , OG ( output_start_lineno ) ) ;
# endif
}
sapi_module . ub_write ( context . out . data , context . out . used TSRMLS_CC ) ;
if ( OG ( flags ) & PHP_OUTPUT_IMPLICITFLUSH ) {
sapi_flush ( TSRMLS_C ) ;
}
OG ( flags ) | = PHP_OUTPUT_SENT ;
}
php_output_context_dtor ( & context ) ;
2010-03-11 18:24:29 +08:00
}
2010-05-31 18:29:43 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static int php_output_stack_apply_op(void *h, void *c)
2010-12-03 23:34:24 +08:00
* Operation callback for the stack apply function */
2010-05-31 18:29:43 +08:00
static int php_output_stack_apply_op ( void * h , void * c )
2010-03-11 18:24:29 +08:00
{
2010-05-31 18:29:43 +08:00
int was_disabled ;
php_output_handler_status_t status ;
php_output_handler * handler = * ( php_output_handler * * ) h ;
php_output_context * context = ( php_output_context * ) c ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( ( was_disabled = ( handler - > flags & PHP_OUTPUT_HANDLER_DISABLED ) ) ) {
status = PHP_OUTPUT_HANDLER_FAILURE ;
} else {
status = php_output_handler_op ( handler , context ) ;
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
/*
* handler ate all = > break
* handler returned data or failed resp . is disabled = > continue
*/
switch ( status ) {
case PHP_OUTPUT_HANDLER_NO_DATA :
return 1 ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
case PHP_OUTPUT_HANDLER_SUCCESS :
/* swap contexts buffers, unless this is the last handler in the stack */
if ( handler - > level ) {
php_output_context_swap ( context ) ;
}
return 0 ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
case PHP_OUTPUT_HANDLER_FAILURE :
default :
if ( was_disabled ) {
/* pass input along, if it's the last handler in the stack */
if ( ! handler - > level ) {
php_output_context_pass ( context ) ;
}
} else {
/* swap buffers, unless this is the last handler */
if ( handler - > level ) {
php_output_context_swap ( context ) ;
}
}
return 0 ;
}
}
/* }}} */
2010-03-12 18:28:59 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static int php_output_stack_apply_clean(void *h, void *c)
2010-12-03 23:34:24 +08:00
* Clean callback for the stack apply function */
2010-05-31 18:29:43 +08:00
static int php_output_stack_apply_clean ( void * h , void * c )
{
php_output_handler * handler = * ( php_output_handler * * ) h ;
php_output_context * context = ( php_output_context * ) c ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
handler - > buffer . used = 0 ;
php_output_handler_op ( handler , context ) ;
php_output_context_reset ( context ) ;
return 0 ;
}
/* }}} */
2010-11-03 16:35:16 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static int php_output_stack_apply_list(void *h, void *z)
2010-12-03 23:34:24 +08:00
* List callback for the stack apply function */
2010-05-31 18:29:43 +08:00
static int php_output_stack_apply_list ( void * h , void * z )
{
php_output_handler * handler = * ( php_output_handler * * ) h ;
zval * array = ( zval * ) z ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
add_next_index_stringl ( array , handler - > name , handler - > name_len , 1 ) ;
return 0 ;
}
/* }}} */
2010-03-12 18:28:59 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static int php_output_stack_apply_status(void *h, void *z)
2010-12-03 23:34:24 +08:00
* Status callback for the stack apply function */
2010-05-31 18:29:43 +08:00
static int php_output_stack_apply_status ( void * h , void * z )
{
php_output_handler * handler = * ( php_output_handler * * ) h ;
zval * array = ( zval * ) z ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
add_next_index_zval ( array , php_output_handler_status ( handler , NULL ) ) ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
return 0 ;
}
2010-03-12 18:28:59 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static zval *php_output_handler_status(php_output_handler *handler, zval *entry)
2010-12-03 23:34:24 +08:00
* Returns an array with the status of the output handler */
2010-05-31 18:29:43 +08:00
static inline zval * php_output_handler_status ( php_output_handler * handler , zval * entry )
{
if ( ! entry ) {
MAKE_STD_ZVAL ( entry ) ;
array_init ( entry ) ;
2000-01-14 01:54:51 +08:00
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
add_assoc_stringl ( entry , " name " , handler - > name , handler - > name_len , 1 ) ;
add_assoc_long ( entry , " type " , ( long ) ( handler - > flags & 0xf ) ) ;
add_assoc_long ( entry , " flags " , ( long ) handler - > flags ) ;
add_assoc_long ( entry , " level " , ( long ) handler - > level ) ;
add_assoc_long ( entry , " chunk_size " , ( long ) handler - > size ) ;
add_assoc_long ( entry , " buffer_size " , ( long ) handler - > buffer . size ) ;
add_assoc_long ( entry , " buffer_used " , ( long ) handler - > buffer . used ) ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
return entry ;
1999-10-28 02:30:41 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static int php_output_stack_pop(int flags TSRMLS_DC)
2010-12-03 23:34:24 +08:00
* Pops an output handler off the stack */
2010-05-31 18:29:43 +08:00
static inline int php_output_stack_pop ( int flags TSRMLS_DC )
1999-10-28 02:30:41 +08:00
{
2010-05-31 18:29:43 +08:00
php_output_context context ;
php_output_handler * * current , * orphan = OG ( active ) ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( ! orphan ) {
if ( ! ( flags & PHP_OUTPUT_POP_SILENT ) ) {
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to %s buffer. No buffer to %s " , ( flags & PHP_OUTPUT_POP_DISCARD ) ? " discard " : " send " , ( flags & PHP_OUTPUT_POP_DISCARD ) ? " discard " : " send " ) ;
}
return 0 ;
} else if ( ! ( flags & PHP_OUTPUT_POP_FORCE ) & & ! ( orphan - > flags & PHP_OUTPUT_HANDLER_REMOVABLE ) ) {
if ( ! ( flags & PHP_OUTPUT_POP_SILENT ) ) {
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to %s buffer of %s (%d) " , ( flags & PHP_OUTPUT_POP_DISCARD ) ? " discard " : " send " , orphan - > name , orphan - > level ) ;
}
return 0 ;
} else {
php_output_context_init ( & context , PHP_OUTPUT_HANDLER_FINAL TSRMLS_CC ) ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
/* don't run the output handler if it's disabled */
if ( ! ( orphan - > flags & PHP_OUTPUT_HANDLER_DISABLED ) ) {
/* didn't it start yet? */
if ( ! ( orphan - > flags & PHP_OUTPUT_HANDLER_STARTED ) ) {
context . op | = PHP_OUTPUT_HANDLER_START ;
}
/* signal that we're cleaning up */
if ( flags & PHP_OUTPUT_POP_DISCARD ) {
context . op | = PHP_OUTPUT_HANDLER_CLEAN ;
orphan - > buffer . used = 0 ;
}
php_output_handler_op ( orphan , & context ) ;
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
/* pop it off the stack */
2010-08-27 14:09:18 +08:00
zend_stack_del_top ( & OG ( handlers ) ) ;
if ( SUCCESS = = zend_stack_top ( & OG ( handlers ) , ( void * ) & current ) ) {
2010-05-31 18:29:43 +08:00
OG ( active ) = * current ;
} else {
OG ( active ) = NULL ;
2004-10-20 23:31:06 +08:00
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
/* pass output along */
if ( context . out . data & & context . out . used & & ! ( flags & PHP_OUTPUT_POP_DISCARD ) ) {
php_output_write ( context . out . data , context . out . used TSRMLS_CC ) ;
2000-02-04 22:54:30 +08:00
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
/* destroy the handler (after write!) */
php_output_handler_free ( & orphan TSRMLS_CC ) ;
php_output_context_dtor ( & context ) ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
return 1 ;
}
}
/* }}} */
2000-02-04 22:54:30 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static SUCCESS|FAILURE php_output_handler_compat_func(void *ctx, php_output_context *)
2010-12-03 23:34:24 +08:00
* php_output_handler_context_func_t for php_output_handler_func_t output handlers */
2010-05-31 18:29:43 +08:00
static int php_output_handler_compat_func ( void * * handler_context , php_output_context * output_context )
{
php_output_handler_func_t func = * ( php_output_handler_func_t * ) handler_context ;
PHP_OUTPUT_TSRMLS ( output_context ) ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( func ) {
2010-06-01 21:16:33 +08:00
uint safe_out_len ;
2010-12-03 23:34:24 +08:00
2010-06-01 21:16:33 +08:00
func ( output_context - > in . data , output_context - > in . used , & output_context - > out . data , & safe_out_len , output_context - > op TSRMLS_CC ) ;
output_context - > out . used = safe_out_len ;
2010-05-31 18:29:43 +08:00
output_context - > out . free = 1 ;
return SUCCESS ;
1999-10-28 02:30:41 +08:00
}
2010-05-31 18:29:43 +08:00
return FAILURE ;
}
/* }}} */
/* {{{ static SUCCESS|FAILURE php_output_handler_default_func(void *ctx, php_output_context *)
2010-12-03 23:34:24 +08:00
* Default output handler */
2010-05-31 18:29:43 +08:00
static int php_output_handler_default_func ( void * * handler_context , php_output_context * output_context )
{
2010-11-03 16:35:16 +08:00
php_output_context_pass ( output_context ) ;
2010-05-31 18:29:43 +08:00
return SUCCESS ;
}
/* }}} */
1999-10-28 02:30:41 +08:00
2010-05-31 18:29:43 +08:00
/* {{{ static SUCCESS|FAILURE php_output_handler_devnull_func(void *ctx, php_output_context *)
2010-12-03 23:34:24 +08:00
* Null output handler */
2010-05-31 18:29:43 +08:00
static int php_output_handler_devnull_func ( void * * handler_context , php_output_context * output_context )
{
return SUCCESS ;
1999-10-28 02:30:41 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
/*
2010-05-31 18:29:43 +08:00
* USERLAND ( nearly 1 : 1 of old output . c )
1999-10-28 02:30:41 +08:00
*/
2010-05-31 18:29:43 +08:00
/* {{{ proto bool ob_start([string|array user_function [, int chunk_size [, int flags]]])
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 )
{
2010-05-31 18:29:43 +08:00
zval * output_handler = NULL ;
long chunk_size = 0 ;
long flags = PHP_OUTPUT_HANDLER_STDFLAGS ;
2010-12-03 23:34:24 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " |z/ll " , & output_handler , & chunk_size , & flags ) = = FAILURE ) {
return ;
2002-10-07 19:21:06 +08:00
}
2010-03-12 18:28:59 +08:00
2010-12-03 23:34:24 +08:00
if ( chunk_size < 0 ) {
2003-04-04 02:19:15 +08:00
chunk_size = 0 ;
2010-12-03 23:34:24 +08:00
}
2010-03-12 18:28:59 +08:00
2010-12-03 23:34:24 +08:00
if ( php_output_start_user ( output_handler , chunk_size , flags TSRMLS_CC ) = = FAILURE ) {
2010-05-31 18:29:43 +08:00
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to create buffer " ) ;
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
2010-03-12 18:28:59 +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 )
{
2008-03-11 06:15:36 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
2002-10-07 19:21:06 +08:00
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( ! OG ( active ) ) {
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 ;
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( SUCCESS ! = php_output_flush ( TSRMLS_C ) ) {
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to flush buffer of %s (%d) " , OG ( active ) - > name , OG ( active ) - > level ) ;
2009-02-13 19:48:17 +08:00
RETURN_FALSE ;
}
2002-03-01 11:05:50 +08:00
RETURN_TRUE ;
2001-11-30 18:48:38 +08:00
}
/* }}} */
2010-03-12 18:28:59 +08:00
/* {{{ proto bool ob_clean(void)
2002-03-01 11:05:50 +08:00
Clean ( delete ) the current output buffer */
2001-11-30 18:48:38 +08:00
PHP_FUNCTION ( ob_clean )
{
2008-03-11 06:15:36 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
2002-10-07 19:21:06 +08:00
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( ! OG ( active ) ) {
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 ;
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( SUCCESS ! = php_output_clean ( TSRMLS_C ) ) {
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to delete buffer of %s (%d) " , OG ( active ) - > name , OG ( active ) - > level ) ;
2002-03-01 11:05:50 +08:00
RETURN_FALSE ;
}
RETURN_TRUE ;
2001-11-30 18:48:38 +08:00
}
/* }}} */
2010-03-12 18:28:59 +08:00
/* {{{ proto bool ob_end_flush(void)
2002-03-01 11:05:50 +08:00
Flush ( send ) the output buffer , and delete current output buffer */
1999-10-28 02:30:41 +08:00
PHP_FUNCTION ( ob_end_flush )
{
2008-03-11 06:15:36 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
2002-10-07 19:21:06 +08:00
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( ! OG ( active ) ) {
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to delete and flush buffer. No buffer to delete or flush " ) ;
2010-03-12 18:28:59 +08:00
RETURN_FALSE ;
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
RETURN_BOOL ( SUCCESS = = php_output_end ( TSRMLS_C ) ) ;
1999-10-28 02:30:41 +08:00
}
2000-04-19 03:18:47 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2010-03-12 18:28:59 +08:00
/* {{{ proto bool ob_end_clean(void)
2002-03-01 11:05:50 +08:00
Clean the output buffer , and delete current output buffer */
1999-10-28 02:30:41 +08:00
PHP_FUNCTION ( ob_end_clean )
{
2008-03-11 06:15:36 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
2002-10-07 19:21:06 +08:00
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( ! OG ( active ) ) {
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to delete buffer. No buffer to delete " ) ;
2010-03-12 18:28:59 +08:00
RETURN_FALSE ;
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
RETURN_BOOL ( SUCCESS = = php_output_discard ( TSRMLS_C ) ) ;
1999-10-28 02:30:41 +08:00
}
2000-04-19 03:18:47 +08:00
/* }}} */
1999-10-28 02:30:41 +08:00
2010-03-12 18:28:59 +08:00
/* {{{ proto bool ob_get_flush(void)
2002-10-03 09:36:44 +08:00
Get current buffer contents , flush ( send ) the output buffer , and delete current output buffer */
PHP_FUNCTION ( ob_get_flush )
{
2008-03-11 06:15:36 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
2002-10-07 19:21:06 +08:00
}
2010-12-03 23:34:24 +08:00
if ( php_output_get_contents ( return_value TSRMLS_CC ) = = FAILURE ) {
2010-05-31 18:29:43 +08:00
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to delete and flush buffer. No buffer to delete or flush " ) ;
2010-03-12 18:28:59 +08:00
RETURN_FALSE ;
2002-10-03 09:36:44 +08:00
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( SUCCESS ! = php_output_end ( TSRMLS_C ) ) {
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to delete buffer of %s (%d) " , OG ( active ) - > name , OG ( active ) - > level ) ;
2010-03-12 18:28:59 +08:00
}
2002-10-03 09:36:44 +08:00
}
/* }}} */
2010-03-12 18:28:59 +08:00
/* {{{ proto bool ob_get_clean(void)
2002-10-03 09:36:44 +08:00
Get current buffer contents and delete current output buffer */
PHP_FUNCTION ( ob_get_clean )
{
2008-03-11 06:15:36 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2010-12-03 23:34:24 +08:00
2011-12-26 13:01:46 +08:00
if ( ! OG ( active ) ) {
RETURN_FALSE ;
}
2010-12-03 23:34:24 +08:00
if ( php_output_get_contents ( return_value TSRMLS_CC ) = = FAILURE ) {
2010-05-31 18:29:43 +08:00
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to delete buffer. No buffer to delete " ) ;
2010-03-12 18:28:59 +08:00
RETURN_FALSE ;
2002-10-03 09:36:44 +08:00
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( SUCCESS ! = php_output_discard ( TSRMLS_C ) ) {
php_error_docref ( " ref.outcontrol " TSRMLS_CC , E_NOTICE , " failed to delete buffer of %s (%d) " , OG ( active ) - > name , OG ( active ) - > level ) ;
2010-03-12 18:28:59 +08:00
}
2002-10-03 09:36:44 +08:00
}
/* }}} */
2010-03-12 18:28:59 +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 )
{
2008-03-11 06:15:36 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
2002-10-07 19:21:06 +08:00
}
2010-12-03 23:34:24 +08:00
if ( php_output_get_contents ( 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
2010-03-12 18:28: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 )
{
2008-03-11 06:15:36 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
2002-10-07 19:21:06 +08:00
}
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
RETURN_LONG ( php_output_get_level ( TSRMLS_C ) ) ;
2001-12-03 15:43:53 +08:00
}
/* }}} */
2010-03-12 18:28:59 +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 )
{
2008-03-11 06:15:36 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
2002-10-07 19:21:06 +08:00
}
2010-12-03 23:34:24 +08:00
if ( php_output_get_length ( return_value TSRMLS_CC ) = = FAILURE ) {
2000-08-25 11:10:42 +08:00
RETURN_FALSE ;
}
}
/* }}} */
2010-05-31 18:29:43 +08:00
/* {{{ proto false|array ob_list_handlers()
2010-12-03 23:34:24 +08:00
List all output_buffers in an array */
2010-05-31 18:29:43 +08:00
PHP_FUNCTION ( ob_list_handlers )
2002-03-01 11:05:50 +08:00
{
2010-05-31 18:29:43 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2002-03-01 11:05:50 +08:00
2010-05-31 18:29:43 +08:00
array_init ( return_value ) ;
2002-03-01 17:29:32 +08:00
2010-05-31 18:29:43 +08:00
if ( ! OG ( active ) ) {
return ;
2010-03-12 18:28:59 +08:00
}
2010-12-03 23:34:24 +08:00
2010-08-27 14:09:18 +08:00
zend_stack_apply_with_argument ( & OG ( handlers ) , ZEND_STACK_APPLY_BOTTOMUP , php_output_stack_apply_list , return_value ) ;
2002-03-01 11:05:50 +08:00
}
2002-10-03 12:17:41 +08:00
/* }}} */
2002-03-01 11:05:50 +08:00
2010-03-12 18:28:59 +08:00
/* {{{ proto false|array ob_get_status([bool full_status])
2002-08-10 06:29:58 +08:00
Return the status of the active or all output buffers */
2002-03-01 11:05:50 +08:00
PHP_FUNCTION ( ob_get_status )
{
zend_bool full_status = 0 ;
2010-12-03 23:34:24 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " |b " , & full_status ) = = FAILURE ) {
return ;
2010-03-11 18:24:29 +08:00
}
2011-11-18 08:16:58 +08:00
array_init ( return_value ) ;
2010-12-03 23:34:24 +08:00
2010-05-31 18:29:43 +08:00
if ( ! OG ( active ) ) {
2011-11-18 08:16:58 +08:00
return ;
2010-05-31 18:29:43 +08:00
}
2010-12-03 23:34:24 +08:00
2002-03-01 11:05:50 +08:00
if ( full_status ) {
2010-08-27 14:09:18 +08:00
zend_stack_apply_with_argument ( & OG ( handlers ) , ZEND_STACK_APPLY_BOTTOMUP , php_output_stack_apply_status , return_value ) ;
2010-05-31 18:29:43 +08:00
} else {
php_output_handler_status ( OG ( active ) , return_value ) ;
2002-03-01 11:05:50 +08:00
}
}
/* }}} */
2010-03-12 18:28:59 +08:00
/* {{{ proto void ob_implicit_flush([int flag])
2000-04-19 04:00:21 +08:00
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 )
{
2008-07-15 16:50:04 +08:00
long flag = 1 ;
2010-12-03 23:34:24 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " |l " , & flag ) = = FAILURE ) {
return ;
2010-03-12 18:28:59 +08:00
}
2010-12-03 23:34:24 +08:00
php_output_set_implicit_flush ( flag TSRMLS_CC ) ;
2010-03-12 18:28:59 +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 ) {
2010-12-03 23:34:24 +08:00
return ;
2002-05-03 16:00:41 +08:00
}
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
2011-12-30 16:50:49 +08:00
/* {{{ php_output_handler* php_get_active_output_handler(TSRMLS_D)
* Get active output handler */
PHPAPI php_output_handler * php_get_active_output_handler ( TSRMLS_D )
{
return OG ( active ) ;
}
/* }}} */
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
*/