Loading CHANGES +2 −0 Changes for CHANGES: 2 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -2,6 +2,8 @@ Changes with Apache 2.3.0 [Remove entries to the current 2.0 and 2.2 section below, when backported] *) mod_headers: support regexp-based editing of HTTP headers [Nick Kew] *) mod_echo: Fix precedence problem in if statement. PR 40658. [Larry Cipriani <lvc lucent.com>] Loading docs/manual/mod/mod_headers.xml +34 −4 Changes for docs/manual/mod/mod_headers.xml: 34 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -144,6 +144,15 @@ is available only in Apache 2.0</compatibility> MyHeader: D=3775428 t=991424704447256 mytext </example> </li> <li>Enable DAV to work with Apache running HTTP through SSL hardware (<a href="http://svn.haxx.se/users/archive-2006-03/0549.shtml" >problem description</a>) by replacing <var>https:</var> with <var>http:</var> in the <var>Destination</var> header: <example> RequestHeader edit Destination ^https: http: early </example> </li> </ol> </section> Loading @@ -151,13 +160,13 @@ is available only in Apache 2.0</compatibility> <name>RequestHeader</name> <description>Configure HTTP request headers</description> <syntax>RequestHeader set|append|add|unset <var>header</var> [<var>value</var>] [early|env=[!]<var>variable</var>]</syntax> [<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> <override>FileInfo</override> <usage> <p>This directive can replace, merge or remove HTTP request <p>This directive can replace, merge, change or remove HTTP request headers. The header is modified just before the content handler is run, allowing incoming headers to be modified. The action it performs is determined by the first argument. This can be one Loading Loading @@ -186,18 +195,28 @@ is available only in Apache 2.0</compatibility> <dd>The request header of this name is removed, if it exists. If there are multiple headers of the same name, all will be removed. <var>value</var> must be omitted.</dd> <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> </dl> <p>This argument is followed by a header name, which can include the final colon, but it is not required. Case is ignored. For <code>add</code>, <code>append</code> and <code>set</code> a <var>value</var> is given as the third argument. If <code>set</code> a <var>value</var> is given as the third argument. If a <var>value</var> contains spaces, it should be surrounded by double quotes. For unset, no <var>value</var> should be given. <var>value</var> may be a character string, a string containing format specifiers or a combination of both. The supported format specifiers are the same as for the <directive module="mod_headers">Header</directive>, please have a look there for details.</p> please have a look there for details. For <code>edit</code> both a <var>value</var> and a <var>replacement</var> are required, and are a <glossary ref="regex">regular expression</glossary> and a replacement string respectively.</p> <p>The <directive>RequestHeader</directive> directive may be followed by an additional argument, which may be used to specify conditions under Loading Loading @@ -271,6 +290,13 @@ is available only in Apache 2.0</compatibility> response headers. <var>header</var> may be a <glossary ref="regex">regular expression</glossary>. <var>value</var> must be omitted.</dd> <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> </dl> <p>This argument is followed by a <var>header</var> name, which Loading Loading @@ -322,6 +348,10 @@ is available only in Apache 2.0</compatibility> more efficient than <code>%s</code>.</p> </note> <p>For <code>edit</code> there is both a <var>value</var> argument which is a <glossary ref="regex">regular expression</glossary>, and an additional <var>replacement</var> string.</p> <p>The <directive>Header</directive> directive may be followed by an an additional argument, which may be used to specify conditions under which the action will be taken, or may be the keyword <code>early</code> Loading modules/metadata/mod_headers.c +57 −6 Changes for modules/metadata/mod_headers.c: 57 added lines, 6 removed lines. Original line number Diff line number Diff line Loading @@ -89,7 +89,8 @@ typedef enum { hdr_set = 's', /* set (replace old value) */ hdr_append = 'm', /* append (merge into any old value) */ hdr_unset = 'u', /* unset header */ hdr_echo = 'e' /* echo headers from request to response */ hdr_echo = 'e', /* echo headers from request to response */ hdr_edit = 'r' /* change value by regexp */ } hdr_actions; /* Loading Loading @@ -119,6 +120,7 @@ typedef struct { apr_array_header_t *ta; /* Array of format_tag structs */ ap_regex_t *regex; const char *condition_var; const char *subs; } header_entry; /* echo_do is used for Header echo to iterate through the request headers*/ Loading Loading @@ -348,6 +350,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_echo) { return NULL; } Loading @@ -368,6 +371,7 @@ static APR_INLINE const char *header_inout_cmd(cmd_parms *cmd, const char *action, const char *hdr, const char *value, const char *subs, const char *envclause) { headers_conf *dirconf = indirconf; Loading @@ -392,10 +396,29 @@ static APR_INLINE const char *header_inout_cmd(cmd_parms *cmd, new->action = hdr_unset; else if (!strcasecmp(action, "echo")) new->action = hdr_echo; else if (!strcasecmp(action, "edit")) new->action = hdr_edit; else return "first argument must be 'add', 'set', 'append', 'unset' or " "'echo'."; return "first argument must be 'add', 'set', 'append', 'unset', " "'echo' or 'edit'."; if (new->action == hdr_edit) { if (subs == NULL) { return "Header edit requires a match and a substitution"; } new->regex = ap_pregcomp(cmd->pool, value, AP_REG_EXTENDED); if (new->regex == NULL) { return "Header edit regex could not be compiled"; } new->subs = subs; } else { /* there's no subs, so envclause is really that argument */ if (envclause != NULL) { return "Too many arguments to directive"; } envclause = subs; } if (new->action == hdr_unset) { if (value) { if (envclause) { Loading Loading @@ -465,6 +488,7 @@ static const char *header_cmd(cmd_parms *cmd, void *indirconf, const char *hdr; const char *val; const char *envclause; const char *subs; action = ap_getword_conf(cmd->pool, &args); if (cmd->info == &hdr_out) { Loading @@ -478,6 +502,7 @@ static const char *header_cmd(cmd_parms *cmd, void *indirconf, } hdr = ap_getword_conf(cmd->pool, &args); val = *args ? ap_getword_conf(cmd->pool, &args) : NULL; subs = *args ? ap_getword_conf(cmd->pool, &args) : NULL; envclause = *args ? ap_getword_conf(cmd->pool, &args) : NULL; if (*args) { Loading @@ -485,7 +510,7 @@ static const char *header_cmd(cmd_parms *cmd, void *indirconf, " has too many arguments", NULL); } return header_inout_cmd(cmd, indirconf, action, hdr, val, envclause); return header_inout_cmd(cmd, indirconf, action, hdr, val, subs, envclause); } /* Loading @@ -512,6 +537,26 @@ 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) { unsigned int nmatch = 10; ap_regmatch_t pmatch[10]; const char *subs; char *ret; int diffsz; if (ap_regexec(hdr->regex, value, nmatch, pmatch, 0)) { /* no match, nothing to do */ return value; } subs = ap_pregsub(pool, hdr->subs, value, nmatch, pmatch); diffsz = strlen(subs) - (pmatch[0].rm_eo - pmatch[0].rm_so); ret = apr_palloc(pool, strlen(value) + 1 + diffsz); memcpy(ret, value, pmatch[0].rm_so); strcpy(ret + pmatch[0].rm_so, subs); strcat(ret, value + pmatch[0].rm_eo); return ret; } static int echo_header(echo_do *v, const char *key, const char *val) { Loading @@ -528,7 +573,9 @@ static int echo_header(echo_do *v, const char *key, const char *val) static void do_headers_fixup(request_rec *r, apr_table_t *headers, apr_array_header_t *fixup, int early) { echo_do v; int i; const char *val; for (i = 0; i < fixup->nelts; ++i) { header_entry *hdr = &((header_entry *) (fixup->elts))[i]; Loading Loading @@ -568,14 +615,18 @@ static void do_headers_fixup(request_rec *r, apr_table_t *headers, apr_table_unset(headers, hdr->header); break; case hdr_echo: { echo_do v; v.r = r; v.hdr = hdr; apr_table_do((int (*) (void *, const char *, const char *)) 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)); } break; } } } Loading Loading
CHANGES +2 −0 Changes for CHANGES: 2 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -2,6 +2,8 @@ Changes with Apache 2.3.0 [Remove entries to the current 2.0 and 2.2 section below, when backported] *) mod_headers: support regexp-based editing of HTTP headers [Nick Kew] *) mod_echo: Fix precedence problem in if statement. PR 40658. [Larry Cipriani <lvc lucent.com>] Loading
docs/manual/mod/mod_headers.xml +34 −4 Changes for docs/manual/mod/mod_headers.xml: 34 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -144,6 +144,15 @@ is available only in Apache 2.0</compatibility> MyHeader: D=3775428 t=991424704447256 mytext </example> </li> <li>Enable DAV to work with Apache running HTTP through SSL hardware (<a href="http://svn.haxx.se/users/archive-2006-03/0549.shtml" >problem description</a>) by replacing <var>https:</var> with <var>http:</var> in the <var>Destination</var> header: <example> RequestHeader edit Destination ^https: http: early </example> </li> </ol> </section> Loading @@ -151,13 +160,13 @@ is available only in Apache 2.0</compatibility> <name>RequestHeader</name> <description>Configure HTTP request headers</description> <syntax>RequestHeader set|append|add|unset <var>header</var> [<var>value</var>] [early|env=[!]<var>variable</var>]</syntax> [<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> <override>FileInfo</override> <usage> <p>This directive can replace, merge or remove HTTP request <p>This directive can replace, merge, change or remove HTTP request headers. The header is modified just before the content handler is run, allowing incoming headers to be modified. The action it performs is determined by the first argument. This can be one Loading Loading @@ -186,18 +195,28 @@ is available only in Apache 2.0</compatibility> <dd>The request header of this name is removed, if it exists. If there are multiple headers of the same name, all will be removed. <var>value</var> must be omitted.</dd> <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> </dl> <p>This argument is followed by a header name, which can include the final colon, but it is not required. Case is ignored. For <code>add</code>, <code>append</code> and <code>set</code> a <var>value</var> is given as the third argument. If <code>set</code> a <var>value</var> is given as the third argument. If a <var>value</var> contains spaces, it should be surrounded by double quotes. For unset, no <var>value</var> should be given. <var>value</var> may be a character string, a string containing format specifiers or a combination of both. The supported format specifiers are the same as for the <directive module="mod_headers">Header</directive>, please have a look there for details.</p> please have a look there for details. For <code>edit</code> both a <var>value</var> and a <var>replacement</var> are required, and are a <glossary ref="regex">regular expression</glossary> and a replacement string respectively.</p> <p>The <directive>RequestHeader</directive> directive may be followed by an additional argument, which may be used to specify conditions under Loading Loading @@ -271,6 +290,13 @@ is available only in Apache 2.0</compatibility> response headers. <var>header</var> may be a <glossary ref="regex">regular expression</glossary>. <var>value</var> must be omitted.</dd> <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> </dl> <p>This argument is followed by a <var>header</var> name, which Loading Loading @@ -322,6 +348,10 @@ is available only in Apache 2.0</compatibility> more efficient than <code>%s</code>.</p> </note> <p>For <code>edit</code> there is both a <var>value</var> argument which is a <glossary ref="regex">regular expression</glossary>, and an additional <var>replacement</var> string.</p> <p>The <directive>Header</directive> directive may be followed by an an additional argument, which may be used to specify conditions under which the action will be taken, or may be the keyword <code>early</code> Loading
modules/metadata/mod_headers.c +57 −6 Changes for modules/metadata/mod_headers.c: 57 added lines, 6 removed lines. Original line number Diff line number Diff line Loading @@ -89,7 +89,8 @@ typedef enum { hdr_set = 's', /* set (replace old value) */ hdr_append = 'm', /* append (merge into any old value) */ hdr_unset = 'u', /* unset header */ hdr_echo = 'e' /* echo headers from request to response */ hdr_echo = 'e', /* echo headers from request to response */ hdr_edit = 'r' /* change value by regexp */ } hdr_actions; /* Loading Loading @@ -119,6 +120,7 @@ typedef struct { apr_array_header_t *ta; /* Array of format_tag structs */ ap_regex_t *regex; const char *condition_var; const char *subs; } header_entry; /* echo_do is used for Header echo to iterate through the request headers*/ Loading Loading @@ -348,6 +350,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_echo) { return NULL; } Loading @@ -368,6 +371,7 @@ static APR_INLINE const char *header_inout_cmd(cmd_parms *cmd, const char *action, const char *hdr, const char *value, const char *subs, const char *envclause) { headers_conf *dirconf = indirconf; Loading @@ -392,10 +396,29 @@ static APR_INLINE const char *header_inout_cmd(cmd_parms *cmd, new->action = hdr_unset; else if (!strcasecmp(action, "echo")) new->action = hdr_echo; else if (!strcasecmp(action, "edit")) new->action = hdr_edit; else return "first argument must be 'add', 'set', 'append', 'unset' or " "'echo'."; return "first argument must be 'add', 'set', 'append', 'unset', " "'echo' or 'edit'."; if (new->action == hdr_edit) { if (subs == NULL) { return "Header edit requires a match and a substitution"; } new->regex = ap_pregcomp(cmd->pool, value, AP_REG_EXTENDED); if (new->regex == NULL) { return "Header edit regex could not be compiled"; } new->subs = subs; } else { /* there's no subs, so envclause is really that argument */ if (envclause != NULL) { return "Too many arguments to directive"; } envclause = subs; } if (new->action == hdr_unset) { if (value) { if (envclause) { Loading Loading @@ -465,6 +488,7 @@ static const char *header_cmd(cmd_parms *cmd, void *indirconf, const char *hdr; const char *val; const char *envclause; const char *subs; action = ap_getword_conf(cmd->pool, &args); if (cmd->info == &hdr_out) { Loading @@ -478,6 +502,7 @@ static const char *header_cmd(cmd_parms *cmd, void *indirconf, } hdr = ap_getword_conf(cmd->pool, &args); val = *args ? ap_getword_conf(cmd->pool, &args) : NULL; subs = *args ? ap_getword_conf(cmd->pool, &args) : NULL; envclause = *args ? ap_getword_conf(cmd->pool, &args) : NULL; if (*args) { Loading @@ -485,7 +510,7 @@ static const char *header_cmd(cmd_parms *cmd, void *indirconf, " has too many arguments", NULL); } return header_inout_cmd(cmd, indirconf, action, hdr, val, envclause); return header_inout_cmd(cmd, indirconf, action, hdr, val, subs, envclause); } /* Loading @@ -512,6 +537,26 @@ 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) { unsigned int nmatch = 10; ap_regmatch_t pmatch[10]; const char *subs; char *ret; int diffsz; if (ap_regexec(hdr->regex, value, nmatch, pmatch, 0)) { /* no match, nothing to do */ return value; } subs = ap_pregsub(pool, hdr->subs, value, nmatch, pmatch); diffsz = strlen(subs) - (pmatch[0].rm_eo - pmatch[0].rm_so); ret = apr_palloc(pool, strlen(value) + 1 + diffsz); memcpy(ret, value, pmatch[0].rm_so); strcpy(ret + pmatch[0].rm_so, subs); strcat(ret, value + pmatch[0].rm_eo); return ret; } static int echo_header(echo_do *v, const char *key, const char *val) { Loading @@ -528,7 +573,9 @@ static int echo_header(echo_do *v, const char *key, const char *val) static void do_headers_fixup(request_rec *r, apr_table_t *headers, apr_array_header_t *fixup, int early) { echo_do v; int i; const char *val; for (i = 0; i < fixup->nelts; ++i) { header_entry *hdr = &((header_entry *) (fixup->elts))[i]; Loading Loading @@ -568,14 +615,18 @@ static void do_headers_fixup(request_rec *r, apr_table_t *headers, apr_table_unset(headers, hdr->header); break; case hdr_echo: { echo_do v; v.r = r; v.hdr = hdr; apr_table_do((int (*) (void *, const char *, const char *)) 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)); } break; } } } Loading