Am Montag, 23. Juni 2003 03:56 schrieb Jeff Trawick:
> (apologies for missing the right mail reference and nasty quoting...
> e-mail problems, and luckily I was browsing the archives on daedalus
> during my ISP-imposed silence)
>
> Philip,
>
> Thanks for submitting the patch.  I hope you will fix minor issues and
> resubmit for further review?

Hi Jeff,

Of course! I am happy that you are willing to help me to get it in.

Please find the new version of the patch attached.

BTW, Please have a close look to the part where I look at the "Content-Type"
header. The old code examien r->content_type. I had to find an other
way, one that is also possible for request filtering...

-Philipp
-- 
: Dipl-Ing Philipp Reisner                      Tel +43-1-8178292-50 :
: LINBIT Information Technologies GmbH          Fax +43-1-8178292-82 :
: Schönbrunnerstr 244, 1120 Vienna, Austria    http://www.linbit.com :
--- mod_ext_filter.c_orig	2003-02-27 13:33:07.000000000 +0100
+++ mod_ext_filter.c	2003-06-23 10:22:07.000000000 +0200
@@ -117,6 +117,9 @@
 static const server_rec *main_server;
 
 static apr_status_t ef_output_filter(ap_filter_t *, apr_bucket_brigade *);
+static apr_status_t ef_input_filter(ap_filter_t *, apr_bucket_brigade *, 
+                                    ap_input_mode_t, apr_read_type_e, 
+                                    apr_off_t);
 
 #define DBGLVL_SHOWOPTIONS         1
 #define DBGLVL_ERRORCHECK          2
@@ -351,12 +354,10 @@
         /* XXX need a way to ensure uniqueness among all filters */
         ap_register_output_filter(filter->name, ef_output_filter, NULL, filter->ftype);
     }
-#if 0              /* no input filters yet */
     else if (filter->mode == INPUT_FILTER) {
         /* XXX need a way to ensure uniqueness among all filters */
-        ap_register_input_filter(filter->name, ef_input_filter, NULL, AP_FTYPE_RESOURCE);
+        ap_register_input_filter(filter->name, ef_input_filter, NULL, filter->ftype);
     }
-#endif
     else {
         ap_assert(1 != 1); /* we set the field wrong somehow */
     }
