]> granicus.if.org Git - php/commitdiff
Patch by Aaron Bannert <aaron@clove.org> and Cliff Woolley <jwoolley@virginia.edu>.
authorSebastian Bergmann <sebastian@php.net>
Thu, 11 Apr 2002 06:01:54 +0000 (06:01 +0000)
committerSebastian Bergmann <sebastian@php.net>
Thu, 11 Apr 2002 06:01:54 +0000 (06:01 +0000)
sapi/apache2filter/php_apache.h
sapi/apache2filter/sapi_apache2.c

index 931f45c28ae53a408e1b281fe8b15fed1c69a570..e758a860e4c06766622b8130f2cca185af009686 100644 (file)
@@ -21,7 +21,6 @@
 
 typedef struct php_struct {
        int state;
-       apr_bucket_brigade *bb;
        ap_filter_t *f;
        /* Length of post_data buffer */
        int post_len;
@@ -29,6 +28,8 @@ typedef struct php_struct {
        int post_idx;
        /* Buffer for request body filter */
        char *post_data;
+       /* Whether or not we've processed PHP in the output filters yet. */
+       int request_processed;
 } php_struct;
 
 int php_apache_register_module(void);
index f671d60a8015714b091eb74a21c4a0ab38e1155c..ef97176ee2bc1306aee81ad0bd287818d0abe433 100644 (file)
@@ -50,26 +50,29 @@ php_apache_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
        apr_bucket_brigade *bb;
        apr_bucket_alloc_t *ba;
        php_struct *ctx;
-       uint now;
 
        ctx = SG(server_context);
 
        if (str_length == 0) return 0;
        
-       ba = ctx->f->r->connection->bucket_alloc;
+       ba = ctx->f->c->bucket_alloc;
        bb = apr_brigade_create(ctx->f->r->pool, ba);
-       while (str_length > 0) {
-               now = MIN(str_length, 4096);
-               b = apr_bucket_transient_create(str, now, ba);
-               APR_BRIGADE_INSERT_TAIL(bb, b);
-               str += now;
-               str_length -= now;
-       }
+
+       b = apr_bucket_transient_create(str, str_length, ba);
+       APR_BRIGADE_INSERT_TAIL(bb, b);
+
+       /* Add a Flush bucket to the end of this brigade, so that
+        * the transient buckets above are more likely to make it out
+        * the end of the filter instead of having to be copied into
+        * someone's setaside. */
+       b = apr_bucket_flush_create(ba);
+       APR_BRIGADE_INSERT_TAIL(bb, b);
+
        if (ap_pass_brigade(ctx->f->next, bb) != APR_SUCCESS) {
                php_handle_aborted_connection();
        }
        
-       return str_length;
+       return 0; /* we wrote everything, we promise! */
 }
 
 static int
@@ -234,13 +237,6 @@ static sapi_module_struct apache2_sapi_module = {
 
 AP_MODULE_DECLARE_DATA module php4_module;
 
-#define INIT_CTX \
-       if (ctx == NULL) { \
-               /* Initialize filter context */ \
-               SG(server_context) = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));  \
-               ctx->bb = apr_brigade_create(f->c->pool, f->c->bucket_alloc); \
-       }
-
 static int php_input_filter(ap_filter_t *f, apr_bucket_brigade *bb, 
                ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes)
 {
@@ -258,7 +254,10 @@ static int php_input_filter(ap_filter_t *f, apr_bucket_brigade *bb,
 
        ctx = SG(server_context);
 
-       INIT_CTX;
+       if (ctx == NULL) {
+               /* Initialize filter context */
+               SG(server_context) = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));
+       }
 
        if ((rv = ap_get_brigade(f->next, bb, mode, block, readbytes)) != APR_SUCCESS) {
                return rv;
@@ -331,79 +330,67 @@ static int php_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
        ap_add_common_vars(f->r);
        ap_add_cgi_vars(f->r);
 
-       ctx = SG(server_context);
-       INIT_CTX;
-
-       ctx->f = f;
-
-       /* states:
-        * 0: request startup
-        * 1: collecting data
-        * 2: script execution and request shutdown
-        */
-       if (ctx->state == 0) {
-       
-               apply_config(conf);
-               
-               ctx->state++;
-
-               php_apache_request_ctor(f, ctx TSRMLS_CC);
+       if (f->ctx == NULL) {
+               /* Initialize filter context */
+               f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));
+               ctx->f = f;
        }
 
