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

Generated by: LCOV version 1.10

Generated at Wed, 02 Sep 2015 17:19:24 +0000 (2 days ago)

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