From: Ruediger Pluem Date: Fri, 4 Jul 2008 10:54:36 +0000 (+0000) Subject: * Prevent Header edit from processing only the first header it should X-Git-Tag: 2.3.0~440 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=86efa65bf875e81f44e8f1f9043257eebfe21b41;p=thirdparty%2Fapache%2Fhttpd.git * Prevent Header edit from processing only the first header it should edit and deleting the remaining ones by iterating over all headers with the same name. PR: 45333 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@674000 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index fb64b7feb7c..7e1c35a0bb6 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,11 @@ Changes with Apache 2.3.0 [ When backported to 2.2.x, remove entry from this file ] + + *) mod_headers: Prevent Header edit from processing only the first header + of possibly multiple headers with the same name and deleting the + remaining ones. PR 45333. [Ruediger Pluem] + *) mod_auth_digest: Detect during startup when AuthDigestProvider is configured to use an incompatible provider via AuthnProviderAlias. PR 45196 [Eric Covener] diff --git a/modules/metadata/mod_headers.c b/modules/metadata/mod_headers.c index d35c44f14b2..8e748fa9d74 100644 --- a/modules/metadata/mod_headers.c +++ b/modules/metadata/mod_headers.c @@ -133,6 +133,13 @@ typedef struct { header_entry *hdr; } echo_do; +/* edit_do is used for Header edit to iterate through the request headers */ +typedef struct { + apr_pool_t *p; + header_entry *hdr; + apr_table_t *t; +} edit_do; + /* * headers_conf is our per-module configuration. This is used as both * a per-dir and per-server config @@ -578,6 +585,22 @@ static int echo_header(echo_do *v, const char *key, const char *val) return 1; } +static int edit_header(void *v, const char *key, const char *val) +{ + edit_do *ed = (edit_do *)v; + + apr_table_addn(ed->t, key, process_regexp(ed->hdr, val, ed->p)); + return 1; +} + +static int add_them_all(void *v, const char *key, const char *val) +{ + apr_table_t *headers = (apr_table_t *)v; + + apr_table_addn(headers, key, val); + return 1; +} + static void do_headers_fixup(request_rec *r, apr_table_t *headers, apr_array_header_t *fixup, int early) { @@ -669,10 +692,16 @@ static void do_headers_fixup(request_rec *r, apr_table_t *headers, echo_header, (void *) &v, r->headers_in, NULL); break; case hdr_edit: - val = apr_table_get(headers, hdr->header); - if (val != NULL) { - apr_table_setn(headers, hdr->header, - process_regexp(hdr, val, r->pool)); + if (apr_table_get(headers, hdr->header)) { + edit_do ed; + + ed.p = r->pool; + ed.hdr = hdr; + ed.t = apr_table_make(r->pool, 5); + apr_table_do(edit_header, (void *) &ed, headers, hdr->header, + NULL); + apr_table_unset(headers, hdr->header); + apr_table_do(add_them_all, (void *) headers, ed.t, NULL); } break; }