Return-Path: Delivered-To: apmail-httpd-dev-archive@httpd.apache.org Received: (qmail 32839 invoked by uid 500); 23 Jun 2003 08:26:46 -0000 Mailing-List: contact dev-help@httpd.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@httpd.apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list dev@httpd.apache.org Received: (qmail 32826 invoked from network); 23 Jun 2003 08:26:45 -0000 From: Philipp Reisner To: dev@httpd.apache.org, Jeff Trawick Subject: Re: input filters with mod_ext_filter [patch] Date: Mon, 23 Jun 2003 10:26:55 +0200 User-Agent: KMail/1.5.1 References: <3EF65E4C.70303@attglobal.net> In-Reply-To: <3EF65E4C.70303@attglobal.net> MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_Pnr9+2tuht9EA5l" Message-Id: <200306231026.56008.philipp.reisner@linbit.com> X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N --Boundary-00=_Pnr9+2tuht9EA5l Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 8bit Content-Disposition: inline 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 : --Boundary-00=_Pnr9+2tuht9EA5l Content-Type: text/x-diff; charset="iso-8859-1"; name="diff2" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="diff2" --- 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 = { --Boundary-00=_Pnr9+2tuht9EA5l--