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