-       /* moves all buckets from bb to ctx->bb */
-       ap_save_brigade(f, &ctx->bb, &bb, f->r->pool);
+       if (ctx->request_processed) {
+               return ap_pass_brigade(f->next, bb);
+       }
 
-       /* If we have received all data from the previous filters,
-        * we "flatten" the buckets by creating a single string buffer.
-        */
-       if (ctx->state == 1 && APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(ctx->bb))) {
+       APR_BRIGADE_FOREACH(b, bb) {
                zend_file_handle zfd;
-               apr_bucket *eos;
 
-               /* We want to execute only one script per request.
-                * A bug in Apache or other filters could cause us
-                * to reenter php_filter during script execution, so
-                * we protect ourselves here.
-                */
-               ctx->state = 2;
+               if (!ctx->request_processed && APR_BUCKET_IS_FILE(b)) {
+                       const char *path;
+                       apr_bucket_brigade *prebb = bb;
+
+                       /* Split the brigade into two brigades before and after
+                        * the file bucket. Leave the "after the FILE" brigade
+                        * in the original bb, so it gets passed outside of this
+                        * loop. */
+                       bb = apr_brigade_split(prebb, b);
+
+                       /* Pass the "before the FILE" brigade here
+                        * (if it's non-empty). */
+                       if (!APR_BRIGADE_EMPTY(prebb)) {
+                               apr_status_t rv;
+                               rv = ap_pass_brigade(f->next, prebb);
+                               /* XXX: destroy the prebb, since we know we're
+                                * done with it? */
+                               if (rv != APR_SUCCESS) {
+                                       php_handle_aborted_connection();
+                               }
+                       }
 
-               /* Handle phpinfo/phpcredits/built-in images */
-               if (!php_handle_special_queries(TSRMLS_C)) {
+                       SG(server_context) = ctx;
+                       apply_config(conf);
+                       php_apache_request_ctor(f, ctx TSRMLS_CC);
 
-                       b = APR_BRIGADE_FIRST(ctx->bb);
+                       apr_file_name_get(&path, ((apr_bucket_file *) b->data)->fd);
+                       zfd.type = ZEND_HANDLE_FILENAME;
+                       zfd.filename = (char *) path;
+                       zfd.free_filename = 0;
+                       zfd.opened_path = NULL;
+
+                       php_execute_script(&zfd TSRMLS_CC);
+                       php_apache_request_dtor(f TSRMLS_CC);
                        
-                       if (APR_BUCKET_IS_FILE(b)) {
-                               const char *path;
-
-                               apr_file_name_get(&path, ((apr_bucket_file *) b->data)->fd);
-                               
-                               zfd.type = ZEND_HANDLE_FILENAME;
-                               zfd.filename = (char *) path;
-                               zfd.free_filename = 0;
-                               zfd.opened_path = NULL;
-
-                               php_execute_script(&zfd TSRMLS_CC);
-                       } else {
-                               
-#define PHP_NO_DATA "The PHP Filter did not receive suitable input data"
-                               
-                               eos = apr_bucket_transient_create(PHP_NO_DATA, sizeof(PHP_NO_DATA)-1, f->c->bucket_alloc);
-                               APR_BRIGADE_INSERT_HEAD(bb, eos);
-                       }
-               }
-               
-               php_apache_request_dtor(f TSRMLS_CC);
+                       ctx->request_processed = 1;
 
-               SG(server_context) = 0;
-               /* Pass EOS bucket to next filter to signal end of request */
-               eos = apr_bucket_eos_create(f->c->bucket_alloc);
-               APR_BRIGADE_INSERT_TAIL(bb, eos);
-               
-               return ap_pass_brigade(f->next, bb);
-       } else
-               apr_brigade_destroy(bb);
+                       /* Delete the FILE bucket from the brigade. */
+                       apr_bucket_delete(b);
 
-       return APR_SUCCESS;
+                       /* We won't handle any more buckets in this brigade, so
+                        * it's ok to break out now. */
+                       break;
+               }
+       }
+
+       /* Pass whatever is left on the brigade. */
+       return ap_pass_brigade(f->next, bb);
 }
 
 static apr_status_t
@@ -496,3 +483,5 @@ AP_MODULE_DECLARE_DATA module php4_module = {
  * vim600: sw=4 ts=4 fdm=marker
  * vim<600: sw=4 ts=4
  */
+
+