|
|
|
@ -29,13 +29,12 @@ static int php_ub_body_write(const char *str, uint str_length); |
|
|
|
static int php_ub_body_write_no_header(const char *str, uint str_length); |
|
|
|
static int php_b_body_write(const char *str, uint str_length); |
|
|
|
|
|
|
|
static void php_ob_init(uint initial_size, uint block_size); |
|
|
|
static void php_ob_init(uint initial_size, uint block_size, zval *output_handler); |
|
|
|
static void php_ob_destroy(void); |
|
|
|
static void php_ob_append(const char *text, uint text_length); |
|
|
|
#if 0 |
|
|
|
static void php_ob_prepend(const char *text, uint text_length); |
|
|
|
#endif |
|
|
|
static inline void php_ob_send(void); |
|
|
|
|
|
|
|
|
|
|
|
#ifdef ZTS |
|
|
|
@ -51,6 +50,7 @@ static void php_output_init_globals(OLS_D) |
|
|
|
OG(implicit_flush) = 0; |
|
|
|
OG(output_start_filename) = NULL; |
|
|
|
OG(output_start_lineno) = 0; |
|
|
|
OG(lock) = 0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -88,37 +88,75 @@ PHPAPI int php_header_write(const char *str, uint str_length) |
|
|
|
} |
|
|
|
|
|
|
|
/* Start output buffering */ |
|
|
|
PHPAPI void php_start_ob_buffer() |
|
|
|
PHPAPI int php_start_ob_buffer(zval *output_handler) |
|
|
|
{ |
|
|
|
OLS_FETCH(); |
|
|
|
|
|
|
|
php_ob_init(4096, 1024); |
|
|
|
if (OG(lock)) { |
|
|
|
return FAILURE; |
|
|
|
} |
|
|
|
php_ob_init(4096, 1024, output_handler); |
|
|
|
OG(php_body_write) = php_b_body_write; |
|
|
|
return SUCCESS; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* End output buffering (one level) */ |
|
|
|
PHPAPI void php_end_ob_buffer(int send_buffer) |
|
|
|
{ |
|
|
|
char *final_buffer=NULL; |
|
|
|
int final_buffer_length; |
|
|
|
zval *alternate_buffer=NULL; |
|
|
|
SLS_FETCH(); |
|
|
|
OLS_FETCH(); |
|
|
|
|
|
|
|
if (OG(nesting_level)==0) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (OG(active_ob_buffer).output_handler) { |
|
|
|
zval **params[1]; |
|
|
|
zval *orig_buffer; |
|
|
|
CLS_FETCH(); |
|
|
|
|
|
|
|
ALLOC_INIT_ZVAL(orig_buffer); |
|
|
|
orig_buffer->value.str.val = OG(active_ob_buffer).buffer; |
|
|
|
orig_buffer->value.str.len = OG(active_ob_buffer).text_length; |
|
|
|
orig_buffer->type = IS_STRING; |
|
|
|
orig_buffer->refcount=2; /* don't let call_user_function() destroy our buffer */ |
|
|
|
|
|
|
|
params[0] = &orig_buffer; |
|
|
|
OG(lock) = 1; |
|
|
|
if (call_user_function_ex(CG(function_table), NULL, OG(active_ob_buffer).output_handler, &alternate_buffer, 1, params, 1, NULL)==SUCCESS) { |
|
|
|
convert_to_string_ex(&alternate_buffer); |
|
|
|
final_buffer = alternate_buffer->value.str.val; |
|
|
|
final_buffer_length = alternate_buffer->value.str.len; |
|
|
|
} |
|
|
|
OG(lock) = 0; |
|
|
|
zval_ptr_dtor(&OG(active_ob_buffer).output_handler); |
|
|
|
if (orig_buffer->refcount==2) { /* free the zval */ |
|
|
|
FREE_ZVAL(orig_buffer); |
|
|
|
} else { |
|
|
|
orig_buffer->refcount--; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (!final_buffer) { |
|
|
|
final_buffer = OG(active_ob_buffer).buffer; |
|
|
|
final_buffer_length = OG(active_ob_buffer).text_length; |
|
|
|
} |
|
|
|
if (OG(nesting_level)==1) { /* end buffering */ |
|
|
|
if (SG(headers_sent) && !SG(request_info).headers_only) { |
|
|
|
OG(php_body_write) = php_ub_body_write_no_header; |
|
|
|
} else { |
|
|
|
OG(php_body_write) = php_ub_body_write; |
|
|
|
} |
|
|
|
if (send_buffer) { |
|
|
|
php_ob_send(); |
|
|
|
} |
|
|
|
} else { /* only flush the buffer, if necessary */ |
|
|
|
if (send_buffer) { |
|
|
|
OG(php_body_write)(OG(active_ob_buffer).buffer, OG(active_ob_buffer).text_length); |
|
|
|
} |
|
|
|
} |
|
|
|
if (send_buffer) { |
|
|
|
OG(php_body_write)(final_buffer, final_buffer_length); |
|
|
|
} |
|
|
|
if (alternate_buffer) { |
|
|
|
zval_ptr_dtor(&alternate_buffer); |
|
|
|
} |
|
|
|
php_ob_destroy(); |
|
|
|
} |
|
|
|
@ -170,7 +208,7 @@ static inline void php_ob_allocate(void) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void php_ob_init(uint initial_size, uint block_size) |
|
|
|
static void php_ob_init(uint initial_size, uint block_size, zval *output_handler) |
|
|
|
{ |
|
|
|
OLS_FETCH(); |
|
|
|
|
|
|
|
@ -185,6 +223,7 @@ static void php_ob_init(uint initial_size, uint block_size) |
|
|
|
OG(active_ob_buffer).size = initial_size; |
|
|
|
OG(active_ob_buffer).buffer = (char *) emalloc(initial_size+1); |
|
|
|
OG(active_ob_buffer).text_length = 0; |
|
|
|
OG(active_ob_buffer).output_handler = output_handler; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -245,14 +284,6 @@ static void php_ob_prepend(const char *text, uint text_length) |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
static inline void php_ob_send() |
|
|
|
{ |
|
|
|
OLS_FETCH(); |
|
|
|
|
|
|
|
/* header_write is a simple, unbuffered output function */ |
|
|
|
OG(php_body_write)(OG(active_ob_buffer).buffer, OG(active_ob_buffer).text_length); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Return the current output buffer */ |
|
|
|
int php_ob_get_buffer(pval *p) |
|
|
|
@ -362,7 +393,29 @@ static int php_ub_body_write(const char *str, uint str_length) |
|
|
|
Turn on Output Buffering */ |
|
|
|
PHP_FUNCTION(ob_start) |
|
|
|
{ |
|
|
|
php_start_ob_buffer(); |
|
|
|
zval *output_handler; |
|
|
|
|
|
|
|
switch (ZEND_NUM_ARGS()) { |
|
|
|
case 0: |
|
|
|
output_handler = NULL; |
|
|
|
break; |
|
|
|
case 1: { |
|
|
|
zval **output_handler_p; |
|
|
|
|
|
|
|
if (zend_get_parameters_ex(1, &output_handler_p)==FAILURE) { |
|
|
|
RETURN_FALSE; |
|
|
|
} |
|
|
|
SEPARATE_ZVAL(output_handler_p); |
|
|
|
output_handler = *output_handler_p; |
|
|
|
output_handler->refcount++; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
if (php_start_ob_buffer(output_handler)==FAILURE) { |
|
|
|
php_error(E_WARNING, "Cannot use output buffering in output buffering display handlers"); |
|
|
|
RETURN_FALSE; |
|
|
|
} |
|
|
|
RETURN_TRUE; |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
|