From: Eric Covener Date: Sat, 5 Apr 2014 18:40:36 +0000 (+0000) Subject: add BNP flag to give control to the user on whether a space ' ' in X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aa54ed8e98949d9d0f3b563eab22910e2d6a1178;p=thirdparty%2Fapache%2Fhttpd.git add BNP flag to give control to the user on whether a space ' ' in an escaped backrefernece is decoded to a + (default) or %20. Useful if your backreference isn't going into the query string. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1585157 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 87e9629df26..2517204d713 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,10 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) mod_rewrite: Add 'BNF' (backreferences-no-plus) flag to RewriteRule to + allow spaces in backreferences to be encoded as %20 instead of '+'. + [Eric Covener] + *) mod_ssl: bring SNI behavior into better conformance with RFC 6066: no longer send warning-level unrecognized_name(112) alerts, and limit startup warnings to cases where an OpenSSL version diff --git a/docs/manual/mod/mod_rewrite.xml b/docs/manual/mod/mod_rewrite.xml index e75300d7744..60cbf328e8b 100644 --- a/docs/manual/mod/mod_rewrite.xml +++ b/docs/manual/mod/mod_rewrite.xml @@ -1188,6 +1188,14 @@ cannot use $N in the substitution string! applying the transformation. details ... + + backrefnoplus|BNP + If backreferences are being escaped, spaces should be escaped to + %20 instead of +. Useful when the backreference will be used in the + path component rather than the query string.details ... + + chain|C Rule is chained to the following rule. If the rule fails, diff --git a/docs/manual/rewrite/flags.xml b/docs/manual/rewrite/flags.xml index 0efa39f346e..1c4060065d3 100644 --- a/docs/manual/rewrite/flags.xml +++ b/docs/manual/rewrite/flags.xml @@ -71,6 +71,12 @@ characters before applying the transformation.

In 2.4.10 and later, you can limit the escaping to specific characters in backreferences by listing them: [B=#?;]

+
BNP|backrefnoplus (don't escape space to +) +

The [BNP] flag instructs RewriteRule to escape the space character +in a backreference to %20 rather than '+'. Useful when the backreference +will be used in the path component rather than the query string. +

mod_rewrite has to unescape URLs before mapping them, so backreferences are unescaped at the time they are applied. Using the B flag, non-alphanumeric characters in backreferences diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c index 5e281769d28..1d41d4e1a4a 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c @@ -170,6 +170,7 @@ static const char* really_last_key = "rewrite_really_last"; #define RULEFLAG_DISCARDPATHINFO 1<<15 #define RULEFLAG_QSDISCARD 1<<16 #define RULEFLAG_END 1<<17 +#define RULEFLAG_ESCAPENOPLUS 1<<18 /* return code of the rewrite rule * the result may be escaped - or not @@ -420,7 +421,7 @@ static const char *rewritemap_mutex_type = "rewrite-map"; /* Optional functions imported from mod_ssl when loaded: */ static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *rewrite_ssl_lookup = NULL; static APR_OPTIONAL_FN_TYPE(ssl_is_https) *rewrite_is_https = NULL; -static char *escape_uri(apr_pool_t *p, const char *path, const char *escapeme); +static char *escape_backref(apr_pool_t *p, const char *path, const char *escapeme, int noplus); /* * +-------------------------------------------------------+ @@ -629,10 +630,10 @@ static APR_INLINE unsigned char *c2x(unsigned what, unsigned char prefix, } /* - * Escapes a uri in a similar way as php's urlencode does. + * Escapes a backreference in a similar way as php's urlencode does. * Based on ap_os_escape_path in server/util.c */ -static char *escape_uri(apr_pool_t *p, const char *path, const char *escapeme) { +static char *escape_backref(apr_pool_t *p, const char *path, const char *escapeme, int noplus) { char *copy = apr_palloc(p, 3 * strlen(path) + 3); const unsigned char *s = (const unsigned char *)path; unsigned char *d = (unsigned char *)copy; @@ -643,7 +644,7 @@ static char *escape_uri(apr_pool_t *p, const char *path, const char *escapeme) { if (apr_isalnum(c) || c == '_') { *d++ = c; } - else if (c == ' ') { + else if (c == ' ' && !noplus) { *d++ = '+'; } else { @@ -654,7 +655,12 @@ static char *escape_uri(apr_pool_t *p, const char *path, const char *escapeme) { const char *esc = escapeme; while (*esc) { if (c == *esc) { - d = c2x(c, '%', d); + if (c == ' ' && !noplus) { + *d++ = '+'; + } + else { + d = c2x(c, '%', d); + } break; } ++esc; @@ -2384,7 +2390,7 @@ static char *do_expand(char *input, rewrite_ctx *ctx, rewriterule_entry *entry) /* escape the backreference */ char *tmp2, *tmp; tmp = apr_pstrmemdup(pool, bri->source + bri->regmatch[n].rm_so, span); - tmp2 = escape_uri(pool, tmp, entry->escapes); + tmp2 = escape_backref(pool, tmp, entry->escapes, entry->flags & RULEFLAG_ESCAPENOPLUS); rewritelog((ctx->r, 5, ctx->perdir, "escaping backreference '%s' to '%s'", tmp, tmp2)); @@ -3435,6 +3441,9 @@ static const char *cmd_rewriterule_setflag(apr_pool_t *p, void *_cfg, cfg->escapes = val; } } + else if (!strcasecmp(key, "NP") || !strcasecmp(key, "ackrefernoplus")) { + cfg->flags |= RULEFLAG_ESCAPENOPLUS; + } else { ++error; }