]> granicus.if.org Git - php/commitdiff
@- Added support for an optional output handler function for output
authorZeev Suraski <zeev@php.net>
Sat, 2 Sep 2000 18:03:58 +0000 (18:03 +0000)
committerZeev Suraski <zeev@php.net>
Sat, 2 Sep 2000 18:03:58 +0000 (18:03 +0000)
@  buffering.  This enables transparent rendering of XML through XSL,
@  transparent compression, etc. (Zeev)

ext/standard/output.c
ext/standard/php_output.h
main/main.c
main/output.c
main/php_output.h

index 253b4294cf4b21f76a47952be8ae0d9e76ef8a04..248c4a16cb2ce95a980a88e84def8dc0c50dc1ce 100644 (file)
@@ -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;
 }
 /* }}} */
 
index cb43c8cb7f2ae8ff6f3147b9a7796fb0308ed2e7..7d2269879664d7ef9d8cc4d4da583505fab2a79b 100644 (file)
@@ -26,7 +26,7 @@
 PHPAPI void php_output_startup(void);
 PHPAPI int  php_body_write(const char *str, uint str_length);
 PHPAPI int  php_header_write(const char *str, uint str_length);
-PHPAPI void php_start_ob_buffer(void);
+PHPAPI int php_start_ob_buffer(zval *output_handler);
 PHPAPI void php_end_ob_buffer(int send_buffer);
 PHPAPI void php_end_ob_buffers(int send_buffer);
 PHPAPI int php_ob_get_buffer(pval *p);
@@ -50,6 +50,7 @@ typedef struct _php_ob_buffer {
        uint size;
        uint text_length;
        int block_size;
+       zval *output_handler;
 } php_ob_buffer;
 
 typedef struct _php_output_globals {
@@ -61,6 +62,7 @@ typedef struct _php_output_globals {
        int output_start_lineno;
        zend_stack ob_buffers;
        int nesting_level;
+       zend_bool lock;
 } php_output_globals;
 
 
index 7b10e2f3332eb6df92010cb6e3e451972e1c004a..a3887075f14dbc15ddff537b698ff5fb18596173 100644 (file)
@@ -607,7 +607,7 @@ int php_request_startup(CLS_D ELS_DC PLS_DC SLS_DC)
        }
 
        if (PG(output_buffering)) {
-               php_start_ob_buffer();
+               php_start_ob_buffer(NULL);
        } else if (PG(implicit_flush)) {
                php_start_implicit_flush();
        }
index 253b4294cf4b21f76a47952be8ae0d9e76ef8a04..248c4a16cb2ce95a980a88e84def8dc0c50dc1ce 100644 (file)
@@ -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;
 }
 /* }}} */
 
index cb43c8cb7f2ae8ff6f3147b9a7796fb0308ed2e7..7d2269879664d7ef9d8cc4d4da583505fab2a79b 100644 (file)
@@ -26,7 +26,7 @@
 PHPAPI void php_output_startup(void);
 PHPAPI int  php_body_write(const char *str, uint str_length);
 PHPAPI int  php_header_write(const char *str, uint str_length);
-PHPAPI void php_start_ob_buffer(void);
+PHPAPI int php_start_ob_buffer(zval *output_handler);
 PHPAPI void php_end_ob_buffer(int send_buffer);
 PHPAPI void php_end_ob_buffers(int send_buffer);
 PHPAPI int php_ob_get_buffer(pval *p);
@@ -50,6 +50,7 @@ typedef struct _php_ob_buffer {
        uint size;
        uint text_length;
        int block_size;
+       zval *output_handler;
 } php_ob_buffer;
 
 typedef struct _php_output_globals {
@@ -61,6 +62,7 @@ typedef struct _php_output_globals {
        int output_start_lineno;
        zend_stack ob_buffers;
        int nesting_level;
+       zend_bool lock;
 } php_output_globals;