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: 537 657 81.7 %
Date: 2014-10-14 Functions: 70 81 86.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Tue, 14 Oct 2014 07:25:55 +0000 (6 days ago)

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