From fd8791dd22ca2c2bd907fc820a0b0175011b0118 Mon Sep 17 00:00:00 2001 From: Ryan Bloom Date: Sun, 3 Mar 2002 02:15:52 +0000 Subject: [PATCH] Fix the mod_dir/mod_negotiation bug, where redirects and sub requests were not getting the correct filters. This is done by creating a location in the request rec that holds protocol level filters. Protocol level filters survive for one request, from the time the request is received from the user to the time the response is sent. r->output_filters now stores the request level filters, which are only valid for the lifetime of one request_rec. This patch works, but it is not complete. The second half of the problem is that add_any_filter doesn't check where it puts the filters that it adds, so it is possible for filters to be put on this wrong list, and for filters to be lost completely during request processing. That half of the fix will be coming in the next day or so. Submitted by: Will Rowe, Justin Erenkrantz, Ryan Bloom git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@93682 13f79535-47bb-0310-9956-ffa450edef68 --- include/httpd.h | 8 ++++++++ modules/http/http_request.c | 10 ++++++++-- server/protocol.c | 6 ++++-- server/request.c | 16 +++++++++++++--- server/util_filter.c | 16 +++++++++++----- 5 files changed, 44 insertions(+), 12 deletions(-) diff --git a/include/httpd.h b/include/httpd.h index c6f6d1da8f..fa57f98183 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -905,6 +905,14 @@ struct request_rec { struct ap_filter_t *output_filters; /** A list of input filters to be used for this request */ struct ap_filter_t *input_filters; + + /** A list of protocol level output filters to be used for this + * request */ + struct ap_filter_t *proto_output_filters; + /** A list of protocol level input filters to be used for this + * request */ + struct ap_filter_t *proto_input_filters; + /** A flag to determine if the eos bucket has been sent yet */ int eos_sent; diff --git a/modules/http/http_request.c b/modules/http/http_request.c index 244c346cf1..b1763edbe9 100644 --- a/modules/http/http_request.c +++ b/modules/http/http_request.c @@ -391,8 +391,11 @@ static request_rec *internal_internal_redirect(const char *new_uri, new->read_length = r->read_length; /* We can only read it once */ new->vlist_validator = r->vlist_validator; - new->output_filters = r->connection->output_filters; - new->input_filters = r->connection->input_filters; + new->proto_output_filters = r->proto_output_filters; + new->proto_input_filters = r->proto_input_filters; + + new->output_filters = new->proto_output_filters; + new->input_filters = new->proto_input_filters; ap_add_input_filter("HTTP_IN", NULL, new, new->connection); @@ -441,6 +444,9 @@ AP_DECLARE(void) ap_internal_fast_redirect(request_rec *rr, request_rec *r) r->err_headers_out); r->subprocess_env = apr_table_overlay(r->pool, rr->subprocess_env, r->subprocess_env); + + r->output_filters = rr->output_filters; + r->input_filters = rr->input_filters; } AP_DECLARE(void) ap_internal_redirect(const char *new_uri, request_rec *r) diff --git a/server/protocol.c b/server/protocol.c index 923c6de854..a902d55a17 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -776,8 +776,10 @@ request_rec *ap_read_request(conn_rec *conn) r->request_config = ap_create_request_config(r->pool); /* Must be set before we run create request hook */ - r->output_filters = conn->output_filters; - r->input_filters = conn->input_filters; + r->proto_output_filters = conn->output_filters; + r->output_filters = r->proto_output_filters; + r->proto_input_filters = conn->input_filters; + r->input_filters = r->proto_input_filters; ap_run_create_request(r); r->per_dir_config = r->server->lookup_defaults; diff --git a/server/request.c b/server/request.c index 7d3cc6c22b..69d6df5954 100644 --- a/server/request.c +++ b/server/request.c @@ -1492,13 +1492,23 @@ static request_rec *make_sub_request(const request_rec *r, /* start with the same set of output filters */ if (next_filter) { + /* no input filters for a subrequest */ rnew->output_filters = next_filter; + ap_add_output_filter_handle(ap_subreq_core_filter_handle, + NULL, rnew, rnew->connection); } else { - rnew->output_filters = r->output_filters; + /* If NULL - we are expecting to be internal_fast_redirect'ed + * to this subrequest - or this request will never be invoked. + * Ignore the original request filter stack entirely, and + * drill the input and output stacks back to the connection. + */ + rnew->proto_input_filters = r->proto_input_filters; + rnew->proto_output_filters = r->proto_output_filters; + + rnew->input_filters = r->proto_input_filters; + rnew->output_filters = r->proto_output_filters; } - ap_add_output_filter_handle(ap_subreq_core_filter_handle, - NULL, rnew, rnew->connection); /* no input filters for a subrequest */ diff --git a/server/util_filter.c b/server/util_filter.c index afc0731de2..e457aaf9c9 100644 --- a/server/util_filter.c +++ b/server/util_filter.c @@ -294,7 +294,8 @@ AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter(const char *name, static ap_filter_t *add_any_filter(const char *name, void *ctx, request_rec *r, conn_rec *c, const filter_trie_node *reg_filter_set, - ap_filter_t **r_filters, + ap_filter_t **r_filters, + ap_filter_t **p_filters, ap_filter_t **c_filters) { if (reg_filter_set) { @@ -329,7 +330,7 @@ static ap_filter_t *add_any_filter(const char *name, void *ctx, if (node && node->frec) { apr_pool_t* p = r ? r->pool : c->pool; ap_filter_t *f = apr_palloc(p, sizeof(*f)); - ap_filter_t **outf = r ? r_filters : c_filters; + ap_filter_t **outf = r ? (r_filters ? r_filters : p_filters) : c_filters; f->frec = node->frec; f->ctx = ctx; @@ -360,11 +361,12 @@ static ap_filter_t *add_any_filter(const char *name, void *ctx, static ap_filter_t *add_any_filter_handle(ap_filter_rec_t *frec, void *ctx, request_rec *r, conn_rec *c, ap_filter_t **r_filters, + ap_filter_t **p_filters, ap_filter_t **c_filters) { apr_pool_t* p = r ? r->pool : c->pool; ap_filter_t *f = apr_palloc(p, sizeof(*f)); - ap_filter_t **outf = r ? r_filters : c_filters; + ap_filter_t **outf = r ? (r_filters ? r_filters : p_filters) : c_filters; f->frec = frec; f->ctx = ctx; @@ -390,7 +392,8 @@ AP_DECLARE(ap_filter_t *) ap_add_input_filter(const char *name, void *ctx, request_rec *r, conn_rec *c) { return add_any_filter(name, ctx, r, c, registered_input_filters, - r ? &r->input_filters : NULL, &c->input_filters); + r ? &r->input_filters : NULL, + r ? &r->proto_input_filters : NULL, &c->input_filters); } AP_DECLARE(ap_filter_t *) ap_add_input_filter_handle(ap_filter_rec_t *f, @@ -399,6 +402,7 @@ AP_DECLARE(ap_filter_t *) ap_add_input_filter_handle(ap_filter_rec_t *f, conn_rec *c) { return add_any_filter_handle(f, ctx, r, c, r ? &r->input_filters : NULL, + r ? &r->proto_input_filters : NULL, &c->input_filters); } @@ -406,7 +410,8 @@ AP_DECLARE(ap_filter_t *) ap_add_output_filter(const char *name, void *ctx, request_rec *r, conn_rec *c) { return add_any_filter(name, ctx, r, c, registered_output_filters, - r ? &r->output_filters : NULL, &c->output_filters); + r ? &r->output_filters : NULL, + r ? &r->proto_output_filters : NULL, &c->output_filters); } AP_DECLARE(ap_filter_t *) ap_add_output_filter_handle(ap_filter_rec_t *f, @@ -415,6 +420,7 @@ AP_DECLARE(ap_filter_t *) ap_add_output_filter_handle(ap_filter_rec_t *f, conn_rec *c) { return add_any_filter_handle(f, ctx, r, c, r ? &r->output_filters : NULL, + r ? &r->proto_output_filters : NULL, &c->output_filters); } -- 2.50.1