From: Nick Kew Date: Wed, 27 Oct 2004 10:46:26 +0000 (+0000) Subject: Fix mod_filter to support the case where a provider sets its own f->ctx X-Git-Tag: 2.1.1~93 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8bed492892a7da3d05e2f77ea6619e7522b25b19;p=apache Fix mod_filter to support the case where a provider sets its own f->ctx in its filter_init [grumble about filter_init ....] git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@105604 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/experimental/mod_filter.c b/modules/experimental/mod_filter.c index 4d9e7d0bca..9de4cb7a8a 100644 --- a/modules/experimental/mod_filter.c +++ b/modules/experimental/mod_filter.c @@ -77,9 +77,17 @@ struct ap_filter_provider_t { ap_filter_provider_t *next; }; +/** we need provider_ctx to save ctx values set by providers in filter_init */ +typedef struct provider_ctx provider_ctx; +struct provider_ctx { + ap_filter_provider_t *provider; + void *ctx; + provider_ctx *next; +}; typedef struct { ap_out_filter_func func; void *fctx; + provider_ctx *init_ctx; } harness_ctx; typedef struct mod_filter_chain { @@ -119,30 +127,43 @@ static void filter_trace(apr_pool_t *pool, int debug, const char *fname, static int filter_init(ap_filter_t *f) { ap_filter_provider_t *p; + provider_ctx *pctx; int err; ap_filter_rec_t *filter = f->frec; - f->ctx = apr_pcalloc(f->r->pool, sizeof(harness_ctx)); + harness_ctx *fctx = apr_pcalloc(f->r->pool, sizeof(harness_ctx)); for (p = filter->providers; p; p = p->next) { if (p->frec->filter_init_func) { + f->ctx = NULL; if ((err = p->frec->filter_init_func(f)) != OK) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, "filter_init for %s failed", p->frec->name); return err; /* if anyone errors out here, so do we */ } + if (f->ctx != NULL) { + /* the filter init function set a ctx - we need to record it */ + pctx = apr_pcalloc(f->r->pool, sizeof(provider_ctx)); + pctx->provider = p; + pctx->ctx = f->ctx; + pctx->next = fctx->init_ctx; + fctx->init_ctx = pctx; + } } } - + f->ctx = fctx; return OK; } -static ap_out_filter_func filter_lookup(request_rec *r, ap_filter_rec_t *filter) +static int filter_lookup(ap_filter_t *f, ap_filter_rec_t *filter) { ap_filter_provider_t *provider; const char *str = NULL; char *str1; int match; unsigned int proto_flags; + request_rec *r = f->r; + harness_ctx *ctx = f->ctx; + provider_ctx *pctx; /* Check registered providers in order */ for (provider = filter->providers; provider; provider = provider->next) { @@ -290,12 +311,18 @@ static ap_out_filter_func filter_lookup(request_rec *r, ap_filter_rec_t *filter) apr_table_setn(r->headers_in, "Range", filter->range); } #endif - return provider->frec->filter_func.out_func; + for (pctx = ctx->init_ctx; pctx; pctx = pctx->next) { + if (pctx->provider == provider) { + ctx->fctx = pctx->ctx ; + } + } + ctx->func = provider->frec->filter_func.out_func; + return 1; } } /* No provider matched */ - return NULL; + return 0; } static apr_status_t filter_harness(ap_filter_t *f, apr_bucket_brigade *bb) @@ -336,8 +363,7 @@ static apr_status_t filter_harness(ap_filter_t *f, apr_bucket_brigade *bb) } } #endif - ctx->func = filter_lookup(f->r, filter); - if (!ctx->func) { + if (!filter_lookup(f, filter)) { ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); } @@ -367,7 +393,7 @@ static const char *filter_protocol(cmd_parms *cmd, void *CFG, const char *fname, ap_filter_rec_t *filter = apr_hash_get(cfg->live_filters, fname, APR_HASH_KEY_STRING); - if (!provider) { + if (!filter) { return "FilterProtocol: No such filter"; }