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

Generated by: LCOV version 1.10

Generated at Sun, 01 Mar 2015 23:22:40 +0000 (23 hours ago)

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