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

LTP GCOV extension - code coverage report
Current view: directory - var/php_gcov/PHP_HEAD/main - output.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 673
Code covered: 78.2 % Executed lines: 526
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:46 +0000 (36 hours ago)

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