From e8a15ec117f75235ff463a31edb7f2d0285c4300 Mon Sep 17 00:00:00 2001 From: Jim Jagielski Date: Sat, 9 Nov 2013 14:37:23 +0000 Subject: [PATCH] * mod_headers: Allow for format specifiers to be used in the base substitution string when using Header edit trunk patch: http://people.apache.org/~druggeri/patches/HeaderEditENV.trunk.patch 2.4.x patch: http://people.apache.org/~druggeri/patches/HeaderEditENV.2.4.patch +1: druggeri, covener, jim git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1540313 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 3 +++ STATUS | 6 ------ docs/manual/mod/mod_headers.xml | 7 ++++--- modules/metadata/mod_headers.c | 28 ++++++++++++++++------------ 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/CHANGES b/CHANGES index c8801cb578..8c3a90df62 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,9 @@ Changes with Apache 2.4.7 SessionHeader directive, remove the value from the response. PR 55279. [Graham Leggett] + *) mod_headers: Allow for format specifiers in the substitution string + when using Header edit. [Daniel Ruggeri] + *) mod_dav: dav_resource->uri is treated as unencoded. This was an unnecessary ABI changed introduced in 2.4.6. PR 55397. diff --git a/STATUS b/STATUS index cc5e3952d2..d76da71c73 100644 --- a/STATUS +++ b/STATUS @@ -97,12 +97,6 @@ RELEASE SHOWSTOPPERS: PATCHES ACCEPTED TO BACKPORT FROM TRUNK: [ start all new proposals below, under PATCHES PROPOSED. ] - * mod_headers: Allow for format specifiers to be used in the base - substitution string when using Header edit - trunk patch: http://people.apache.org/~druggeri/patches/HeaderEditENV.trunk.patch - 2.4.x patch: http://people.apache.org/~druggeri/patches/HeaderEditENV.2.4.patch - +1: druggeri, covener, jim - PATCHES PROPOSED TO BACKPORT FROM TRUNK: diff --git a/docs/manual/mod/mod_headers.xml b/docs/manual/mod/mod_headers.xml index 68ba926add..fc8c46b00a 100644 --- a/docs/manual/mod/mod_headers.xml +++ b/docs/manual/mod/mod_headers.xml @@ -229,7 +229,7 @@ Header merge Cache-Control no-store env=NO_STORE to a regular expression search-and-replace. The value argument is a regular expression, and the replacement - is a replacement string, which may contain backreferences. + is a replacement string, which may contain backreferences or format specifiers. The edit form will match and replace exactly once in a header value, whereas the edit* form will replace every instance of the search pattern if it appears more @@ -372,7 +372,7 @@ Header merge Cache-Control no-store env=NO_STORE to a regular expression search-and-replace. The value argument is a regular expression, and the replacement - is a replacement string, which may contain backreferences. + is a replacement string, which may contain backreferences or format specifiers. The edit form will match and replace exactly once in a header value, whereas the edit* form will replace every instance of the search pattern if it appears more @@ -481,7 +481,8 @@ Header merge Cache-Control no-store env=NO_STORE

For edit there is both a value argument which is a regular expression, - and an additional replacement string.

+ and an additional replacement string.

As of version 2.4.7 + the replacement string may also contain format specifiers.

The Header directive may be followed by an additional argument, which may be any of:

diff --git a/modules/metadata/mod_headers.c b/modules/metadata/mod_headers.c index 55cfb50a9b..d4e694bf71 100644 --- a/modules/metadata/mod_headers.c +++ b/modules/metadata/mod_headers.c @@ -143,7 +143,7 @@ typedef struct { /* edit_do is used for Header edit to iterate through the request headers */ typedef struct { - apr_pool_t *p; + request_rec *r; header_entry *hdr; apr_table_t *t; } edit_do; @@ -392,12 +392,13 @@ static char *parse_format_string(apr_pool_t *p, header_entry *hdr, const char *s char *res; /* No string to parse with unset and echo commands */ - if (hdr->action == hdr_unset || - hdr->action == hdr_edit || - hdr->action == hdr_edit_r || - hdr->action == hdr_echo) { + if (hdr->action == hdr_unset || hdr->action == hdr_echo) { return NULL; } + /* Tags are in the replacement value for edit */ + else if (hdr->action == hdr_edit || hdr->action == hdr_edit_r ) { + s = hdr->subs; + } hdr->ta = apr_array_make(p, 10, sizeof(format_tag)); @@ -602,7 +603,7 @@ static char* process_tags(header_entry *hdr, request_rec *r) return str ? str : ""; } static const char *process_regexp(header_entry *hdr, const char *value, - apr_pool_t *pool) + request_rec *r) { ap_regmatch_t pmatch[AP_MAX_REG_MATCH]; const char *subs; @@ -613,7 +614,10 @@ static const char *process_regexp(header_entry *hdr, const char *value, /* no match, nothing to do */ return value; } - subs = ap_pregsub(pool, hdr->subs, value, AP_MAX_REG_MATCH, pmatch); + /* Process tags in the input string rather than the resulting + * substitution to avoid surprises + */ + subs = ap_pregsub(r->pool, process_tags(hdr, r), value, AP_MAX_REG_MATCH, pmatch); if (subs == NULL) return NULL; diffsz = strlen(subs) - (pmatch[0].rm_eo - pmatch[0].rm_so); @@ -621,12 +625,12 @@ static const char *process_regexp(header_entry *hdr, const char *value, remainder = value + pmatch[0].rm_eo; } else { /* recurse to edit multiple matches if applicable */ - remainder = process_regexp(hdr, value + pmatch[0].rm_eo, pool); + remainder = process_regexp(hdr, value + pmatch[0].rm_eo, r); if (remainder == NULL) return NULL; diffsz += strlen(remainder) - strlen(value + pmatch[0].rm_eo); } - ret = apr_palloc(pool, strlen(value) + 1 + diffsz); + ret = apr_palloc(r->pool, strlen(value) + 1 + diffsz); memcpy(ret, value, pmatch[0].rm_so); strcpy(ret + pmatch[0].rm_so, subs); strcat(ret, remainder); @@ -648,7 +652,7 @@ static int echo_header(echo_do *v, const char *key, const char *val) static int edit_header(void *v, const char *key, const char *val) { edit_do *ed = (edit_do *)v; - const char *repl = process_regexp(ed->hdr, val, ed->p); + const char *repl = process_regexp(ed->hdr, val, ed->r); if (repl == NULL) return 0; @@ -781,7 +785,7 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers, case hdr_edit: case hdr_edit_r: if (!strcasecmp(hdr->header, "Content-Type") && r->content_type) { - const char *repl = process_regexp(hdr, r->content_type, r->pool); + const char *repl = process_regexp(hdr, r->content_type, r); if (repl == NULL) return 0; ap_set_content_type(r, repl); @@ -789,7 +793,7 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers, if (apr_table_get(headers, hdr->header)) { edit_do ed; - ed.p = r->pool; + ed.r = r; ed.hdr = hdr; ed.t = apr_table_make(r->pool, 5); if (!apr_table_do(edit_header, (void *) &ed, headers, -- 2.40.0