diff options
author | Nick Kew <niq@apache.org> | 2009-12-27 01:05:12 +0100 |
---|---|---|
committer | Nick Kew <niq@apache.org> | 2009-12-27 01:05:12 +0100 |
commit | 76ea26f7a0a7da2e29bf3dc19941647dd9d90518 (patch) | |
tree | c6e7c7d51d672a0c24d6e1d67505090c3b423e4d | |
parent | mod_headers: align Header Edit with Header Set on Content-Type (diff) | |
download | apache2-76ea26f7a0a7da2e29bf3dc19941647dd9d90518.tar.xz apache2-76ea26f7a0a7da2e29bf3dc19941647dd9d90518.zip |
mod_headers: Enable multi-match-and-replace edit option
PR 47066
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@894036 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | docs/manual/mod/mod_headers.xml | 9 | ||||
-rw-r--r-- | modules/metadata/mod_headers.c | 19 |
3 files changed, 26 insertions, 5 deletions
@@ -36,6 +36,9 @@ Changes with Apache 2.3.5 *) mod_headers: align Header Edit with Header Set when used on Content-Type PR 48422 [Cyril Bonté <cyril.bonte free.fr>, Nick Kew>] + *) mod_headers: Enable multi-match-and-replace edit option + PR 47066 [Nick Kew] + Changes with Apache 2.3.4 *) Replace AcceptMutex, LockFile, RewriteLock, SSLMutex, SSLStaplingMutex, diff --git a/docs/manual/mod/mod_headers.xml b/docs/manual/mod/mod_headers.xml index f23b965203..cc377a60e3 100644 --- a/docs/manual/mod/mod_headers.xml +++ b/docs/manual/mod/mod_headers.xml @@ -193,7 +193,7 @@ headers</description> <directivesynopsis> <name>RequestHeader</name> <description>Configure HTTP request headers</description> -<syntax>RequestHeader add|append|edit|merge|set|unset <var>header</var> +<syntax>RequestHeader add|append|edit|edit*|merge|set|unset <var>header</var> [<var>value</var>] [<var>replacement</var>] [early|env=[!]<var>variable</var>]</syntax> <contextlist><context>server config</context><context>virtual host</context> <context>directory</context><context>.htaccess</context></contextlist> @@ -223,11 +223,16 @@ headers</description> values.</dd> <dt><code>edit</code></dt> + <dt><code>edit*</code></dt> <dd>If this request header exists, its value is transformed according to a <glossary ref="regex">regular expression</glossary> search-and-replace. The <var>value</var> argument is a <glossary ref="regex">regular expression</glossary>, and the <var>replacement</var> - is a replacement string, which may contain backreferences.</dd> + is a replacement string, which may contain backreferences. + The <code>edit</code> form will match and replace exactly once + in a header value, whereas the <code>edit*</code> form will replace + <em>every</em> instance of the search pattern if it appears more + than once.</dd> <dt><code>merge</code></dt> <dd>The response header is appended to any existing header of diff --git a/modules/metadata/mod_headers.c b/modules/metadata/mod_headers.c index e27f504ae6..5e7834aecc 100644 --- a/modules/metadata/mod_headers.c +++ b/modules/metadata/mod_headers.c @@ -95,7 +95,8 @@ typedef enum { hdr_merge = 'g', /* merge (merge, but avoid duplicates) */ hdr_unset = 'u', /* unset header */ hdr_echo = 'e', /* echo headers from request to response */ - hdr_edit = 'r' /* change value by regexp */ + hdr_edit = 'r', /* change value by regexp, match once */ + hdr_edit_r = 'R' /* change value by regexp, everymatch */ } hdr_actions; /* @@ -366,6 +367,7 @@ static char *parse_format_string(apr_pool_t *p, header_entry *hdr, const char *s /* 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) { return NULL; } @@ -416,11 +418,13 @@ static APR_INLINE const char *header_inout_cmd(cmd_parms *cmd, new->action = hdr_echo; else if (!strcasecmp(action, "edit")) new->action = hdr_edit; + else if (!strcasecmp(action, "edit*")) + new->action = hdr_edit_r; else return "first argument must be 'add', 'set', 'append', 'merge', " - "'unset', 'echo', or 'edit'."; + "'unset', 'echo', 'edit', or 'edit*'."; - if (new->action == hdr_edit) { + if (new->action == hdr_edit || new->action == hdr_edit_r) { if (subs == NULL) { return "Header edit requires a match and a substitution"; } @@ -566,6 +570,7 @@ static const char *process_regexp(header_entry *hdr, const char *value, unsigned int nmatch = 10; ap_regmatch_t pmatch[10]; const char *subs; + const char *remainder; char *ret; int diffsz; if (ap_regexec(hdr->regex, value, nmatch, pmatch, 0)) { @@ -574,6 +579,13 @@ static const char *process_regexp(header_entry *hdr, const char *value, } subs = ap_pregsub(pool, hdr->subs, value, nmatch, pmatch); diffsz = strlen(subs) - (pmatch[0].rm_eo - pmatch[0].rm_so); + if (hdr->action == hdr_edit) { + remainder = value + pmatch[0].rm_eo; + } + else { /* recurse to edit multiple matches if applicable */ + remainder = process_regexp(hdr, value + pmatch[0].rm_eo, pool); + diffsz += strlen(remainder) - strlen(value + pmatch[0].rm_eo); + } ret = apr_palloc(pool, strlen(value) + 1 + diffsz); memcpy(ret, value, pmatch[0].rm_so); strcpy(ret + pmatch[0].rm_so, subs); @@ -722,6 +734,7 @@ static void do_headers_fixup(request_rec *r, apr_table_t *headers, echo_header, (void *) &v, r->headers_in, NULL); break; case hdr_edit: + case hdr_edit_r: if (!strcasecmp(hdr->header, "Content-Type") && r->content_type) { ap_set_content_type(r, process_regexp(hdr, r->content_type, r->pool)); |