summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/session/session.c15
-rw-r--r--ext/standard/basic_functions.c5
-rw-r--r--ext/standard/var.c2
-rw-r--r--ext/zlib/zlib.c4
-rw-r--r--main/main.c15
-rw-r--r--main/output.c211
-rw-r--r--main/php_output.h12
7 files changed, 193 insertions, 71 deletions
diff --git a/ext/session/session.c b/ext/session/session.c
index bcfe81aa79..12c626a4c8 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -71,7 +71,7 @@ function_entry session_functions[] = {
PHP_FE(session_set_cookie_params, NULL)
PHP_FE(session_get_cookie_params, NULL)
PHP_FE(session_write_close, NULL)
- {0}
+ {NULL, NULL, NULL}
};
/* }}} */
@@ -95,8 +95,8 @@ static void php_session_start_output_handler(uint chunk_size TSRMLS_DC)
{
php_url_scanner_activate(TSRMLS_C);
php_url_scanner_ex_activate(TSRMLS_C);
- php_start_ob_buffer(NULL, chunk_size TSRMLS_CC);
- php_ob_set_internal_handler(php_session_output_handler, chunk_size TSRMLS_CC);
+ php_start_ob_buffer(NULL, chunk_size, 1 TSRMLS_CC);
+ php_ob_set_internal_handler(php_session_output_handler, chunk_size, "trans sid session", 1 TSRMLS_CC);
PS(output_handler_registered) = 1;
}
@@ -124,9 +124,12 @@ static PHP_INI_MH(OnUpdateSaveHandler)
static PHP_INI_MH(OnUpdateSerializer)
{
PS(serializer) = _php_find_ps_serializer(new_value TSRMLS_CC);
- if(!PS(serializer)) {
- php_error(E_ERROR,"Cannot find serialization handler %s",new_value);
- }
+/* Following lines are commented out to prevent bogus error message at
+ start up. i.e. Serializer modules are not initilzied before Session
+ module. */
+/* if(!PS(serializer)) { */
+/* php_error(E_ERROR,"Cannot find serialization handler %s",new_value); */
+/* } */
return SUCCESS;
}
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index b8310462fc..8033e577b8 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -734,6 +734,7 @@ function_entry basic_functions[] = {
PHP_FE(ob_end_clean, NULL)
PHP_FE(ob_get_length, NULL)
PHP_FE(ob_get_level, NULL)
+ PHP_FE(ob_get_status, NULL)
PHP_FE(ob_get_contents, NULL)
PHP_FE(ob_implicit_flush, NULL)
@@ -1883,7 +1884,7 @@ PHP_FUNCTION(highlight_file)
convert_to_string(filename);
if (i) {
- php_start_ob_buffer (NULL, 0 TSRMLS_CC);
+ php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC);
}
php_get_highlight_struct(&syntax_highlighter_ini);
@@ -1916,7 +1917,7 @@ PHP_FUNCTION(highlight_string)
convert_to_string(expr);
if (i) {
- php_start_ob_buffer (NULL, 0 TSRMLS_CC);
+ php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC);
}
php_get_highlight_struct(&syntax_highlighter_ini);
diff --git a/ext/standard/var.c b/ext/standard/var.c
index ec38e33d56..65fa4e9431 100644
--- a/ext/standard/var.c
+++ b/ext/standard/var.c
@@ -316,7 +316,7 @@ PHP_FUNCTION(var_export)
}
if (i) {
- php_start_ob_buffer (NULL, 0 TSRMLS_CC);
+ php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC);
}
php_var_export(&var, 1 TSRMLS_CC);
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 55e2dda70f..6f0f08d298 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -1283,8 +1283,8 @@ int php_enable_output_compression(int buffer_size TSRMLS_DC)
return FAILURE;
}
- php_start_ob_buffer(NULL, buffer_size TSRMLS_CC);
- php_ob_set_internal_handler(php_gzip_output_handler, buffer_size*1.5 TSRMLS_CC);
+ php_start_ob_buffer(NULL, buffer_size, 0 TSRMLS_CC);
+ php_ob_set_internal_handler(php_gzip_output_handler, buffer_size*1.5, "zlib output compression", 0 TSRMLS_CC);
return SUCCESS;
}
/* }}} */
diff --git a/main/main.c b/main/main.c
index e09e9765e7..069288efc2 100644
--- a/main/main.c
+++ b/main/main.c
@@ -669,14 +669,17 @@ int php_request_startup(TSRMLS_D)
Z_STRLEN_P(output_handler) = strlen(PG(output_handler)); /* this can be optimized */
Z_STRVAL_P(output_handler) = estrndup(PG(output_handler), Z_STRLEN_P(output_handler));
Z_TYPE_P(output_handler) = IS_STRING;
- php_start_ob_buffer(output_handler, 0 TSRMLS_CC);
- } else if (PG(output_buffering)) {
+ php_start_ob_buffer(output_handler, 0, 1 TSRMLS_CC);
+ }
+ else if (PG(output_buffering)) {
if (PG(output_buffering)>1) {
- php_start_ob_buffer(NULL, PG(output_buffering) TSRMLS_CC);
- } else {
- php_start_ob_buffer(NULL, 0 TSRMLS_CC);
+ php_start_ob_buffer(NULL, PG(output_buffering), 1 TSRMLS_CC);
}
- } else if (PG(implicit_flush)) {
+ else {
+ php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC);
+ }
+ }
+ else if (PG(implicit_flush)) {
php_start_implicit_flush(TSRMLS_C);
}
diff --git a/main/output.c b/main/output.c
index 46e6319ed0..58f3504fe4 100644
--- a/main/output.c
+++ b/main/output.c
@@ -29,7 +29,7 @@ static int php_ub_body_write(const char *str, uint str_length TSRMLS_DC);
static int php_ub_body_write_no_header(const char *str, uint str_length TSRMLS_DC);
static int php_b_body_write(const char *str, uint str_length TSRMLS_DC);
-static void php_ob_init(uint initial_size, uint block_size, zval *output_handler, uint chunk_size TSRMLS_DC);
+static void php_ob_init(uint initial_size, uint block_size, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC);
static void php_ob_append(const char *text, uint text_length TSRMLS_DC);
#if 0
static void php_ob_prepend(const char *text, uint text_length);
@@ -110,15 +110,15 @@ PHPAPI int php_header_write(const char *str, uint str_length TSRMLS_DC)
/* {{{ php_start_ob_buffer
* Start output buffering */
-PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size TSRMLS_DC)
+PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC)
{
if (OG(ob_lock)) {
return FAILURE;
}
if (chunk_size) {
- php_ob_init((chunk_size*3/2), chunk_size/2, output_handler, chunk_size TSRMLS_CC);
+ php_ob_init((chunk_size*3/2), chunk_size/2, output_handler, chunk_size, erase TSRMLS_CC);
} else {
- php_ob_init(40*1024, 10*1024, output_handler, chunk_size TSRMLS_CC);
+ php_ob_init(40*1024, 10*1024, output_handler, chunk_size, erase TSRMLS_CC);
}
OG(php_body_write) = php_b_body_write;
return SUCCESS;
@@ -185,6 +185,7 @@ PHPAPI void php_end_ob_buffer(zend_bool send_buffer, zend_bool just_flush TSRMLS
orig_buffer->refcount-=2;
}
zval_ptr_dtor(&z_status);
+ zval_ptr_dtor(&OG(active_ob_buffer).output_handler);
}
if (!final_buffer) {
@@ -283,7 +284,7 @@ PHPAPI void php_end_implicit_flush(TSRMLS_D)
/* {{{ php_ob_set_internal_handler
*/
-PHPAPI void php_ob_set_internal_handler(php_output_handler_func_t internal_output_handler, uint buffer_size TSRMLS_DC)
+PHPAPI void php_ob_set_internal_handler(php_output_handler_func_t internal_output_handler, uint buffer_size, char *handler_name, zend_bool erase TSRMLS_DC)
{
if (OG(ob_nesting_level)==0) {
return;
@@ -292,6 +293,8 @@ PHPAPI void php_ob_set_internal_handler(php_output_handler_func_t internal_outpu
OG(active_ob_buffer).internal_output_handler = internal_output_handler;
OG(active_ob_buffer).internal_output_handler_buffer = (char *) emalloc(buffer_size);
OG(active_ob_buffer).internal_output_handler_buffer_size = buffer_size;
+ OG(active_ob_buffer).handler_name = handler_name;
+ OG(active_ob_buffer).erase = erase;
}
/* }}} */
@@ -315,7 +318,7 @@ static inline void php_ob_allocate(TSRMLS_D)
/* {{{ php_ob_init
*/
-static void php_ob_init(uint initial_size, uint block_size, zval *output_handler, uint chunk_size TSRMLS_DC)
+static void php_ob_init(uint initial_size, uint block_size, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC)
{
if (OG(ob_nesting_level)>0) {
if (OG(ob_nesting_level)==1) { /* initialize stack */
@@ -332,6 +335,18 @@ static void php_ob_init(uint initial_size, uint block_size, zval *output_handler
OG(active_ob_buffer).chunk_size = chunk_size;
OG(active_ob_buffer).status = 0;
OG(active_ob_buffer).internal_output_handler = NULL;
+ if (output_handler && output_handler->type == IS_STRING) {
+ OG(active_ob_buffer).handler_name = Z_STRVAL_P(output_handler);
+ }
+ else if (output_handler && output_handler->type == IS_ARRAY) {
+ /* FIXME: Array type is not supported yet.
+ See call_user_function_ex() for detials. */
+ OG(active_ob_buffer).handler_name = "array is not supported yet";
+ }
+ else {
+ OG(active_ob_buffer).handler_name = "default output handler";
+ }
+ OG(active_ob_buffer).erase = erase;
}
/* }}} */
@@ -478,47 +493,24 @@ static int php_ub_body_write(const char *str, uint str_length TSRMLS_DC)
* HEAD support
*/
-/* {{{ proto void ob_start([ string user_function [, int chunk_size]])
+/* {{{ proto void ob_start([ string user_function [, int chunk_size [, bool erase]]])
Turn on Output Buffering (specifying an optional output handler). */
PHP_FUNCTION(ob_start)
{
zval *output_handler=NULL;
uint chunk_size=0;
+ zend_bool erase=1;
+ int argc = ZEND_NUM_ARGS();
+
+ if (zend_parse_parameters(argc TSRMLS_CC, "|zlb", &output_handler,
+ &chunk_size, &erase) == FAILURE)
+ return;
- switch (ZEND_NUM_ARGS()) {
- case 0:
- 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;
- case 2: {
- zval **output_handler_p, **chunk_size_p;
-
- if (zend_get_parameters_ex(2, &output_handler_p, &chunk_size_p)==FAILURE) {
- RETURN_FALSE;
- }
- if (Z_STRLEN_PP(output_handler_p)>0) {
- SEPARATE_ZVAL(output_handler_p);
- output_handler = *output_handler_p;
- output_handler->refcount++;
- }
- convert_to_long_ex(chunk_size_p);
- chunk_size = (uint) Z_LVAL_PP(chunk_size_p);
- }
- break;
- default:
- ZEND_WRONG_PARAM_COUNT();
- break;
- }
- if (php_start_ob_buffer(output_handler, chunk_size TSRMLS_CC)==FAILURE) {
+ if (output_handler) {
+ SEPARATE_ZVAL(&output_handler);
+ output_handler->refcount++;
+ }
+ if (php_start_ob_buffer(output_handler, chunk_size, erase TSRMLS_CC)==FAILURE) {
if (SG(headers_sent) && !SG(request_info).headers_only) {
OG(php_body_write) = php_ub_body_write_no_header;
} else {
@@ -532,47 +524,91 @@ PHP_FUNCTION(ob_start)
}
/* }}} */
-/* {{{ proto void ob_flush(void)
- Flush (send) the output buffer */
+/* {{{ proto bool ob_flush(void)
+ Flush (send) contents of the output buffers */
PHP_FUNCTION(ob_flush)
{
if (ZEND_NUM_ARGS() != 0)
WRONG_PARAM_COUNT;
+
+ if (!OG(ob_nesting_level)) {
+ php_error(E_NOTICE, "%s() failed to flush buffer. No buffer to flush.",
+ get_active_function_name(TSRMLS_C));
+ RETURN_FALSE;
+ }
php_end_ob_buffer(1, 1 TSRMLS_CC);
+ RETURN_TRUE;
}
/* }}} */
-/* {{{ proto void ob_clean(void)
- Clean (erase) the output buffer */
+/* {{{ proto bool ob_clean(void)
+ Clean (delete) the current output buffer */
PHP_FUNCTION(ob_clean)
{
if (ZEND_NUM_ARGS() != 0)
WRONG_PARAM_COUNT;
-
+
+
+ if (!OG(ob_nesting_level)) {
+ php_error(E_NOTICE, "%s() failed to delete buffer. No buffer to delete.",
+ get_active_function_name(TSRMLS_C));
+ RETURN_FALSE;
+ }
+ if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) {
+ php_error(E_NOTICE, "%s() failed to delete buffer %s.",
+ get_active_function_name(TSRMLS_C), OG(active_ob_buffer).handler_name);
+ RETURN_FALSE;
+ }
+
php_end_ob_buffer(0, 1 TSRMLS_CC);
+ RETURN_TRUE;
}
/* }}} */
-/* {{{ proto void ob_end_flush(void)
- Flush (send) the output buffer, and turn off output buffering */
+/* {{{ proto bool ob_end_flush(void)
+ Flush (send) the output buffer, and delete current output buffer */
PHP_FUNCTION(ob_end_flush)
{
if (ZEND_NUM_ARGS() != 0)
WRONG_PARAM_COUNT;
-
+
+ if (!OG(ob_nesting_level)) {
+ php_error(E_NOTICE, "%s() failed to delete and flush buffer. No buffer to delete or flush.",
+ get_active_function_name(TSRMLS_C));
+ RETURN_FALSE;
+ }
+ if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) {
+ php_error(E_NOTICE, "%s() failed to delete buffer %s.",
+ get_active_function_name(TSRMLS_C), OG(active_ob_buffer).handler_name);
+ RETURN_FALSE;
+ }
+
php_end_ob_buffer(1, 0 TSRMLS_CC);
+ RETURN_TRUE;
}
/* }}} */
-/* {{{ proto void ob_end_clean(void)
- Clean (erase) the output buffer, and turn off output buffering */
+/* {{{ proto bool ob_end_clean(void)
+ Clean the output buffer, and delete current output buffer */
PHP_FUNCTION(ob_end_clean)
{
if (ZEND_NUM_ARGS() != 0)
WRONG_PARAM_COUNT;
+ if (!OG(ob_nesting_level)) {
+ php_error(E_NOTICE, "%s() failed to delete buffer. No buffer to delete.",
+ get_active_function_name(TSRMLS_C));
+ RETURN_FALSE;
+ }
+ if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) {
+ php_error(E_NOTICE, "%s() failed to delete buffer %s.",
+ get_active_function_name(TSRMLS_C), OG(active_ob_buffer).handler_name);
+ RETURN_FALSE;
+ }
+
php_end_ob_buffer(0, 0 TSRMLS_CC);
+ RETURN_TRUE;
}
/* }}} */
@@ -613,6 +649,79 @@ PHP_FUNCTION(ob_get_length)
}
/* }}} */
+static int php_ob_buffer_status(php_ob_buffer *ob_buffer, zval *result)
+{
+ zval *elem;
+
+ MAKE_STD_ZVAL(elem);
+ if (array_init(elem))
+ return FAILURE;
+
+ if (ob_buffer->internal_output_handler) {
+ add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_INTERNAL);
+ }
+ else {
+ add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_USER);
+ }
+ add_assoc_long(elem, "status", ob_buffer->status);
+ add_assoc_string(elem, "name", ob_buffer->handler_name, 1);
+ add_assoc_bool(elem, "del", ob_buffer->erase);
+ add_next_index_zval(result, elem);
+
+ return SUCCESS;
+}
+
+
+/* {{{ poto array ob_get_status([bool full_status])
+ Return the nesting level of the output buffer */
+PHP_FUNCTION(ob_get_status)
+{
+ int argc = ZEND_NUM_ARGS();
+ zend_bool full_status = 0;
+
+ if (zend_parse_parameters(argc TSRMLS_CC, "|b", &full_status) == FAILURE )
+ return;
+
+ if (array_init(return_value) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (full_status) {
+ zval *elem;
+
+ zend_stack_apply_with_argument(&OG(ob_buffers), ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *elem, void *))php_ob_buffer_status, return_value);
+
+ MAKE_STD_ZVAL(elem);
+ if (array_init(elem))
+ RETURN_FALSE;
+
+ if (OG(active_ob_buffer).internal_output_handler) {
+ add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_INTERNAL);
+ }
+ else {
+ add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_USER);
+ }
+ add_assoc_long(elem, "status", OG(active_ob_buffer).status);
+ add_assoc_string(elem, "name", OG(active_ob_buffer).handler_name, 1);
+ add_assoc_bool(elem, "del", OG(active_ob_buffer).erase);
+ add_next_index_zval(return_value, elem);
+ }
+ else {
+ add_assoc_long(return_value, "level", OG(ob_nesting_level));
+ if (OG(active_ob_buffer).internal_output_handler) {
+ add_assoc_long(return_value, "type", PHP_OUTPUT_HANDLER_INTERNAL);
+ }
+ else {
+ add_assoc_long(return_value, "type", PHP_OUTPUT_HANDLER_USER);
+ }
+ add_assoc_long(return_value, "status", OG(active_ob_buffer).status);
+ add_assoc_string(return_value, "name", OG(active_ob_buffer).handler_name, 1);
+ add_assoc_bool(return_value, "del", OG(active_ob_buffer).erase);
+ }
+}
+/* }}} */
+
+
/* {{{ proto void ob_implicit_flush([int flag])
Turn implicit flush on/off and is equivalent to calling flush() after every output call */
PHP_FUNCTION(ob_implicit_flush)
diff --git a/main/php_output.h b/main/php_output.h
index 4a6b5f1ae2..f1a8069ce1 100644
--- a/main/php_output.h
+++ b/main/php_output.h
@@ -29,7 +29,7 @@ PHPAPI void php_output_set_status(zend_bool status TSRMLS_DC);
void php_output_register_constants(TSRMLS_D);
PHPAPI int php_body_write(const char *str, uint str_length TSRMLS_DC);
PHPAPI int php_header_write(const char *str, uint str_length TSRMLS_DC);
-PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size TSRMLS_DC);
+PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC);
PHPAPI void php_end_ob_buffer(zend_bool send_buffer, zend_bool just_flush TSRMLS_DC);
PHPAPI void php_end_ob_buffers(zend_bool send_buffer TSRMLS_DC);
PHPAPI int php_ob_get_buffer(zval *p TSRMLS_DC);
@@ -38,7 +38,7 @@ PHPAPI void php_start_implicit_flush(TSRMLS_D);
PHPAPI void php_end_implicit_flush(TSRMLS_D);
PHPAPI char *php_get_output_start_filename(TSRMLS_D);
PHPAPI int php_get_output_start_lineno(TSRMLS_D);
-PHPAPI void php_ob_set_internal_handler(php_output_handler_func_t internal_output_handler, uint buffer_size TSRMLS_DC);
+PHPAPI void php_ob_set_internal_handler(php_output_handler_func_t internal_output_handler, uint buffer_size, char *handler_name, zend_bool erase TSRMLS_DC);
PHP_FUNCTION(ob_start);
PHP_FUNCTION(ob_flush);
@@ -48,6 +48,7 @@ PHP_FUNCTION(ob_end_clean);
PHP_FUNCTION(ob_get_contents);
PHP_FUNCTION(ob_get_length);
PHP_FUNCTION(ob_get_level);
+PHP_FUNCTION(ob_get_status);
PHP_FUNCTION(ob_implicit_flush);
typedef struct _php_ob_buffer {
@@ -61,6 +62,8 @@ typedef struct _php_ob_buffer {
php_output_handler_func_t internal_output_handler;
char *internal_output_handler_buffer;
uint internal_output_handler_buffer_size;
+ char *handler_name;
+ zend_bool erase;
} php_ob_buffer;
typedef struct _php_output_globals {
@@ -76,7 +79,6 @@ typedef struct _php_output_globals {
zend_bool disable_output;
} php_output_globals;
-
#ifdef ZTS
#define OG(v) TSRMG(output_globals_id, php_output_globals *, v)
ZEND_API extern int output_globals_id;
@@ -89,4 +91,8 @@ ZEND_API extern php_output_globals output_globals;
#define PHP_OUTPUT_HANDLER_CONT (1<<1)
#define PHP_OUTPUT_HANDLER_END (1<<2)
+#define PHP_OUTPUT_HANDLER_INTERNAL 0
+#define PHP_OUTPUT_HANDLER_USER 1
+
+
#endif /* PHP_OUTPUT_H */