PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - main - output.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 543 661 82.1 %
Date: 2014-11-25 Functions: 70 80 87.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2014 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Zeev Suraski <zeev@zend.com>                                |
      16             :    |          Thies C. Arntzen <thies@thieso.net>                         |
      17             :    |          Marcus Boerger <helly@php.net>                              |
      18             :    | New API: Michael Wallner <mike@php.net>                              |
      19             :    +----------------------------------------------------------------------+
      20             : */
      21             : 
      22             : /* $Id$ */
      23             : 
      24             : #ifndef PHP_OUTPUT_DEBUG
      25             : # define PHP_OUTPUT_DEBUG 0
      26             : #endif
      27             : #ifndef PHP_OUTPUT_NOINLINE
      28             : # define PHP_OUTPUT_NOINLINE 0
      29             : #endif
      30             : 
      31             : #include "php.h"
      32             : #include "ext/standard/head.h"
      33             : #include "ext/standard/url_scanner_ex.h"
      34             : #include "SAPI.h"
      35             : #include "zend_stack.h"
      36             : #include "php_output.h"
      37             : 
      38             : ZEND_DECLARE_MODULE_GLOBALS(output);
      39             : 
      40             : const char php_output_default_handler_name[sizeof("default output handler")] = "default output handler";
      41             : const char php_output_devnull_handler_name[sizeof("null output handler")] = "null output handler";
      42             : 
      43             : #if PHP_OUTPUT_NOINLINE || PHP_OUTPUT_DEBUG
      44             : # undef inline
      45             : # define inline
      46             : #endif
      47             : 
      48             : /* {{{ aliases, conflict and reverse conflict hash tables */
      49             : static HashTable php_output_handler_aliases;
      50             : static HashTable php_output_handler_conflicts;
      51             : static HashTable php_output_handler_reverse_conflicts;
      52             : /* }}} */
      53             : 
      54             : /* {{{ forward declarations */
      55             : static inline int php_output_lock_error(int op TSRMLS_DC);
      56             : static inline void php_output_op(int op, const char *str, size_t len TSRMLS_DC);
      57             : 
      58             : static inline php_output_handler *php_output_handler_init(const char *name, size_t name_len, size_t chunk_size, int flags TSRMLS_DC);
      59             : static inline php_output_handler_status_t php_output_handler_op(php_output_handler *handler, php_output_context *context);
      60             : static inline int php_output_handler_append(php_output_handler *handler, const php_output_buffer *buf TSRMLS_DC);
      61             : static inline zval *php_output_handler_status(php_output_handler *handler, zval *entry);
      62             : 
      63             : static inline php_output_context *php_output_context_init(php_output_context *context, int op TSRMLS_DC);
      64             : static inline void php_output_context_reset(php_output_context *context);
      65             : static inline void php_output_context_swap(php_output_context *context);
      66             : static inline void php_output_context_dtor(php_output_context *context);
      67             : 
      68             : static inline int php_output_stack_pop(int flags TSRMLS_DC);
      69             : 
      70             : static int php_output_stack_apply_op(void *h, void *c);
      71             : static int php_output_stack_apply_clean(void *h, void *c);
      72             : static int php_output_stack_apply_list(void *h, void *z);
      73             : static int php_output_stack_apply_status(void *h, void *z);
      74             : 
      75             : static int php_output_handler_compat_func(void **handler_context, php_output_context *output_context);
      76             : static int php_output_handler_default_func(void **handler_context, php_output_context *output_context);
      77             : static int php_output_handler_devnull_func(void **handler_context, php_output_context *output_context);
      78             : /* }}} */
      79             : 
      80             : /* {{{ static void php_output_init_globals(zend_output_globals *G)
      81             :  * Initialize the module globals on MINIT */
      82       20225 : static inline void php_output_init_globals(zend_output_globals *G)
      83             : {
      84       20225 :         memset(G, 0, sizeof(*G));
      85       20225 : }
      86             : /* }}} */
      87             : 
      88             : /* {{{ stderr/stdout writer if not PHP_OUTPUT_ACTIVATED */
      89          62 : static int php_output_stdout(const char *str, size_t str_len)
      90             : {
      91          62 :         fwrite(str, 1, str_len, stdout);
      92          62 :         return str_len;
      93             : }
      94           0 : static int php_output_stderr(const char *str, size_t str_len)
      95             : {
      96           0 :         fwrite(str, 1, str_len, stderr);
      97             : /* See http://support.microsoft.com/kb/190351 */
      98             : #ifdef PHP_WIN32
      99             :         fflush(stderr);
     100             : #endif
     101           0 :         return str_len;
     102             : }
     103             : static int (*php_output_direct)(const char *str, size_t str_len) = php_output_stderr;
     104             : /* }}} */
     105             : 
     106             : /* {{{ void php_output_header(TSRMLS_D) */
     107      950838 : static void php_output_header(TSRMLS_D)
     108             : {
     109      950838 :         if (!SG(headers_sent)) {
     110       20009 :                 if (!OG(output_start_filename)) {
     111       20009 :                         if (zend_is_compiling(TSRMLS_C)) {
     112         229 :                                 OG(output_start_filename) = zend_get_compiled_filename(TSRMLS_C);
     113         229 :                                 OG(output_start_lineno) = zend_get_compiled_lineno(TSRMLS_C);
     114       19780 :                         } else if (zend_is_executing(TSRMLS_C)) {
     115       12842 :                                 OG(output_start_filename) = zend_get_executed_filename(TSRMLS_C);
     116       12842 :                                 OG(output_start_lineno) = zend_get_executed_lineno(TSRMLS_C);
     117             :                         }
     118             : #if PHP_OUTPUT_DEBUG
     119             :                         fprintf(stderr, "!!! output started at: %s (%d)\n", OG(output_start_filename), OG(output_start_lineno));
     120             : #endif
     121             :                 }
     122       20009 :                 if (!php_header(TSRMLS_C)) {
     123           0 :                         OG(flags) |= PHP_OUTPUT_DISABLED;
     124             :                 }
     125             :         }
     126      950838 : }
     127             : /* }}} */
     128             : 
     129             : /* {{{ void php_output_startup(void)
     130             :  * Set up module globals and initalize the conflict and reverse conflict hash tables */
     131       20225 : PHPAPI void php_output_startup(void)
     132             : {
     133       20225 :         ZEND_INIT_MODULE_GLOBALS(output, php_output_init_globals, NULL);
     134       20225 :         zend_hash_init(&php_output_handler_aliases, 0, NULL, NULL, 1);
     135       20225 :         zend_hash_init(&php_output_handler_conflicts, 0, NULL, NULL, 1);
     136       20225 :         zend_hash_init(&php_output_handler_reverse_conflicts, 0, NULL, (void (*)(void *)) zend_hash_destroy, 1);
     137       20225 :         php_output_direct = php_output_stdout;
     138       20225 : }
     139             : /* }}} */
     140             : 
     141             : /* {{{ void php_output_shutdown(void)
     142             :  * Destroy module globals and the conflict and reverse conflict hash tables */
     143       20264 : PHPAPI void php_output_shutdown(void)
     144             : {
     145       20264 :         php_output_direct = php_output_stderr;
     146       20264 :         zend_hash_destroy(&php_output_handler_aliases);
     147       20264 :         zend_hash_destroy(&php_output_handler_conflicts);
     148       20264 :         zend_hash_destroy(&php_output_handler_reverse_conflicts);
     149       20264 : }
     150             : /* }}} */
     151             : 
     152             : /* {{{ SUCCESS|FAILURE php_output_activate(TSRMLS_D)
     153             :  * Reset output globals and setup the output handler stack */
     154       20182 : PHPAPI int php_output_activate(TSRMLS_D)
     155             : {
     156             : #ifdef ZTS
     157             :         memset((*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(output_globals_id)], 0, sizeof(zend_output_globals));
     158             : #else
     159       20182 :         memset(&output_globals, 0, sizeof(zend_output_globals));
     160             : #endif
     161             : 
     162       20182 :         zend_stack_init(&OG(handlers));
     163       20182 :         OG(flags) |= PHP_OUTPUT_ACTIVATED;
     164             : 
     165       20182 :         return SUCCESS;
     166             : }
     167             : /* }}} */
     168             : 
     169             : /* {{{ void php_output_deactivate(TSRMLS_D)
     170             :  * Destroy the output handler stack */
     171       20226 : PHPAPI void php_output_deactivate(TSRMLS_D)
     172             : {
     173       20226 :         php_output_handler **handler = NULL;
     174             : 
     175       20226 :         php_output_header(TSRMLS_C);
     176             : 
     177       20226 :         OG(flags) ^= PHP_OUTPUT_ACTIVATED;
     178       20226 :         OG(active) = NULL;
     179       20226 :         OG(running) = NULL;
     180             : 
     181             :         /* release all output handlers */
     182       20226 :         if (OG(handlers).elements) {
     183        1633 :                 while (SUCCESS == zend_stack_top(&OG(handlers), (void *) &handler)) {
     184           3 :                         php_output_handler_free(handler TSRMLS_CC);
     185           3 :                         zend_stack_del_top(&OG(handlers));
     186             :                 }
     187         815 :                 zend_stack_destroy(&OG(handlers));
     188             :         }
     189             : 
     190       20226 : }
     191             : /* }}} */
     192             : 
     193             : /* {{{ void php_output_register_constants() */
     194       20225 : PHPAPI void php_output_register_constants(TSRMLS_D)
     195             : {
     196       20225 :         REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_START", PHP_OUTPUT_HANDLER_START, CONST_CS | CONST_PERSISTENT);
     197       20225 :         REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_WRITE", PHP_OUTPUT_HANDLER_WRITE, CONST_CS | CONST_PERSISTENT);
     198       20225 :         REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_FLUSH", PHP_OUTPUT_HANDLER_FLUSH, CONST_CS | CONST_PERSISTENT);
     199       20225 :         REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CLEAN", PHP_OUTPUT_HANDLER_CLEAN, CONST_CS | CONST_PERSISTENT);
     200       20225 :         REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_FINAL", PHP_OUTPUT_HANDLER_FINAL, CONST_CS | CONST_PERSISTENT);
     201       20225 :         REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CONT", PHP_OUTPUT_HANDLER_WRITE, CONST_CS | CONST_PERSISTENT);
     202       20225 :         REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_END", PHP_OUTPUT_HANDLER_FINAL, CONST_CS | CONST_PERSISTENT);
     203             : 
     204       20225 :         REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CLEANABLE", PHP_OUTPUT_HANDLER_CLEANABLE, CONST_CS | CONST_PERSISTENT);
     205       20225 :         REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_FLUSHABLE", PHP_OUTPUT_HANDLER_FLUSHABLE, CONST_CS | CONST_PERSISTENT);
     206       20225 :         REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_REMOVABLE", PHP_OUTPUT_HANDLER_REMOVABLE, CONST_CS | CONST_PERSISTENT);
     207       20225 :         REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_STDFLAGS", PHP_OUTPUT_HANDLER_STDFLAGS, CONST_CS | CONST_PERSISTENT);
     208       20225 :         REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_STARTED", PHP_OUTPUT_HANDLER_STARTED, CONST_CS | CONST_PERSISTENT);
     209       20225 :         REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_DISABLED", PHP_OUTPUT_HANDLER_DISABLED, CONST_CS | CONST_PERSISTENT);
     210       20225 : }
     211             : /* }}} */
     212             : 
     213             : /* {{{ void php_output_set_status(int status TSRMLS_DC)
     214             :  * Used by SAPIs to disable output */
     215           2 : PHPAPI void php_output_set_status(int status TSRMLS_DC)
     216             : {
     217           2 :         OG(flags) = (OG(flags) & ~0xf) | (status & 0xf);
     218           2 : }
     219             : /* }}} */
     220             : 
     221             : /* {{{ int php_output_get_status(TSRMLS_C)
     222             :  * Get output control status */
     223         255 : PHPAPI int php_output_get_status(TSRMLS_D)
     224             : {
     225         255 :         return (
     226         510 :                 OG(flags)
     227         255 :                 |       (OG(active) ? PHP_OUTPUT_ACTIVE : 0)
     228         255 :                 |       (OG(running)? PHP_OUTPUT_LOCKED : 0)
     229             :         ) & 0xff;
     230             : }
     231             : /* }}} */
     232             : 
     233             : /* {{{ int php_output_write_unbuffered(const char *str, size_t len TSRMLS_DC)
     234             :  * Unbuffered write */
     235        1440 : PHPAPI int php_output_write_unbuffered(const char *str, size_t len TSRMLS_DC)
     236             : {
     237             : #if PHP_DEBUG
     238             :         if (len > UINT_MAX) {
     239             :                 php_error(E_WARNING, "Attempt to output more than UINT_MAX bytes at once; "
     240             :                                 "output will be truncated %lu => %lu",
     241             :                                 (unsigned long) len, (unsigned long) (len % UINT_MAX));
     242             :         }
     243             : #endif
     244        1440 :         if (OG(flags) & PHP_OUTPUT_DISABLED) {
     245           0 :                 return 0;
     246             :         }
     247        1440 :         if (OG(flags) & PHP_OUTPUT_ACTIVATED) {
     248        1440 :                 return sapi_module.ub_write(str, len TSRMLS_CC);
     249             :         }
     250           0 :         return php_output_direct(str, len);
     251             : }
     252             : /* }}} */
     253             : 
     254             : /* {{{ int php_output_write(const char *str, size_t len TSRMLS_DC)
     255             :  * Buffered write */
     256     1661032 : PHPAPI int php_output_write(const char *str, size_t len TSRMLS_DC)
     257             : {
     258             : #if PHP_DEBUG
     259             :         if (len > UINT_MAX) {
     260             :                 php_error(E_WARNING, "Attempt to output more than UINT_MAX bytes at once; "
     261             :                                 "output will be truncated %lu => %lu",
     262             :                                 (unsigned long) len, (unsigned long) (len % UINT_MAX));
     263             :         }
     264             : #endif
     265     1661032 :         if (OG(flags) & PHP_OUTPUT_DISABLED) {
     266           0 :                 return 0;
     267             :         }
     268     1661032 :         if (OG(flags) & PHP_OUTPUT_ACTIVATED) {
     269     1660970 :                 php_output_op(PHP_OUTPUT_HANDLER_WRITE, str, len TSRMLS_CC);
     270     1660968 :                 return (int) len;
     271             :         }
     272          62 :         return php_output_direct(str, len);
     273             : }
     274             : /* }}} */
     275             : 
     276             : /* {{{ SUCCESS|FAILURE php_output_flush(TSRMLS_D)
     277             :  * Flush the most recent output handlers buffer */
     278          23 : PHPAPI int php_output_flush(TSRMLS_D)
     279             : {
     280             :         php_output_context context;
     281             : 
     282          23 :         if (OG(active) && (OG(active)->flags & PHP_OUTPUT_HANDLER_FLUSHABLE)) {
     283          21 :                 php_output_context_init(&context, PHP_OUTPUT_HANDLER_FLUSH TSRMLS_CC);
     284          21 :                 php_output_handler_op(OG(active), &context);
     285          21 :                 if (context.out.data && context.out.used) {
     286          19 :                         zend_stack_del_top(&OG(handlers));
     287          19 :                         php_output_write(context.out.data, context.out.used TSRMLS_CC);
     288          19 :                         zend_stack_push(&OG(handlers), &OG(active), sizeof(php_output_handler *));
     289             :                 }
     290          21 :                 php_output_context_dtor(&context);
     291          21 :                 return SUCCESS;
     292             :         }
     293           2 :         return FAILURE;
     294             : }
     295             : /* }}} */
     296             : 
     297             : /* {{{ void php_output_flush_all(TSRMLS_C)
     298             :  * Flush all output buffers subsequently */
     299           0 : PHPAPI void php_output_flush_all(TSRMLS_D)
     300             : {
     301           0 :         if (OG(active)) {
     302           0 :                 php_output_op(PHP_OUTPUT_HANDLER_FLUSH, NULL, 0 TSRMLS_CC);
     303             :         }
     304           0 : }
     305             : /* }}} */
     306             : 
     307             : /* {{{ SUCCESS|FAILURE php_output_clean(TSRMLS_D)
     308             :  * Cleans the most recent output handlers buffer if the handler is cleanable */
     309           8 : PHPAPI int php_output_clean(TSRMLS_D)
     310             : {
     311             :         php_output_context context;
     312             : 
     313           8 :         if (OG(active) && (OG(active)->flags & PHP_OUTPUT_HANDLER_CLEANABLE)) {
     314           7 :                 php_output_context_init(&context, PHP_OUTPUT_HANDLER_CLEAN TSRMLS_CC);
     315           7 :                 php_output_handler_op(OG(active), &context);
     316           7 :                 php_output_context_dtor(&context);
     317           7 :                 return SUCCESS;
     318             :         }
     319           1 :         return FAILURE;
     320             : }
     321             : /* }}} */
     322             : 
     323             : /* {{{ void php_output_clean_all(TSRMLS_D)
     324             :  * Cleans all output handler buffers, without regard whether the handler is cleanable */
     325           0 : PHPAPI void php_output_clean_all(TSRMLS_D)
     326             : {
     327             :         php_output_context context;
     328             : 
     329           0 :         if (OG(active)) {
     330           0 :                 php_output_context_init(&context, PHP_OUTPUT_HANDLER_CLEAN TSRMLS_CC);
     331           0 :                 zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_TOPDOWN, php_output_stack_apply_clean, &context);
     332             :         }
     333           0 : }
     334             : 
     335             : /* {{{ SUCCESS|FAILURE php_output_end(TSRMLS_D)
     336             :  * Finalizes the most recent output handler at pops it off the stack if the handler is removable */
     337         343 : PHPAPI int php_output_end(TSRMLS_D)
     338             : {
     339         343 :         if (php_output_stack_pop(PHP_OUTPUT_POP_TRY TSRMLS_CC)) {
     340         340 :                 return SUCCESS;
     341             :         }
     342           2 :         return FAILURE;
     343             : }
     344             : /* }}} */
     345             : 
     346             : /* {{{ void php_output_end_all(TSRMLS_D)
     347             :  * Finalizes all output handlers and ends output buffering without regard whether a handler is removable */
     348       20355 : PHPAPI void php_output_end_all(TSRMLS_D)
     349             : {
     350       20355 :         while (OG(active) && php_output_stack_pop(PHP_OUTPUT_POP_FORCE TSRMLS_CC));
     351       20222 : }
     352             : /* }}} */
     353             : 
     354             : /* {{{ SUCCESS|FAILURE php_output_discard(TSRMLS_D)
     355             :  * Discards the most recent output handlers buffer and pops it off the stack if the handler is removable */
     356        4494 : PHPAPI int php_output_discard(TSRMLS_D)
     357             : {
     358        4494 :         if (php_output_stack_pop(PHP_OUTPUT_POP_DISCARD|PHP_OUTPUT_POP_TRY TSRMLS_CC)) {
     359        4492 :                 return SUCCESS;
     360             :         }
     361           2 :         return FAILURE;
     362             : }
     363             : /* }}} */
     364             : 
     365             : /* {{{ void php_output_discard_all(TSRMLS_D)
     366             :  * Discard all output handlers and buffers without regard whether a handler is removable */
     367           0 : PHPAPI void php_output_discard_all(TSRMLS_D)
     368             : {
     369           0 :         while (OG(active)) {
     370           0 :                 php_output_stack_pop(PHP_OUTPUT_POP_DISCARD|PHP_OUTPUT_POP_FORCE TSRMLS_CC);
     371             :         }
     372           0 : }
     373             : /* }}} */
     374             : 
     375             : /* {{{ int php_output_get_level(TSRMLS_D)
     376             :  * Get output buffering level, ie. how many output handlers the stack contains */
     377        3731 : PHPAPI int php_output_get_level(TSRMLS_D)
     378             : {
     379        3731 :         return OG(active) ? zend_stack_count(&OG(handlers)) : 0;
     380             : }
     381             : /* }}} */
     382             : 
     383             : /* {{{ SUCCESS|FAILURE php_output_get_contents(zval *z TSRMLS_DC)
     384             :  * Get the contents of the active output handlers buffer */
     385        3959 : PHPAPI int php_output_get_contents(zval *p TSRMLS_DC)
     386             : {
     387        3959 :         if (OG(active)) {
     388        3953 :                 ZVAL_STRINGL(p, OG(active)->buffer.data, OG(active)->buffer.used, 1);
     389        3953 :                 return SUCCESS;
     390             :         } else {
     391           6 :                 ZVAL_NULL(p);
     392           6 :                 return FAILURE;
     393             :         }
     394             : }
     395             : 
     396             : /* {{{ SUCCESS|FAILURE php_output_get_length(zval *z TSRMLS_DC)
     397             :  * Get the length of the active output handlers buffer */
     398          22 : PHPAPI int php_output_get_length(zval *p TSRMLS_DC)
     399             : {
     400          22 :         if (OG(active)) {
     401          19 :                 ZVAL_LONG(p, OG(active)->buffer.used);
     402          19 :                 return SUCCESS;
     403             :         } else {
     404           3 :                 ZVAL_NULL(p);
     405           3 :                 return FAILURE;
     406             :         }
     407             : }
     408             : /* }}} */
     409             : 
     410             : /* {{{ php_output_handler* php_output_get_active_handler(TSRMLS_D)
     411             :  * Get active output handler */
     412           0 : PHPAPI php_output_handler* php_output_get_active_handler(TSRMLS_D)
     413             : {
     414           0 :         return OG(active);
     415             : }
     416             : /* }}} */
     417             : 
     418             : /* {{{ SUCCESS|FAILURE php_output_handler_start_default(TSRMLS_D)
     419             :  * Start a "default output handler" */
     420         820 : PHPAPI int php_output_start_default(TSRMLS_D)
     421             : {
     422             :         php_output_handler *handler;
     423             : 
     424         820 :         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);
     425         820 :         if (SUCCESS == php_output_handler_start(handler TSRMLS_CC)) {
     426         819 :                 return SUCCESS;
     427             :         }
     428           0 :         php_output_handler_free(&handler TSRMLS_CC);
     429           0 :         return FAILURE;
     430             : }
     431             : /* }}} */
     432             : 
     433             : /* {{{ SUCCESS|FAILURE php_output_handler_start_devnull(TSRMLS_D)
     434             :  * Start a "null output handler" */
     435           0 : PHPAPI int php_output_start_devnull(TSRMLS_D)
     436             : {
     437             :         php_output_handler *handler;
     438             : 
     439           0 :         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);
     440           0 :         if (SUCCESS == php_output_handler_start(handler TSRMLS_CC)) {
     441           0 :                 return SUCCESS;
     442             :         }
     443           0 :         php_output_handler_free(&handler TSRMLS_CC);
     444           0 :         return FAILURE;
     445             : }
     446             : /* }}} */
     447             : 
     448             : /* {{{ SUCCESS|FAILURE php_output_start_user(zval *handler, size_t chunk_size, int flags TSRMLS_DC)
     449             :  * Start a user level output handler */
     450        4138 : PHPAPI int php_output_start_user(zval *output_handler, size_t chunk_size, int flags TSRMLS_DC)
     451             : {
     452             :         php_output_handler *handler;
     453             : 
     454        4138 :         if (output_handler) {
     455         105 :                 handler = php_output_handler_create_user(output_handler, chunk_size, flags TSRMLS_CC);
     456             :         } else {
     457        4033 :                 handler = php_output_handler_create_internal(ZEND_STRL(php_output_default_handler_name), php_output_handler_default_func, chunk_size, flags TSRMLS_CC);
     458             :         }
     459        4138 :         if (SUCCESS == php_output_handler_start(handler TSRMLS_CC)) {
     460        4123 :                 return SUCCESS;
     461             :         }
     462          14 :         php_output_handler_free(&handler TSRMLS_CC);
     463          14 :         return FAILURE;
     464             : }
     465             : /* }}} */
     466             : 
     467             : /* {{{ SUCCESS|FAILURE php_output_start_internal(zval *name, php_output_handler_func_t handler, size_t chunk_size, int flags TSRMLS_DC)
     468             :  * Start an internal output handler that does not have to maintain a non-global state */
     469          10 : 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)
     470             : {
     471             :         php_output_handler *handler;
     472             : 
     473          10 :         handler = php_output_handler_create_internal(name, name_len, php_output_handler_compat_func, chunk_size, flags TSRMLS_CC);
     474          10 :         php_output_handler_set_context(handler, output_handler, NULL TSRMLS_CC);
     475          10 :         if (SUCCESS == php_output_handler_start(handler TSRMLS_CC)) {
     476          10 :                 return SUCCESS;
     477             :         }
     478           0 :         php_output_handler_free(&handler TSRMLS_CC);
     479           0 :         return FAILURE;
     480             : }
     481             : /* }}} */
     482             : 
     483             : /* {{{ php_output_handler *php_output_handler_create_user(zval *handler, size_t chunk_size, int flags TSRMLS_DC)
     484             :  * Create a user level output handler */
     485         105 : PHPAPI php_output_handler *php_output_handler_create_user(zval *output_handler, size_t chunk_size, int flags TSRMLS_DC)
     486             : {
     487         105 :         char *handler_name = NULL, *error = NULL;
     488         105 :         php_output_handler *handler = NULL;
     489         105 :         php_output_handler_alias_ctor_t *alias = NULL;
     490         105 :         php_output_handler_user_func_t *user = NULL;
     491             : 
     492         105 :         switch (Z_TYPE_P(output_handler)) {
     493             :                 case IS_NULL:
     494           0 :                         handler = php_output_handler_create_internal(ZEND_STRL(php_output_default_handler_name), php_output_handler_default_func, chunk_size, flags TSRMLS_CC);
     495           0 :                         break;
     496             :                 case IS_STRING:
     497          85 :                         if (Z_STRLEN_P(output_handler) && (alias = php_output_handler_alias(Z_STRVAL_P(output_handler), Z_STRLEN_P(output_handler) TSRMLS_CC))) {
     498          12 :                                 handler = (*alias)(Z_STRVAL_P(output_handler), Z_STRLEN_P(output_handler), chunk_size, flags TSRMLS_CC);
     499          12 :                                 break;
     500             :                         }
     501             :                 default:
     502          93 :                         user = ecalloc(1, sizeof(php_output_handler_user_func_t));
     503          93 :                         if (SUCCESS == zend_fcall_info_init(output_handler, 0, &user->fci, &user->fcc, &handler_name, &error TSRMLS_CC)) {
     504          80 :                                 handler = php_output_handler_init(handler_name, strlen(handler_name), chunk_size, (flags & ~0xf) | PHP_OUTPUT_HANDLER_USER TSRMLS_CC);
     505             :                                 Z_ADDREF_P(output_handler);
     506          80 :                                 user->zoh = output_handler;
     507          80 :                                 handler->func.user = user;
     508             :                         } else {
     509          13 :                                 efree(user);
     510             :                         }
     511          93 :                         if (error) {
     512          14 :                                 php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "%s", error);
     513          14 :                                 efree(error);
     514             :                         }
     515          93 :                         if (handler_name) {
     516          93 :                                 efree(handler_name);
     517             :                         }
     518             :         }
     519             : 
     520         105 :         return handler;
     521             : }
     522             : /* }}} */
     523             : 
     524             : /* {{{ 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)
     525             :  * Create an internal output handler that can maintain a non-global state */
     526        4888 : 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)
     527             : {
     528             :         php_output_handler *handler;
     529             : 
     530        4888 :         handler = php_output_handler_init(name, name_len, chunk_size, (flags & ~0xf) | PHP_OUTPUT_HANDLER_INTERNAL TSRMLS_CC);
     531        4888 :         handler->func.internal = output_handler;
     532             : 
     533        4888 :         return handler;
     534             : }
     535             : /* }}} */
     536             : 
     537             : /* {{{ void php_output_handler_set_context(php_output_handler *handler, void *opaq, void (*dtor)(void* TSRMLS_DC) TSRMLS_DC)
     538             :  * Set the context/state of an output handler. Calls the dtor of the previous context if there is one */
     539          30 : PHPAPI void php_output_handler_set_context(php_output_handler *handler, void *opaq, void (*dtor)(void* TSRMLS_DC) TSRMLS_DC)
     540             : {
     541          30 :         if (handler->dtor && handler->opaq) {
     542           0 :                 handler->dtor(handler->opaq TSRMLS_CC);
     543             :         }
     544          30 :         handler->dtor = dtor;
     545          30 :         handler->opaq = opaq;
     546          30 : }
     547             : /* }}} */
     548             : 
     549             : /* {{{ SUCCESS|FAILURE php_output_handler_start(php_output_handler *handler TSRMLS_DC)
     550             :  * Starts the set up output handler and pushes it on top of the stack. Checks for any conflicts regarding the output handler to start */
     551        4981 : PHPAPI int php_output_handler_start(php_output_handler *handler TSRMLS_DC)
     552             : {
     553             :         HashPosition pos;
     554             :         HashTable *rconflicts;
     555             :         php_output_handler_conflict_check_t *conflict;
     556             : 
     557        4981 :         if (php_output_lock_error(PHP_OUTPUT_HANDLER_START TSRMLS_CC) || !handler) {
     558          13 :                 return FAILURE;
     559             :         }
     560        4966 :         if (SUCCESS == zend_hash_find(&php_output_handler_conflicts, handler->name, handler->name_len+1, (void *) &conflict)) {
     561          22 :                 if (SUCCESS != (*conflict)(handler->name, handler->name_len TSRMLS_CC)) {
     562           1 :                         return FAILURE;
     563             :                 }
     564             :         }
     565        4965 :         if (SUCCESS == zend_hash_find(&php_output_handler_reverse_conflicts, handler->name, handler->name_len+1, (void *) &rconflicts)) {
     566           0 :                 for (zend_hash_internal_pointer_reset_ex(rconflicts, &pos);
     567           0 :                         zend_hash_get_current_data_ex(rconflicts, (void *) &conflict, &pos) == SUCCESS;
     568             :                         zend_hash_move_forward_ex(rconflicts, &pos)
     569           0 :                 ) {
     570           0 :                         if (SUCCESS != (*conflict)(handler->name, handler->name_len TSRMLS_CC)) {
     571           0 :                                 return FAILURE;
     572             :                         }
     573             :                 }
     574             :         }
     575             :         /* zend_stack_push never returns SUCCESS but FAILURE or stack level */
     576        4965 :         if (FAILURE == (handler->level = zend_stack_push(&OG(handlers), &handler, sizeof(php_output_handler *)))) {
     577           0 :                 return FAILURE;
     578             :         }
     579        4965 :         OG(active) = handler;
     580        4965 :         return SUCCESS;
     581             : }
     582             : /* }}} */
     583             : 
     584             : /* {{{ int php_output_handler_started(zval *name TSRMLS_DC)
     585             :  * Check whether a certain output handler is in use */
     586           8 : PHPAPI int php_output_handler_started(const char *name, size_t name_len TSRMLS_DC)
     587             : {
     588             :         php_output_handler ***handlers;
     589           8 :         int i, count = php_output_get_level(TSRMLS_C);
     590             : 
     591           8 :         if (count) {
     592           5 :                 handlers = (php_output_handler ***) zend_stack_base(&OG(handlers));
     593             : 
     594          13 :                 for (i = 0; i < count; ++i) {
     595           9 :                         if (name_len == (*(handlers[i]))->name_len && !memcmp((*(handlers[i]))->name, name, name_len)) {
     596           1 :                                 return 1;
     597             :                         }
     598             :                 }
     599             :         }
     600             : 
     601           7 :         return 0;
     602             : }
     603             : /* }}} */
     604             : 
     605             : /* {{{ int php_output_handler_conflict(zval *handler_new, zval *handler_old TSRMLS_DC)
     606             :  * Check whether a certain handler is in use and issue a warning that the new handler would conflict with the already used one */
     607           5 : 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)
     608             : {
     609           5 :         if (php_output_handler_started(handler_set, handler_set_len TSRMLS_CC)) {
     610           2 :                 if (handler_new_len != handler_set_len || memcmp(handler_new, handler_set, handler_set_len)) {
     611           1 :                         php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler '%s' conflicts with '%s'", handler_new, handler_set);
     612             :                 } else {
     613           0 :                         php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler '%s' cannot be used twice", handler_new);
     614             :                 }
     615           1 :                 return 1;
     616             :         }
     617           4 :         return 0;
     618             : }
     619             : /* }}} */
     620             : 
     621             : /* {{{ SUCCESS|FAILURE php_output_handler_conflict_register(zval *name, php_output_handler_conflict_check_t check_func TSRMLS_DC)
     622             :  * Register a conflict checking function on MINIT */
     623       60675 : PHPAPI int php_output_handler_conflict_register(const char *name, size_t name_len, php_output_handler_conflict_check_t check_func TSRMLS_DC)
     624             : {
     625       60675 :         if (!EG(current_module)) {
     626           0 :                 zend_error(E_ERROR, "Cannot register an output handler conflict outside of MINIT");
     627           0 :                 return FAILURE;
     628             :         }
     629       60675 :         return zend_hash_update(&php_output_handler_conflicts, name, name_len+1, &check_func, sizeof(php_output_handler_conflict_check_t *), NULL);
     630             : }
     631             : /* }}} */
     632             : 
     633             : /* {{{ SUCCESS|FAILURE php_output_handler_reverse_conflict_register(zval *name, php_output_handler_conflict_check_t check_func TSRMLS_DC)
     634             :  * Register a reverse conflict checking function on MINIT */
     635           0 : 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)
     636             : {
     637           0 :         HashTable rev, *rev_ptr = NULL;
     638             : 
     639           0 :         if (!EG(current_module)) {
     640           0 :                 zend_error(E_ERROR, "Cannot register a reverse output handler conflict outside of MINIT");
     641           0 :                 return FAILURE;
     642             :         }
     643             : 
     644           0 :         if (SUCCESS == zend_hash_find(&php_output_handler_reverse_conflicts, name, name_len+1, (void *) &rev_ptr)) {
     645           0 :                 return zend_hash_next_index_insert(rev_ptr, &check_func, sizeof(php_output_handler_conflict_check_t *), NULL);
     646             :         } else {
     647           0 :                 zend_hash_init(&rev, 1, NULL, NULL, 1);
     648           0 :                 if (SUCCESS != zend_hash_next_index_insert(&rev, &check_func, sizeof(php_output_handler_conflict_check_t *), NULL)) {
     649           0 :                         zend_hash_destroy(&rev);
     650           0 :                         return FAILURE;
     651             :                 }
     652           0 :                 if (SUCCESS != zend_hash_update(&php_output_handler_reverse_conflicts, name, name_len+1, &rev, sizeof(HashTable), NULL)) {
     653           0 :                         zend_hash_destroy(&rev);
     654           0 :                         return FAILURE;
     655             :                 }
     656           0 :                 return SUCCESS;
     657             :         }
     658             : }
     659             : /* }}} */
     660             : 
     661             : /* {{{ php_output_handler_alias_ctor_t php_output_handler_alias(zval *name TSRMLS_DC)
     662             :  * Get an internal output handler for a user handler if it exists */
     663          85 : PHPAPI php_output_handler_alias_ctor_t *php_output_handler_alias(const char *name, size_t name_len TSRMLS_DC)
     664             : {
     665          85 :         php_output_handler_alias_ctor_t *func = NULL;
     666             : 
     667          85 :         zend_hash_find(&php_output_handler_aliases, name, name_len+1, (void *) &func);
     668          85 :         return func;
     669             : }
     670             : /* }}} */
     671             : 
     672             : /* {{{ SUCCESS|FAILURE php_output_handler_alias_register(zval *name, php_output_handler_alias_ctor_t func TSRMLS_DC)
     673             :  * Registers an internal output handler as alias for a user handler */
     674       60675 : PHPAPI int php_output_handler_alias_register(const char *name, size_t name_len, php_output_handler_alias_ctor_t func TSRMLS_DC)
     675             : {
     676       60675 :         if (!EG(current_module)) {
     677           0 :                 zend_error(E_ERROR, "Cannot register an output handler alias outside of MINIT");
     678           0 :                 return FAILURE;
     679             :         }
     680       60675 :         return zend_hash_update(&php_output_handler_aliases, name, name_len+1, &func, sizeof(php_output_handler_alias_ctor_t *), NULL);
     681             : }
     682             : /* }}} */
     683             : 
     684             : /* {{{ SUCCESS|FAILURE php_output_handler_hook(php_output_handler_hook_t type, void *arg TSMRLS_DC)
     685             :  * Output handler hook for output handler functions to check/modify the current handlers abilities */
     686          27 : PHPAPI int php_output_handler_hook(php_output_handler_hook_t type, void *arg TSRMLS_DC)
     687             : {
     688          27 :         if (OG(running)) {
     689          27 :                 switch (type) {
     690             :                         case PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ:
     691           0 :                                 *(void ***) arg = &OG(running)->opaq;
     692           0 :                                 return SUCCESS;
     693             :                         case PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS:
     694          16 :                                 *(int *) arg = OG(running)->flags;
     695          16 :                                 return SUCCESS;
     696             :                         case PHP_OUTPUT_HANDLER_HOOK_GET_LEVEL:
     697           0 :                                 *(int *) arg = OG(running)->level;
     698           0 :                 return SUCCESS;
     699             :                         case PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE:
     700          11 :                                 OG(running)->flags &= ~(PHP_OUTPUT_HANDLER_REMOVABLE|PHP_OUTPUT_HANDLER_CLEANABLE);
     701          11 :                                 return SUCCESS;
     702             :                         case PHP_OUTPUT_HANDLER_HOOK_DISABLE:
     703           0 :                                 OG(running)->flags |= PHP_OUTPUT_HANDLER_DISABLED;
     704           0 :                                 return SUCCESS;
     705             :                         default:
     706             :                                 break;
     707             :                 }
     708             :         }
     709           0 :         return FAILURE;
     710             : }
     711             : /* }}} */
     712             : 
     713             : /* {{{ void php_output_handler_dtor(php_output_handler *handler TSRMLS_DC)
     714             :  * Destroy an output handler */
     715        4966 : PHPAPI void php_output_handler_dtor(php_output_handler *handler TSRMLS_DC)
     716             : {
     717        4966 :         STR_FREE(handler->name);
     718        4966 :         STR_FREE(handler->buffer.data);
     719        4966 :         if (handler->flags & PHP_OUTPUT_HANDLER_USER) {
     720          80 :                 zval_ptr_dtor(&handler->func.user->zoh);
     721          80 :                 efree(handler->func.user);
     722             :         }
     723        4966 :         if (handler->dtor && handler->opaq) {
     724          20 :                 handler->dtor(handler->opaq TSRMLS_CC);
     725             :         }
     726        4966 :         memset(handler, 0, sizeof(*handler));
     727        4966 : }
     728             : /* }}} */
     729             : 
     730             : /* {{{ void php_output_handler_free(php_output_handler **handler TSMRLS_DC)
     731             :  * Destroy and free an output handler */
     732        4979 : PHPAPI void php_output_handler_free(php_output_handler **h TSRMLS_DC)
     733             : {
     734        4979 :         if (*h) {
     735        4966 :                 php_output_handler_dtor(*h TSRMLS_CC);
     736        4966 :                 efree(*h);
     737        4966 :                 *h = NULL;
     738             :         }
     739        4979 : }
     740             : /* }}} */
     741             : 
     742             : /* void php_output_set_implicit_flush(int enabled TSRMLS_DC)
     743             :  * Enable or disable implicit flush */
     744       19790 : PHPAPI void php_output_set_implicit_flush(int flush TSRMLS_DC)
     745             : {
     746       19790 :         if (flush) {
     747       19782 :                 OG(flags) |= PHP_OUTPUT_IMPLICITFLUSH;
     748             :         } else {
     749           8 :                 OG(flags) &= ~PHP_OUTPUT_IMPLICITFLUSH;
     750             :         }
     751       19790 : }
     752             : /* }}} */
     753             : 
     754             : /* {{{ char *php_output_get_start_filename(TSRMLS_D)
     755             :  * Get the file name where output has started */
     756         560 : PHPAPI const char *php_output_get_start_filename(TSRMLS_D)
     757             : {
     758         560 :         return OG(output_start_filename);
     759             : }
     760             : /* }}} */
     761             : 
     762             : /* {{{ int php_output_get_start_lineno(TSRMLS_D)
     763             :  * Get the line number where output has started */
     764         560 : PHPAPI int php_output_get_start_lineno(TSRMLS_D)
     765             : {
     766         560 :         return OG(output_start_lineno);
     767             : }
     768             : /* }}} */
     769             : 
     770             : /* {{{ static int php_output_lock_error(int op TSRMLS_DC)
     771             :  * Checks whether an unallowed operation is attempted from within the output handler and issues a fatal error */
     772     2394843 : static inline int php_output_lock_error(int op TSRMLS_DC)
     773             : {
     774             :         /* if there's no ob active, ob has been stopped */
     775     2394843 :         if (op && OG(active) && OG(running)) {
     776             :                 /* fatal error */
     777           3 :                 php_output_deactivate(TSRMLS_C);
     778           3 :                 php_error_docref("ref.outcontrol" TSRMLS_CC, E_ERROR, "Cannot use output buffering in output buffering display handlers");
     779           0 :                 return 1;
     780             :         }
     781     2394840 :         return 0;
     782             : }
     783             : /* }}} */
     784             : 
     785             : /* {{{ static php_output_context *php_output_context_init(php_output_context *context, int op TSRMLS_DC)
     786             :  * Initialize a new output context */
     787     1665964 : static inline php_output_context *php_output_context_init(php_output_context *context, int op TSRMLS_DC)
     788             : {
     789     1665964 :         if (!context) {
     790           0 :                 context = emalloc(sizeof(php_output_context));
     791             :         }
     792             : 
     793     1665964 :         memset(context, 0, sizeof(php_output_context));
     794             :         TSRMLS_SET_CTX(context->tsrm_ls);
     795     1665964 :         context->op = op;
     796             : 
     797     1665964 :         return context;
     798             : }
     799             : /* }}} */
     800             : 
     801             : /* {{{ static void php_output_context_reset(php_output_context *context)
     802             :  * Reset an output context */
     803         575 : static inline void php_output_context_reset(php_output_context *context)
     804             : {
     805         575 :         int op = context->op;
     806         575 :         php_output_context_dtor(context);
     807         575 :         memset(context, 0, sizeof(php_output_context));
     808         575 :         context->op = op;
     809         575 : }
     810             : /* }}} */
     811             : 
     812             : /* {{{ static void php_output_context_feed(php_output_context *context, char *, size_t, size_t)
     813             :  * Feed output contexts input buffer */
     814        4906 : static inline void php_output_context_feed(php_output_context *context, char *data, size_t size, size_t used, zend_bool free)
     815             : {
     816        4906 :         if (context->in.free && context->in.data) {
     817           0 :                 efree(context->in.data);
     818             :         }
     819        4906 :         context->in.data = data;
     820        4906 :         context->in.used = used;
     821        4906 :         context->in.free = free;
     822        4906 :         context->in.size = size;
     823        4906 : }
     824             : /* }}} */
     825             : 
     826             : /* {{{ static void php_output_context_swap(php_output_context *context)
     827             :  * Swap output contexts buffers */
     828           0 : static inline void php_output_context_swap(php_output_context *context)
     829             : {
     830           0 :         if (context->in.free && context->in.data) {
     831           0 :                 efree(context->in.data);
     832             :         }
     833           0 :         context->in.data = context->out.data;
     834           0 :         context->in.used = context->out.used;
     835           0 :         context->in.free = context->out.free;
     836           0 :         context->in.size = context->out.size;
     837           0 :         context->out.data = NULL;
     838           0 :         context->out.used = 0;
     839           0 :         context->out.free = 0;
     840           0 :         context->out.size = 0;
     841           0 : }
     842             : /* }}} */
     843             : 
     844             : /* {{{ static void php_output_context_pass(php_output_context *context)
     845             :  * Pass input to output buffer */
     846        4899 : static inline void php_output_context_pass(php_output_context *context)
     847             : {
     848        4899 :         context->out.data = context->in.data;
     849        4899 :         context->out.used = context->in.used;
     850        4899 :         context->out.size = context->in.size;
     851        4899 :         context->out.free = context->in.free;
     852        4899 :         context->in.data = NULL;
     853        4899 :         context->in.used = 0;
     854        4899 :         context->in.free = 0;
     855        4899 :         context->in.size = 0;
     856        4899 : }
     857             : /* }}} */
     858             : 
     859             : /* {{{ static void php_output_context_dtor(php_output_context *context)
     860             :  * Destroy the contents of an output context */
     861     1666533 : static inline void php_output_context_dtor(php_output_context *context)
     862             : {
     863     1666533 :         if (context->in.free && context->in.data) {
     864           0 :                 efree(context->in.data);
     865           0 :                 context->in.data = NULL;
     866             :         }
     867     1666533 :         if (context->out.free && context->out.data) {
     868         148 :                 efree(context->out.data);
     869         148 :                 context->out.data = NULL;
     870             :         }
     871     1666533 : }
     872             : /* }}} */
     873             : 
     874             : /* {{{ static php_output_handler *php_output_handler_init(zval *name, size_t chunk_size, int flags TSRMLS_DC)
     875             :  * Allocates and initializes a php_output_handler structure */
     876        4968 : static inline php_output_handler *php_output_handler_init(const char *name, size_t name_len, size_t chunk_size, int flags TSRMLS_DC)
     877             : {
     878             :         php_output_handler *handler;
     879             : 
     880        4968 :         handler = ecalloc(1, sizeof(php_output_handler));
     881        4968 :         handler->name = estrndup(name, name_len);
     882        4968 :         handler->name_len = name_len;
     883        4968 :         handler->size = chunk_size;
     884        4968 :         handler->flags = flags;
     885        4968 :         handler->buffer.size = PHP_OUTPUT_HANDLER_INITBUF_SIZE(chunk_size);
     886        4968 :         handler->buffer.data = emalloc(handler->buffer.size);
     887             : 
     888        4968 :         return handler;
     889             : }
     890             : /* }}} */
     891             : 
     892             : /* {{{ static int php_output_handler_appen(php_output_handler *handler, const php_output_buffer *buf TSRMLS_DC)
     893             :  * Appends input to the output handlers buffer and indicates whether the buffer does not have to be processed by the output handler */
     894      728891 : static inline int php_output_handler_append(php_output_handler *handler, const php_output_buffer *buf TSRMLS_DC)
     895             : {
     896      728891 :         if (buf->used) {
     897      723490 :                 OG(flags) |= PHP_OUTPUT_WRITTEN;
     898             :                 /* store it away */
     899      723490 :                 if ((handler->buffer.size - handler->buffer.used) <= buf->used) {
     900         443 :                         size_t grow_int = PHP_OUTPUT_HANDLER_INITBUF_SIZE(handler->size);
     901         443 :                         size_t grow_buf = PHP_OUTPUT_HANDLER_INITBUF_SIZE(buf->used - (handler->buffer.size - handler->buffer.used));
     902         443 :                         size_t grow_max = MAX(grow_int, grow_buf);
     903             : 
     904         443 :                         handler->buffer.data = erealloc(handler->buffer.data, handler->buffer.size + grow_max);
     905         443 :                         handler->buffer.size += grow_max;
     906             :                 }
     907      723490 :                 memcpy(handler->buffer.data + handler->buffer.used, buf->data, buf->used);
     908      723490 :                 handler->buffer.used += buf->used;
     909             : 
     910             :                 /* chunked buffering */
     911      723490 :                 if (handler->size && (handler->buffer.used >= handler->size)) {
     912             :                         /* store away errors and/or any intermediate output */
     913          43 :                         return OG(running) ? 1 : 0;
     914             :                 }
     915             :         }
     916      728848 :         return 1;
     917             : }
     918             : /* }}} */
     919             : 
     920             : /* {{{ static php_output_handler_status_t php_output_handler_op(php_output_handler *handler, php_output_context *context)
     921             :  * Output handler operation dispatcher, applying context op to the php_output_handler handler */
     922      728892 : static inline php_output_handler_status_t php_output_handler_op(php_output_handler *handler, php_output_context *context)
     923             : {
     924             :         php_output_handler_status_t status;
     925      728892 :         int original_op = context->op;
     926             :         PHP_OUTPUT_TSRMLS(context);
     927             : 
     928             : #if PHP_OUTPUT_DEBUG
     929             :         fprintf(stderr, ">>> op(%d, "
     930             :                                         "handler=%p, "
     931             :                                         "name=%s, "
     932             :                                         "flags=%d, "
     933             :                                         "buffer.data=%s, "
     934             :                                         "buffer.used=%zu, "
     935             :                                         "buffer.size=%zu, "
     936             :                                         "in.data=%s, "
     937             :                                         "in.used=%zu)\n",
     938             :                         context->op,
     939             :                         handler,
     940             :                         handler->name,
     941             :                         handler->flags,
     942             :                         handler->buffer.used?handler->buffer.data:"",
     943             :                         handler->buffer.used,
     944             :                         handler->buffer.size,
     945             :                         context->in.used?context->in.data:"",
     946             :                         context->in.used
     947             :         );
     948             : #endif
     949             : 
     950      728892 :         if (php_output_lock_error(context->op TSRMLS_CC)) {
     951             :                 /* fatal error */
     952           0 :                 return PHP_OUTPUT_HANDLER_FAILURE;
     953             :         }
     954             : 
     955             :         /* storable? */
     956      728891 :         if (php_output_handler_append(handler, &context->in TSRMLS_CC) && !context->op) {
     957      723859 :                 context->op = original_op;
     958      723859 :                 return PHP_OUTPUT_HANDLER_NO_DATA;
     959             :         } else {
     960             :                 /* need to start? */
     961        5032 :                 if (!(handler->flags & PHP_OUTPUT_HANDLER_STARTED)) {
     962        4965 :                         context->op |= PHP_OUTPUT_HANDLER_START;
     963             :                 }
     964             : 
     965        5032 :                 OG(running) = handler;
     966        5032 :                 if (handler->flags & PHP_OUTPUT_HANDLER_USER) {
     967         126 :                         zval *retval = NULL, *ob_data, *ob_mode;
     968             : 
     969         126 :                         MAKE_STD_ZVAL(ob_data);
     970         126 :                         ZVAL_STRINGL(ob_data, handler->buffer.data, handler->buffer.used, 1);
     971         126 :                         MAKE_STD_ZVAL(ob_mode);
     972         126 :                         ZVAL_LONG(ob_mode, (long) context->op);
     973         126 :                         zend_fcall_info_argn(&handler->func.user->fci TSRMLS_CC, 2, &ob_data, &ob_mode);
     974             : 
     975             : #define PHP_OUTPUT_USER_SUCCESS(retval) (retval && !(Z_TYPE_P(retval) == IS_BOOL && Z_BVAL_P(retval)==0))
     976         247 :                         if (SUCCESS == zend_fcall_info_call(&handler->func.user->fci, &handler->func.user->fcc, &retval, NULL TSRMLS_CC) && PHP_OUTPUT_USER_SUCCESS(retval)) {
     977             :                                 /* user handler may have returned TRUE */
     978         121 :                                 status = PHP_OUTPUT_HANDLER_NO_DATA;
     979         121 :                                 if (Z_TYPE_P(retval) != IS_BOOL) {
     980         160 :                                         convert_to_string_ex(&retval);
     981         121 :                                         if (Z_STRLEN_P(retval)) {
     982         107 :                                                 context->out.data = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
     983         107 :                                                 context->out.used = Z_STRLEN_P(retval);
     984         107 :                                                 context->out.free = 1;
     985         107 :                                                 status = PHP_OUTPUT_HANDLER_SUCCESS;
     986             :                                         }
     987             :                                 }
     988             :                         } else {
     989             :                                 /* call failed, pass internal buffer along */
     990           2 :                                 status = PHP_OUTPUT_HANDLER_FAILURE;
     991             :                         }
     992             : 
     993         123 :                         zend_fcall_info_argn(&handler->func.user->fci TSRMLS_CC, 0);
     994         123 :                         zval_ptr_dtor(&ob_data);
     995         123 :                         zval_ptr_dtor(&ob_mode);
     996         123 :                         if (retval) {
     997         122 :                                 zval_ptr_dtor(&retval);
     998             :                         }
     999             : 
    1000             :                 } else {
    1001             : 
    1002        4906 :                         php_output_context_feed(context, handler->buffer.data, handler->buffer.size, handler->buffer.used, 0);
    1003             : 
    1004        4906 :                         if (SUCCESS == handler->func.internal(&handler->opaq, context)) {
    1005        4895 :                                 if (context->out.used) {
    1006        4334 :                                         status = PHP_OUTPUT_HANDLER_SUCCESS;
    1007             :                                 } else {
    1008         561 :                                         status = PHP_OUTPUT_HANDLER_NO_DATA;
    1009             :                                 }
    1010             :                         } else {
    1011          11 :                                 status = PHP_OUTPUT_HANDLER_FAILURE;
    1012             :                         }
    1013             :                 }
    1014        5029 :                 handler->flags |= PHP_OUTPUT_HANDLER_STARTED;
    1015        5029 :                 OG(running) = NULL;
    1016             :         }
    1017             : 
    1018        5029 :         switch (status) {
    1019             :                 case PHP_OUTPUT_HANDLER_FAILURE:
    1020             :                         /* disable this handler */
    1021          13 :                         handler->flags |= PHP_OUTPUT_HANDLER_DISABLED;
    1022             :                         /* discard any output */
    1023          13 :                         if (context->out.data && context->out.free) {
    1024           7 :                                 efree(context->out.data);
    1025             :                         }
    1026             :                         /* returns handlers buffer */
    1027          13 :                         context->out.data = handler->buffer.data;
    1028          13 :                         context->out.used = handler->buffer.used;
    1029          13 :                         context->out.free = 1;
    1030          13 :                         handler->buffer.data = NULL;
    1031          13 :                         handler->buffer.used = 0;
    1032          13 :                         handler->buffer.size = 0;
    1033          13 :                         break;
    1034             :                 case PHP_OUTPUT_HANDLER_NO_DATA:
    1035             :                         /* handler ate all */
    1036         575 :                         php_output_context_reset(context);
    1037             :                         /* no break */
    1038             :                 case PHP_OUTPUT_HANDLER_SUCCESS:
    1039             :                         /* no more buffered data */
    1040        5016 :                         handler->buffer.used = 0;
    1041        5016 :                         handler->flags |= PHP_OUTPUT_HANDLER_PROCESSED;
    1042             :                         break;
    1043             :         }
    1044             : 
    1045        5029 :         context->op = original_op;
    1046        5029 :         return status;
    1047             : }
    1048             : /* }}} */
    1049             : 
    1050             : 
    1051             : /* {{{ static void php_output_op(int op, const char *str, size_t len TSRMLS_DC)
    1052             :  * Output op dispatcher, passes input and output handlers output through the output handler stack until it gets written to the SAPI */
    1053     1660970 : static inline void php_output_op(int op, const char *str, size_t len TSRMLS_DC)
    1054             : {
    1055             :         php_output_context context;
    1056             :         php_output_handler **active;
    1057             :         int obh_cnt;
    1058             : 
    1059     1660970 :         if (php_output_lock_error(op TSRMLS_CC)) {
    1060           0 :                 return;
    1061             :         }
    1062             : 
    1063     1660970 :         php_output_context_init(&context, op TSRMLS_CC);
    1064             : 
    1065             :         /*
    1066             :          * broken up for better performance:
    1067             :          *  - apply op to the one active handler; note that OG(active) might be popped off the stack on a flush
    1068             :          *  - or apply op to the handler stack
    1069             :          */
    1070     2384903 :         if (OG(active) && (obh_cnt = zend_stack_count(&OG(handlers)))) {
    1071      723933 :                 context.in.data = (char *) str;
    1072      723933 :                 context.in.used = len;
    1073             : 
    1074      723933 :                 if (obh_cnt > 1) {
    1075      672557 :                         zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_TOPDOWN, php_output_stack_apply_op, &context);
    1076      102719 :                 } else if ((SUCCESS == zend_stack_top(&OG(handlers), (void *) &active)) && (!((*active)->flags & PHP_OUTPUT_HANDLER_DISABLED))) {
    1077       51343 :                         php_output_handler_op(*active, &context);
    1078             :                 } else {
    1079          33 :                         php_output_context_pass(&context);
    1080             :                 }
    1081             :         } else {
    1082      937037 :                 context.out.data = (char *) str;
    1083      937037 :                 context.out.used = len;
    1084             :         }
    1085             : 
    1086     1660970 :         if (context.out.data && context.out.used) {
    1087      930612 :                 php_output_header(TSRMLS_C);
    1088             : 
    1089      930612 :                 if (!(OG(flags) & PHP_OUTPUT_DISABLED)) {
    1090             : #if PHP_OUTPUT_DEBUG
    1091             :                         fprintf(stderr, "::: sapi_write('%s', %zu)\n", context.out.data, context.out.used);
    1092             : #endif
    1093      930612 :                         sapi_module.ub_write(context.out.data, context.out.used TSRMLS_CC);
    1094             : 
    1095      930610 :                         if (OG(flags) & PHP_OUTPUT_IMPLICITFLUSH) {
    1096      924523 :                                 sapi_flush(TSRMLS_C);
    1097             :                         }
    1098             : 
    1099      930610 :                         OG(flags) |= PHP_OUTPUT_SENT;
    1100             :                 }
    1101             :         }
    1102     1660968 :         php_output_context_dtor(&context);
    1103             : }
    1104             : /* }}} */
    1105             : 
    1106             : /* {{{ static int php_output_stack_apply_op(void *h, void *c)
    1107             :  * Operation callback for the stack apply function */
    1108      672557 : static int php_output_stack_apply_op(void *h, void *c)
    1109             : {
    1110             :         int was_disabled;
    1111             :         php_output_handler_status_t status;
    1112      672557 :         php_output_handler *handler = *(php_output_handler **) h;
    1113      672557 :         php_output_context *context = (php_output_context *) c;
    1114             : 
    1115      672557 :         if ((was_disabled = (handler->flags & PHP_OUTPUT_HANDLER_DISABLED))) {
    1116           0 :                 status = PHP_OUTPUT_HANDLER_FAILURE;
    1117             :         } else {
    1118      672557 :                 status = php_output_handler_op(handler, context);
    1119             :         }
    1120             : 
    1121             :         /*
    1122             :          * handler ate all => break
    1123             :          * handler returned data or failed resp. is disabled => continue
    1124             :          */
    1125      672557 :         switch (status) {
    1126             :                 case PHP_OUTPUT_HANDLER_NO_DATA:
    1127      672557 :                         return 1;
    1128             : 
    1129             :                 case PHP_OUTPUT_HANDLER_SUCCESS:
    1130             :                         /* swap contexts buffers, unless this is the last handler in the stack */
    1131           0 :                         if (handler->level) {
    1132           0 :                                 php_output_context_swap(context);
    1133             :                         }
    1134           0 :                         return 0;
    1135             : 
    1136             :                 case PHP_OUTPUT_HANDLER_FAILURE:
    1137             :                 default:
    1138           0 :                         if (was_disabled) {
    1139             :                                 /* pass input along, if it's the last handler in the stack */
    1140           0 :                                 if (!handler->level) {
    1141           0 :                                         php_output_context_pass(context);
    1142             :                                 }
    1143             :                         } else {
    1144             :                                 /* swap buffers, unless this is the last handler */
    1145           0 :                                 if (handler->level) {
    1146           0 :                                         php_output_context_swap(context);
    1147             :                                 }
    1148             :                         }
    1149           0 :                         return 0;
    1150             :         }
    1151             : }
    1152             : /* }}} */
    1153             : 
    1154             : /* {{{ static int php_output_stack_apply_clean(void *h, void *c)
    1155             :  * Clean callback for the stack apply function */
    1156           0 : static int php_output_stack_apply_clean(void *h, void *c)
    1157             : {
    1158           0 :         php_output_handler *handler = *(php_output_handler **) h;
    1159           0 :         php_output_context *context = (php_output_context *) c;
    1160             : 
    1161           0 :         handler->buffer.used = 0;
    1162           0 :         php_output_handler_op(handler, context);
    1163           0 :         php_output_context_reset(context);
    1164           0 :         return 0;
    1165             : }
    1166             : /* }}} */
    1167             : 
    1168             : /* {{{ static int php_output_stack_apply_list(void *h, void *z)
    1169             :  * List callback for the stack apply function */
    1170          12 : static int php_output_stack_apply_list(void *h, void *z)
    1171             : {
    1172          12 :         php_output_handler *handler = *(php_output_handler **) h;
    1173          12 :         zval *array = (zval *) z;
    1174             : 
    1175          12 :         add_next_index_stringl(array, handler->name, handler->name_len, 1);
    1176          12 :         return 0;
    1177             : }
    1178             : /* }}} */
    1179             : 
    1180             : /* {{{ static int php_output_stack_apply_status(void *h, void *z)
    1181             :  * Status callback for the stack apply function */
    1182           6 : static int php_output_stack_apply_status(void *h, void *z)
    1183             : {
    1184           6 :         php_output_handler *handler = *(php_output_handler **) h;
    1185           6 :         zval *array = (zval *) z;
    1186             : 
    1187           6 :         add_next_index_zval(array, php_output_handler_status(handler, NULL));
    1188             : 
    1189           6 :         return 0;
    1190             : }
    1191             : 
    1192             : /* {{{ static zval *php_output_handler_status(php_output_handler *handler, zval *entry)
    1193             :  * Returns an array with the status of the output handler */
    1194           7 : static inline zval *php_output_handler_status(php_output_handler *handler, zval *entry)
    1195             : {
    1196           7 :         if (!entry) {
    1197           6 :                 MAKE_STD_ZVAL(entry);
    1198           6 :                 array_init(entry);
    1199             :         }
    1200             : 
    1201           7 :         add_assoc_stringl(entry, "name", handler->name, handler->name_len, 1);
    1202           7 :         add_assoc_long(entry, "type", (long) (handler->flags & 0xf));
    1203           7 :         add_assoc_long(entry, "flags", (long) handler->flags);
    1204           7 :         add_assoc_long(entry, "level", (long) handler->level);
    1205           7 :         add_assoc_long(entry, "chunk_size", (long) handler->size);
    1206           7 :         add_assoc_long(entry, "buffer_size", (long) handler->buffer.size);
    1207           7 :         add_assoc_long(entry, "buffer_used", (long) handler->buffer.used);
    1208             : 
    1209           7 :         return entry;
    1210             : }
    1211             : /* }}} */
    1212             : 
    1213             : /* {{{ static int php_output_stack_pop(int flags TSRMLS_DC)
    1214             :  * Pops an output handler off the stack */
    1215        4970 : static inline int php_output_stack_pop(int flags TSRMLS_DC)
    1216             : {
    1217             :         php_output_context context;
    1218        4970 :         php_output_handler **current, *orphan = OG(active);
    1219             : 
    1220        4970 :         if (!orphan) {
    1221           0 :                 if (!(flags & PHP_OUTPUT_POP_SILENT)) {
    1222           0 :                         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");
    1223             :                 }
    1224           0 :                 return 0;
    1225        4970 :         } else if (!(flags & PHP_OUTPUT_POP_FORCE) && !(orphan->flags & PHP_OUTPUT_HANDLER_REMOVABLE)) {
    1226           4 :                 if (!(flags & PHP_OUTPUT_POP_SILENT)) {
    1227           4 :                         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);
    1228             :                 }
    1229           4 :                 return 0;
    1230             :         } else {
    1231        4966 :                 php_output_context_init(&context, PHP_OUTPUT_HANDLER_FINAL TSRMLS_CC);
    1232             : 
    1233             :                 /* don't run the output handler if it's disabled */
    1234        4966 :                 if (!(orphan->flags & PHP_OUTPUT_HANDLER_DISABLED)) {
    1235             :                         /* didn't it start yet? */
    1236        4964 :                         if (!(orphan->flags & PHP_OUTPUT_HANDLER_STARTED)) {
    1237        4927 :                                 context.op |= PHP_OUTPUT_HANDLER_START;
    1238             :                         }
    1239             :                         /* signal that we're cleaning up */
    1240        4964 :                         if (flags & PHP_OUTPUT_POP_DISCARD) {
    1241        4492 :                                 context.op |= PHP_OUTPUT_HANDLER_CLEAN;
    1242             :                         }
    1243        4964 :                         php_output_handler_op(orphan, &context);
    1244             :                 }
    1245             : 
    1246             :                 /* pop it off the stack */
    1247        4962 :                 zend_stack_del_top(&OG(handlers));
    1248        4962 :                 if (SUCCESS == zend_stack_top(&OG(handlers), (void *) &current)) {
    1249         313 :                         OG(active) = *current;
    1250             :                 } else {
    1251        4649 :                         OG(active) = NULL;
    1252             :                 }
    1253             : 
    1254             :                 /* pass output along */
    1255        4962 :                 if (context.out.data && context.out.used && !(flags & PHP_OUTPUT_POP_DISCARD)) {
    1256         451 :                         php_output_write(context.out.data, context.out.used TSRMLS_CC);
    1257             :                 }
    1258             : 
    1259             :                 /* destroy the handler (after write!) */
    1260        4962 :                 php_output_handler_free(&orphan TSRMLS_CC);
    1261        4962 :                 php_output_context_dtor(&context);
    1262             : 
    1263        4962 :                 return 1;
    1264             :         }
    1265             : }
    1266             : /* }}} */
    1267             : 
    1268             : /* {{{ static SUCCESS|FAILURE php_output_handler_compat_func(void *ctx, php_output_context *)
    1269             :  * php_output_handler_context_func_t for php_output_handler_func_t output handlers */
    1270          15 : static int php_output_handler_compat_func(void **handler_context, php_output_context *output_context)
    1271             : {
    1272          15 :         php_output_handler_func_t func = *(php_output_handler_func_t *) handler_context;
    1273             :         PHP_OUTPUT_TSRMLS(output_context);
    1274             : 
    1275          15 :         if (func) {
    1276          15 :                 char *out_str = NULL;
    1277          15 :                 uint out_len = 0;
    1278             : 
    1279          15 :                 func(output_context->in.data, output_context->in.used, &out_str, &out_len, output_context->op TSRMLS_CC);
    1280             : 
    1281          15 :                 if (out_str) {
    1282          15 :                         output_context->out.data = out_str;
    1283          15 :                         output_context->out.used = out_len;
    1284          15 :                         output_context->out.free = 1;
    1285             :                 } else {
    1286           0 :                         php_output_context_pass(output_context);
    1287             :                 }
    1288             : 
    1289          15 :                 return SUCCESS;
    1290             :         }
    1291           0 :         return FAILURE;
    1292             : }
    1293             : /* }}} */
    1294             : 
    1295             : /* {{{ static SUCCESS|FAILURE php_output_handler_default_func(void *ctx, php_output_context *)
    1296             :  * Default output handler */
    1297        4866 : static int php_output_handler_default_func(void **handler_context, php_output_context *output_context)
    1298             : {
    1299        4866 :         php_output_context_pass(output_context);
    1300        4866 :         return SUCCESS;
    1301             : }
    1302             : /* }}} */
    1303             : 
    1304             : /* {{{ static SUCCESS|FAILURE php_output_handler_devnull_func(void *ctx, php_output_context *)
    1305             :  * Null output handler */
    1306           0 : static int php_output_handler_devnull_func(void **handler_context, php_output_context *output_context)
    1307             : {
    1308           0 :         return SUCCESS;
    1309             : }
    1310             : /* }}} */
    1311             : 
    1312             : /*
    1313             :  * USERLAND (nearly 1:1 of old output.c)
    1314             :  */
    1315             : 
    1316             : /* {{{ proto bool ob_start([string|array user_function [, int chunk_size [, int flags]]])
    1317             :    Turn on Output Buffering (specifying an optional output handler). */
    1318        4133 : PHP_FUNCTION(ob_start)
    1319             : {
    1320        4133 :         zval *output_handler = NULL;
    1321        4133 :         long chunk_size = 0;
    1322        4133 :         long flags = PHP_OUTPUT_HANDLER_STDFLAGS;
    1323             : 
    1324        4133 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z/ll", &output_handler, &chunk_size, &flags) == FAILURE) {
    1325           3 :                 return;
    1326             :         }
    1327             : 
    1328        4130 :         if (chunk_size < 0) {
    1329           2 :                 chunk_size = 0;
    1330             :         }
    1331             : 
    1332        4130 :         if (php_output_start_user(output_handler, chunk_size, flags TSRMLS_CC) == FAILURE) {
    1333          14 :                 php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to create buffer");
    1334          14 :                 RETURN_FALSE;
    1335             :         }
    1336        4115 :         RETURN_TRUE;
    1337             : }
    1338             : /* }}} */
    1339             : 
    1340             : /* {{{ proto bool ob_flush(void)
    1341             :    Flush (send) contents of the output buffer. The last buffer content is sent to next buffer */
    1342          25 : PHP_FUNCTION(ob_flush)
    1343             : {
    1344          25 :         if (zend_parse_parameters_none() == FAILURE) {
    1345           1 :                 return;
    1346             :         }
    1347             : 
    1348          24 :         if (!OG(active)) {
    1349           1 :                 php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to flush buffer. No buffer to flush");
    1350           1 :                 RETURN_FALSE;
    1351             :         }
    1352             : 
    1353          23 :         if (SUCCESS != php_output_flush(TSRMLS_C)) {
    1354           2 :                 php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to flush buffer of %s (%d)", OG(active)->name, OG(active)->level);
    1355           2 :                 RETURN_FALSE;
    1356             :         }
    1357          21 :         RETURN_TRUE;
    1358             : }
    1359             : /* }}} */
    1360             : 
    1361             : /* {{{ proto bool ob_clean(void)
    1362             :    Clean (delete) the current output buffer */
    1363          12 : PHP_FUNCTION(ob_clean)
    1364             : {
    1365          12 :         if (zend_parse_parameters_none() == FAILURE) {
    1366           1 :                 return;
    1367             :         }
    1368             : 
    1369          11 :         if (!OG(active)) {
    1370           3 :                 php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer. No buffer to delete");
    1371           3 :                 RETURN_FALSE;
    1372             :         }
    1373             : 
    1374           8 :         if (SUCCESS != php_output_clean(TSRMLS_C)) {
    1375           1 :                 php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer of %s (%d)", OG(active)->name, OG(active)->level);
    1376           1 :                 RETURN_FALSE;
    1377             :         }
    1378           7 :         RETURN_TRUE;
    1379             : }
    1380             : /* }}} */
    1381             : 
    1382             : /* {{{ proto bool ob_end_flush(void)
    1383             :    Flush (send) the output buffer, and delete current output buffer */
    1384         188 : PHP_FUNCTION(ob_end_flush)
    1385             : {
    1386         188 :         if (zend_parse_parameters_none() == FAILURE) {
    1387           1 :                 return;
    1388             :         }
    1389             : 
    1390         187 :         if (!OG(active)) {
    1391           4 :                 php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete and flush buffer. No buffer to delete or flush");
    1392           4 :                 RETURN_FALSE;
    1393             :         }
    1394             : 
    1395         183 :         RETURN_BOOL(SUCCESS == php_output_end(TSRMLS_C));
    1396             : }
    1397             : /* }}} */
    1398             : 
    1399             : /* {{{ proto bool ob_end_clean(void)
    1400             :    Clean the output buffer, and delete current output buffer */
    1401         258 : PHP_FUNCTION(ob_end_clean)
    1402             : {
    1403         258 :         if (zend_parse_parameters_none() == FAILURE) {
    1404           1 :                 return;
    1405             :         }
    1406             : 
    1407         257 :         if (!OG(active)) {
    1408           5 :                 php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer. No buffer to delete");
    1409           5 :                 RETURN_FALSE;
    1410             :         }
    1411             : 
    1412         252 :         RETURN_BOOL(SUCCESS == php_output_discard(TSRMLS_C));
    1413             : }
    1414             : /* }}} */
    1415             : 
    1416             : /* {{{ proto bool ob_get_flush(void)
    1417             :    Get current buffer contents, flush (send) the output buffer, and delete current output buffer */
    1418           7 : PHP_FUNCTION(ob_get_flush)
    1419             : {
    1420           7 :         if (zend_parse_parameters_none() == FAILURE) {
    1421           1 :                 return;
    1422             :         }
    1423             : 
    1424           6 :         if (php_output_get_contents(return_value TSRMLS_CC) == FAILURE) {
    1425           1 :                 php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete and flush buffer. No buffer to delete or flush");
    1426           1 :                 RETURN_FALSE;
    1427             :         }
    1428             : 
    1429           5 :         if (SUCCESS != php_output_end(TSRMLS_C)) {
    1430           1 :                 php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer of %s (%d)", OG(active)->name, OG(active)->level);
    1431             :         }
    1432             : }
    1433             : /* }}} */
    1434             : 
    1435             : /* {{{ proto bool ob_get_clean(void)
    1436             :    Get current buffer contents and delete current output buffer */
    1437        3607 : PHP_FUNCTION(ob_get_clean)
    1438             : {
    1439        3607 :         if (zend_parse_parameters_none() == FAILURE) {
    1440           1 :                 return;
    1441             :         }
    1442             : 
    1443        3606 :         if(!OG(active)) {
    1444           2 :                 RETURN_FALSE;
    1445             :         }
    1446             : 
    1447        3604 :         if (php_output_get_contents(return_value TSRMLS_CC) == FAILURE) {
    1448           0 :                 php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer. No buffer to delete");
    1449           0 :                 RETURN_FALSE;
    1450             :         }
    1451             : 
    1452        3604 :         if (SUCCESS != php_output_discard(TSRMLS_C)) {
    1453           1 :                 php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer of %s (%d)", OG(active)->name, OG(active)->level);
    1454             :         }
    1455             : }
    1456             : /* }}} */
    1457             : 
    1458             : /* {{{ proto string ob_get_contents(void)
    1459             :    Return the contents of the output buffer */
    1460         160 : PHP_FUNCTION(ob_get_contents)
    1461             : {
    1462         160 :         if (zend_parse_parameters_none() == FAILURE) {
    1463           2 :                 return;
    1464             :         }
    1465             : 
    1466         158 :         if (php_output_get_contents(return_value TSRMLS_CC) == FAILURE) {
    1467           5 :                 RETURN_FALSE;
    1468             :         }
    1469             : }
    1470             : /* }}} */
    1471             : 
    1472             : /* {{{ proto int ob_get_level(void)
    1473             :    Return the nesting level of the output buffer */
    1474          24 : PHP_FUNCTION(ob_get_level)
    1475             : {
    1476          24 :         if (zend_parse_parameters_none() == FAILURE) {
    1477           1 :                 return;
    1478             :         }
    1479             : 
    1480          23 :         RETURN_LONG(php_output_get_level(TSRMLS_C));
    1481             : }
    1482             : /* }}} */
    1483             : 
    1484             : /* {{{ proto int ob_get_length(void)
    1485             :    Return the length of the output buffer */
    1486          15 : PHP_FUNCTION(ob_get_length)
    1487             : {
    1488          15 :         if (zend_parse_parameters_none() == FAILURE) {
    1489           2 :                 return;
    1490             :         }
    1491             : 
    1492          13 :         if (php_output_get_length(return_value TSRMLS_CC) == FAILURE) {
    1493           3 :                 RETURN_FALSE;
    1494             :         }
    1495             : }
    1496             : /* }}} */
    1497             : 
    1498             : /* {{{ proto false|array ob_list_handlers()
    1499             :    List all output_buffers in an array */
    1500          17 : PHP_FUNCTION(ob_list_handlers)
    1501             : {
    1502          17 :         if (zend_parse_parameters_none() == FAILURE) {
    1503           0 :                 return;
    1504             :         }
    1505             : 
    1506          17 :         array_init(return_value);
    1507             : 
    1508          17 :         if (!OG(active)) {
    1509          10 :                 return;
    1510             :         }
    1511             : 
    1512           7 :         zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_BOTTOMUP, php_output_stack_apply_list, return_value);
    1513             : }
    1514             : /* }}} */
    1515             : 
    1516             : /* {{{ proto false|array ob_get_status([bool full_status])
    1517             :    Return the status of the active or all output buffers */
    1518           4 : PHP_FUNCTION(ob_get_status)
    1519             : {
    1520           4 :         zend_bool full_status = 0;
    1521             : 
    1522           4 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &full_status) == FAILURE) {
    1523           0 :                 return;
    1524             :         }
    1525             : 
    1526           4 :         array_init(return_value);
    1527             : 
    1528           4 :         if (!OG(active)) {
    1529           1 :                 return;
    1530             :         }
    1531             : 
    1532           3 :         if (full_status) {
    1533           2 :                 zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_BOTTOMUP, php_output_stack_apply_status, return_value);
    1534             :         } else {
    1535           1 :                 php_output_handler_status(OG(active), return_value);
    1536             :         }
    1537             : }
    1538             : /* }}} */
    1539             : 
    1540             : /* {{{ proto void ob_implicit_flush([int flag])
    1541             :    Turn implicit flush on/off and is equivalent to calling flush() after every output call */
    1542          30 : PHP_FUNCTION(ob_implicit_flush)
    1543             : {
    1544          30 :         long flag = 1;
    1545             : 
    1546          30 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flag) == FAILURE) {
    1547          13 :                 return;
    1548             :         }
    1549             : 
    1550          17 :         php_output_set_implicit_flush(flag TSRMLS_CC);
    1551             : }
    1552             : /* }}} */
    1553             : 
    1554             : /* {{{ proto bool output_reset_rewrite_vars(void)
    1555             :    Reset(clear) URL rewriter values */
    1556           1 : PHP_FUNCTION(output_reset_rewrite_vars)
    1557             : {
    1558           1 :         if (php_url_scanner_reset_vars(TSRMLS_C) == SUCCESS) {
    1559           1 :                 RETURN_TRUE;
    1560             :         } else {
    1561           0 :                 RETURN_FALSE;
    1562             :         }
    1563             : }
    1564             : /* }}} */
    1565             : 
    1566             : /* {{{ proto bool output_add_rewrite_var(string name, string value)
    1567             :    Add URL rewriter values */
    1568           3 : PHP_FUNCTION(output_add_rewrite_var)
    1569             : {
    1570             :         char *name, *value;
    1571             :         int name_len, value_len;
    1572             : 
    1573           3 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &value, &value_len) == FAILURE) {
    1574           0 :                 return;
    1575             :         }
    1576             : 
    1577           3 :         if (php_url_scanner_add_var(name, name_len, value, value_len, 1 TSRMLS_CC) == SUCCESS) {
    1578           3 :                 RETURN_TRUE;
    1579             :         } else {
    1580           0 :                 RETURN_FALSE;
    1581             :         }
    1582             : }
    1583             : /* }}} */
    1584             : 
    1585             : /*
    1586             :  * Local variables:
    1587             :  * tab-width: 4
    1588             :  * c-basic-offset: 4
    1589             :  * End:
    1590             :  * vim600: sw=4 ts=4 fdm=marker
    1591             :  * vim<600: sw=4 ts=4
    1592             :  */

Generated by: LCOV version 1.10

Generated at Tue, 25 Nov 2014 09:11:10 +0000 (32 hours ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.