]> granicus.if.org Git - apache/commitdiff
add BNP flag to give control to the user on whether a space ' ' in
authorEric Covener <covener@apache.org>
Sat, 5 Apr 2014 18:40:36 +0000 (18:40 +0000)
committerEric Covener <covener@apache.org>
Sat, 5 Apr 2014 18:40:36 +0000 (18:40 +0000)
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

CHANGES
docs/manual/mod/mod_rewrite.xml
docs/manual/rewrite/flags.xml
modules/mappers/mod_rewrite.c

diff --git a/CHANGES b/CHANGES
index 87e9629df26400a1ad0338619ce113b1b61a4958..2517204d713a0584e85122bb036a145483cb5649 100644 (file)
--- 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
index e75300d77447037686de50ab9e4726d3c86faa9f..60cbf328e8bc0fbabdfc0d69441abef8d30b5041 100644 (file)
@@ -1188,6 +1188,14 @@ cannot use <code>$N</code> in the substitution string!
         applying the transformation. <em><a
         href="../rewrite/flags.html#flag_b">details ...</a></em></td>
     </tr>
+    <tr>
+        <td>backrefnoplus|BNP</td>
+        <td>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.<em><a
+        href="../rewrite/flags.html#flag_bnp">details ...</a></em></td>
+    </tr>
+
     <tr>
         <td>chain|C</td>
         <td>Rule is chained to the following rule. If the rule fails,
index 0efa39f346e3ebc6b3812907ca73fc7b1ac8a733..1c4060065d391aaa5a6119a7cc002e644585a01c 100644 (file)
@@ -71,6 +71,12 @@ characters before applying the transformation.</p>
 <p>In 2.4.10 and later, you can limit the escaping to specific characters 
 in backreferences by listing them: <code>[B=#?;]</code> </p>
 
+<section id="flag_bnp"><title>BNP|backrefnoplus (don't escape space to +)</title>
+<p>The [BNP] flag instructs <directive
+module="mod_rewrite">RewriteRule</directive> 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.
+
 <p><code>mod_rewrite</code> 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
index 5e281769d28656e7617a769957858aac1c21dbce..1d41d4e1a4a064df465064d7336855298a549dd3 100644 (file)
@@ -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;
         }