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

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

Generated by: LCOV version 1.10

Generated at Sat, 27 Jun 2015 09:41:24 +0000 (7 days ago)

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