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

LCOV - code coverage report
Current view: top level - main - output.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 537 657 81.7 %
Date: 2014-11-22 Functions: 70 81 86.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sat, 22 Nov 2014 23:01:30 +0000 (4 days ago)

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