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

Generated by: LCOV version 1.10

Generated at Mon, 26 Jan 2015 14:46:59 +0000 (2 days ago)

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