@@ -592,18 +593,20 @@
     ctx->p = f->r->pool;
     if (ctx->filter->intype &&
         ctx->filter->intype != INTYPE_ALL) {
-        if (!f->r->content_type) {
-            ctx->noop = 1;
-        }
-        else {
-            const char *ctypes = f->r->content_type;
-            const char *ctype = ap_getword(f->r->pool, &ctypes, ';');
-
-            if (strcasecmp(ctx->filter->intype, ctype)) {
-                /* wrong IMT for us; don't mess with the output */
-                ctx->noop = 1;
-            }
-        }
+        const char *ctypes = apr_table_get(ctx->filter->mode == INPUT_FILTER ?
+                                           f->r->headers_in : f->r->headers_out,
+                                           "Content-Type");
+	if(ctypes) {
+	    const char *ctype = ap_getword(f->r->pool, &ctypes, ';');
+        
+	    if (strcasecmp(ctx->filter->intype, ctype)) {
+		/* wrong IMT for us; don't mess with the output */
+		ctx->noop = 1;
+	    }
+	} 
+	else {
+	    ctx->noop = 1;
+	}
     }
     if (ctx->filter->enable_env &&
         !apr_table_get(f->r->subprocess_env, ctx->filter->enable_env)) {
@@ -646,10 +649,11 @@
 
 /* drain_available_output(): 
  *
- * if any data is available from the filter, read it and pass it
- * to the next filter
+ * if any data is available from the filter, read it and append it
+ * to the the bucket brigade
  */
-static apr_status_t drain_available_output(ap_filter_t *f)
+static apr_status_t drain_available_output(ap_filter_t *f,
+                                           apr_bucket_brigade *bb)
 {
     request_rec *r = f->r;
     conn_rec *c = r->connection;
@@ -658,7 +662,6 @@
     apr_size_t len;
     char buf[4096];
     apr_status_t rv;
-    apr_bucket_brigade *bb;
     apr_bucket *b;
 
     while (1) {
@@ -675,14 +678,9 @@
         if (rv != APR_SUCCESS) {
             return rv;
         }
-        bb = apr_brigade_create(r->pool, c->bucket_alloc);
-        b = apr_bucket_transient_create(buf, len, c->bucket_alloc);
+        b = apr_bucket_heap_create(buf, len, NULL, c->bucket_alloc);
         APR_BRIGADE_INSERT_TAIL(bb, b);
-        if ((rv = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
-                          "ap_pass_brigade()");
-            return rv;
-        }
+        return APR_SUCCESS;
     }
     /* we should never get here; if we do, a bogus error message would be
      * the least of our problems 
@@ -691,7 +689,7 @@
 }
 
 static apr_status_t pass_data_to_filter(ap_filter_t *f, const char *data, 
-                                        apr_size_t len)
+                                        apr_size_t len, apr_bucket_brigade *bb)
 {
     ef_ctx_t *ctx = f->ctx;
     ef_dir_t *dc = ctx->dc;
@@ -716,7 +714,7 @@
              * to read data from the child process and pass it down to the
              * next filter!
              */
-            rv = drain_available_output(f);
+            rv = drain_available_output(f, bb);
             if (APR_STATUS_IS_EAGAIN(rv)) {
 #if APR_FILES_AS_SOCKETS
                 int num_events;
@@ -750,7 +748,13 @@
     return rv;
 }
 
-static apr_status_t ef_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
+/* ef_unified_filter: 
+ *
+ * runs the bucket brigade bb through the filter and puts the result into 
+ * bb, dropping the previous content of bb (the input)
+ */
+
+static int ef_unified_filter(ap_filter_t *f, apr_bucket_brigade *bb)
 {
     request_rec *r = f->r;
     conn_rec *c = r->connection;
@@ -762,18 +766,10 @@
     apr_status_t rv;
     char buf[4096];
     apr_bucket *eos = NULL;
+    apr_bucket_brigade *bb_tmp;
 
-    if (!ctx) {
-        if ((rv = init_filter_instance(f)) != APR_SUCCESS) {
-            return rv;
-        }
-        ctx = f->ctx;
-    }
-    if (ctx->noop) {
-        ap_remove_output_filter(f);
-        return ap_pass_brigade(f->next, bb);
-    }
     dc = ctx->dc;
+    bb_tmp = apr_brigade_create(r->pool, c->bucket_alloc);
 
     APR_BRIGADE_FOREACH(b, bb) {
 
@@ -790,17 +786,16 @@
 
         /* Good cast, we just tested len isn't negative */
         if (len > 0 &&
-            (rv = pass_data_to_filter(f, data, (apr_size_t)len)) 
+            (rv = pass_data_to_filter(f, data, (apr_size_t)len, bb_tmp))
                 != APR_SUCCESS) {
             return rv;
         }
     }
 
-    apr_brigade_destroy(bb);
-
-    /* XXX What we *really* need to do once we've hit eos is create a pipe bucket
-     * from the child output pipe and pass down the pipe bucket + eos.
-     */
+    apr_brigade_cleanup(bb);
+    APR_BRIGADE_CONCAT(bb, bb_tmp);
+    apr_brigade_destroy(bb_tmp);
+    
     if (eos) {
         /* close the child's stdin to signal that no more data is coming;
          * that will cause the child to finish generating output
@@ -842,14 +837,8 @@
         }
         
         if (rv == APR_SUCCESS) {
-            bb = apr_brigade_create(r->pool, c->bucket_alloc);
-            b = apr_bucket_transient_create(buf, len, c->bucket_alloc);
+            b = apr_bucket_heap_create(buf, len, NULL, c->bucket_alloc);
             APR_BRIGADE_INSERT_TAIL(bb, b);
-            if ((rv = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
-                              "ap_pass_brigade(filtered buffer) failed");
-                return rv;
-            }
         }
     } while (rv == APR_SUCCESS);
 
@@ -858,55 +847,71 @@
     }
 
     if (eos) {
-        /* pass down eos */
-        bb = apr_brigade_create(r->pool, c->bucket_alloc);
         b = apr_bucket_eos_create(c->bucket_alloc);
         APR_BRIGADE_INSERT_TAIL(bb, b);
-        if ((rv = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
-                          "ap_pass_brigade(eos) failed");
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t ef_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
+{
+    request_rec *r = f->r;
+    ef_ctx_t *ctx = f->ctx;
+    apr_status_t rv;
+
+    if (!ctx) {
+        if ((rv = init_filter_instance(f)) != APR_SUCCESS) {
             return rv;
         }
+        ctx = f->ctx;
+    }
+    if (ctx->noop) {
+        ap_remove_output_filter(f);
+        return ap_pass_brigade(f->next, bb);
     }
 
-    return APR_SUCCESS;
+    rv = ef_unified_filter(f, bb);
+    if( rv != APR_SUCCESS) { 
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+                      "ef_unified_filter() failed");
+    }
+
+    if ((rv = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+                      "ap_pass_brigade() failed");
+    }
+    return rv;
 }
 
-#if 0
 static int ef_input_filter(ap_filter_t *f, apr_bucket_brigade *bb, 
                            ap_input_mode_t mode, apr_read_type_e block,
                            apr_off_t readbytes)
 {
+    request_rec *r = f->r;
+    ef_ctx_t *ctx = f->ctx;
     apr_status_t rv;
-    apr_bucket *b;
-    char *buf;
-    apr_ssize_t len;
-    char *zero;
+
+    if (!ctx) {
+        if ((rv = init_filter_instance(f)) != APR_SUCCESS) {
+            return rv;
+        }
+        ctx = f->ctx;
+    }
+
+    if (ctx->noop) {
+        ap_remove_input_filter(f);
+        return ap_get_brigade(f->next, bb, mode, block, readbytes);
+    }
 
     rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
     if (rv != APR_SUCCESS) {
         return rv;
     }
 
-    APR_BRIGADE_FOREACH(b, bb) {
-        if (!APR_BUCKET_IS_EOS(b)) {
-            if ((rv = apr_bucket_read(b, (const char **)&buf, &len, APR_BLOCK_READ)) != APR_SUCCESS) {
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, "apr_bucket_read() failed");
-                return rv;
-            }
-            ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "apr_bucket_read -> %d bytes",
-                         len);
-            while ((zero = memchr(buf, '0', len))) {
-                *zero = 'a';
-            }
-        }
-        else
-            ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "got eos bucket");
-    }
-
+    rv = ef_unified_filter(f, bb);
     return rv;
 }
-#endif
 
 module AP_MODULE_DECLARE_DATA ext_filter_module =
 {

Reply via email to