From: Ryan Bloom Date: Sun, 3 Mar 2002 06:04:08 +0000 (+0000) Subject: This finishes the mod_dir/mod_negotiation bug. This final part of the X-Git-Tag: 2.0.33~47 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0d7f234515f2bd22cfadc300a53c169ed42df506;p=thirdparty%2Fapache%2Fhttpd.git This finishes the mod_dir/mod_negotiation bug. This final part of the solution ensures that we don't lose filters if they are added later than we expect. The problem could be seen if a connection filter was added after a request-based filter was added in the past. The problem was that the request-based filters pointed to the first filter in the connection record, so the new connection filter was never called. Now, all filters are put on their correct filter lists, and we are sure to always update all pointers when adding a filter. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@93683 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/STATUS b/STATUS index 6deb0b81455..d01d075ff00 100644 --- a/STATUS +++ b/STATUS @@ -1,5 +1,5 @@ APACHE 2.0 STATUS: -*-text-*- -Last modified at [$Date: 2002/03/02 19:10:07 $] +Last modified at [$Date: 2002/03/03 06:04:08 $] Release: @@ -50,19 +50,6 @@ CURRENT RELEASE NOTES: FINAL RELEASE SHOWSTOPPERS: - * All ap_internal_fast_redirect()ed requests are losing their filters - and output headers. mod_negotiation derived Multiviewed documents - and mod_dir DirectoryIndex documents both demonstrate this behavior. - [PR 9963, 10001] - cf reply: <007c01c1b3d1$46714650$94c0b0d0@v505> - to thread: <200202121332.IAA27467@web.turner.com> - Solutions: - Ditch fast_redirect, it was bogus in 1.3 and it's bogus now. - In Agreement? : Justin, Aaron - Fix [and *Maintain*] fast_redirect, it was useful to our redirects - in negotiation and dir, and it's useful to 3rd parties. - In Agreement? : - * If any request gets to the core handler, without a flag that this r->filename was tested by dir/file_walk, we need to 500 at the very end of the ap_process_request_internal() processing. This provides diff --git a/include/util_filter.h b/include/util_filter.h index 19d845afb96..60ea804b94b 100644 --- a/include/util_filter.h +++ b/include/util_filter.h @@ -263,6 +263,9 @@ struct ap_filter_t { /** The next filter in the chain */ ap_filter_t *next; + /** The previous filter in the chain */ + ap_filter_t *prev; + /** The request_rec associated with the current filter. If a sub-request * adds filters, then the sub-request is the request associated with the * filter. diff --git a/server/util_filter.c b/server/util_filter.c index e457aaf9c98..5b37a91239b 100644 --- a/server/util_filter.c +++ b/server/util_filter.c @@ -330,7 +330,31 @@ 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 ? r_filters : p_filters) : c_filters; + ap_filter_t **outf; + + if (node->frec->ftype < AP_FTYPE_HTTP_HEADER) { + if (r) { + outf = r_filters; + } + else { + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, NULL, + "a content filter was added without a request: %s", name); + return NULL; + } + } + else if (node->frec->ftype < AP_FTYPE_CONNECTION) { + if (r) { + outf = p_filters; + } + else { + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, NULL, + "a protocol filter was added without a request: %s", name); + return NULL; + } + } + else { + outf = c_filters; + } f->frec = node->frec; f->ctx = ctx; @@ -339,13 +363,24 @@ static ap_filter_t *add_any_filter(const char *name, void *ctx, if (INSERT_BEFORE(f, *outf)) { f->next = *outf; + if ((*outf) && (*outf)->prev) { + f->prev = (*outf)->prev; + (*outf)->prev->next = f; + (*outf)->prev = f; + } + else { + f->prev = NULL; + } *outf = f; } else { ap_filter_t *fscan = *outf; while (!INSERT_BEFORE(f, fscan->next)) fscan = fscan->next; + f->next = fscan->next; + f->prev = fscan; + fscan->next->prev = f; fscan->next = f; } @@ -366,7 +401,31 @@ static ap_filter_t *add_any_filter_handle(ap_filter_rec_t *frec, void *ctx, { 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 ? r_filters : p_filters) : c_filters; + ap_filter_t **outf; + + if (frec->ftype < AP_FTYPE_HTTP_HEADER) { + if (r) { + outf = r_filters; + } + else { + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, NULL, + "a content filter was added without a request: %s", frec->name); + return NULL; + } + } + else if (frec->ftype < AP_FTYPE_CONNECTION) { + if (r) { + outf = p_filters; + } + else { + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, NULL, + "a protocol filter was added without a request: %s", frec->name); + return NULL; + } + } + else { + outf = c_filters; + } f->frec = frec; f->ctx = ctx; @@ -375,13 +434,24 @@ static ap_filter_t *add_any_filter_handle(ap_filter_rec_t *frec, void *ctx, if (INSERT_BEFORE(f, *outf)) { f->next = *outf; + if ((*outf) && (*outf)->prev) { + f->prev = (*outf)->prev; + (*outf)->prev->next = f; + (*outf)->prev = f; + } + else { + f->prev = NULL; + } *outf = f; } else { ap_filter_t *fscan = *outf; while (!INSERT_BEFORE(f, fscan->next)) fscan = fscan->next; + f->next = fscan->next; + f->prev = fscan; + fscan->next->prev = f; fscan->next = f; }