]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Add ability to escape characters in Rewrite* input strings using
authorKen Coar <coar@apache.org>
Sun, 6 May 2001 22:00:02 +0000 (22:00 +0000)
committerKen Coar <coar@apache.org>
Sun, 6 May 2001 22:00:02 +0000 (22:00 +0000)
'\' (e.g., "\$" to keep it from having its special meaning), and
NoEscape/NE flag to disable filtering the rewritten output through
URI encoding.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x@89040 13f79535-47bb-0310-9956-ffa450edef68

src/CHANGES
src/modules/standard/mod_rewrite.c
src/modules/standard/mod_rewrite.h

index b2bc7abf1c2a3442238921c0d04a61a286888ec5..ab160349bc95ad9be24dafd0880052d7fd905434 100644 (file)
@@ -1,5 +1,13 @@
 Changes with Apache 1.3.20
 
+  *) Added NOESCAPE (NS) flag to RewriteRule and enabled use of
+     '\' to allow escaping of special characters.  Previously
+     there was no way to embed either '$' or '%' in the output
+     of a RewriteRule; now 'foo\$1' will result in a literal
+     'foo$1' appearing in the result rather than 'foo\<value of $1>'.
+     Note that [NS] disables *all* normal URI escaping, so incautious
+     use can give unexpected results.  [Ken Coar]
+
   *) Add support for Win32 apxs.  Note that cygwin builders must use a
      cygwin perl to avoid the MSWin32 handling.  [William Rowe]
 
@@ -13,8 +21,8 @@ Changes with Apache 1.3.20
      for Win32 systems, see http://www.cygwin.com)
      [Stipe Tolj <tolj@wapme-systems.de>]
 
-  *) Changes to 'ab'; fixed int overrun's, added statistics, output in
-     csv/gnuplot format, rudimentary ssl support and various other tweaks
+  *) Changes to 'ab': fixed int overruns, added statistics, output in
+     csv/gnuplot format, rudimentary SSL support and various other tweaks
      to make results more true to what is measured. The upshot of this it
      turns out that 'ab' has often underreported the true performance of
      apache. Often by a order of magnitude :-) See talk/paper of Sander 
index bc673c7c683dd63cf22f8bba888014c903d332a4..e40a28cd8b5553e108ae18d58013f1c675a68772 100644 (file)
@@ -866,6 +866,10 @@ static const char *cmd_rewriterule_setflag(pool *p, rewriterule_entry *cfg,
             cfg->forced_responsecode = status;
         }
     }
+    else if (   strcasecmp(key, "noescape") == 0
+        || strcasecmp(key, "NE") == 0       ) {
+        cfg->flags |= RULEFLAG_NOESCAPE;
+    }
     else if (   strcasecmp(key, "last") == 0
              || strcasecmp(key, "L") == 0   ) {
         cfg->flags |= RULEFLAG_LASTRULE;
@@ -1010,6 +1014,7 @@ static int hook_uri2file(request_rec *r)
     const char *ccp;
     struct stat finfo;
     unsigned int port;
+    int rulestatus;
     int n;
     int l;
 
@@ -1093,7 +1098,8 @@ static int hook_uri2file(request_rec *r)
     /*
      *  now apply the rules ...
      */
-    if (apply_rewrite_list(r, conf->rewriterules, NULL)) {
+    rulestatus = apply_rewrite_list(r, conf->rewriterules, NULL);
+    if (rulestatus) {
 
         if (strlen(r->filename) > 6 &&
             strncmp(r->filename, "proxy:", 6) == 0) {
@@ -1143,16 +1149,28 @@ static int hook_uri2file(request_rec *r)
             for ( ; *cp != '/' && *cp != '\0'; cp++)
                 ;
             if (*cp != '\0') {
-                rewritelog(r, 1, "escaping %s for redirect", r->filename);
-                cp2 = ap_escape_uri(r->pool, cp);
+                if (rulestatus != ACTION_NOESCAPE) {
+                    rewritelog(r, 1, "escaping %s for redirect", r->filename);
+                    cp2 = ap_escape_uri(r->pool, cp);
+                }
+                else {
+                    cp2 = ap_pstrdup(r->pool, cp);
+                }
                 *cp = '\0';
                 r->filename = ap_pstrcat(r->pool, r->filename, cp2, NULL);
             }
 
             /* append the QUERY_STRING part */
             if (r->args != NULL) {
+                char *args;
+                if (rulestatus == ACTION_NOESCAPE) {
+                    args = r->args;
+                }
+                else {
+                    args = ap_escape_uri(r->pool, r->args);
+                }
                 r->filename = ap_pstrcat(r->pool, r->filename, "?", 
-                                         ap_escape_uri(r->pool, r->args), NULL);
+                                         args, NULL);
             }
 
             /* determine HTTP redirect response code */
@@ -1305,6 +1323,7 @@ static int hook_fixup(request_rec *r)
     const char *ccp;
     char *prefix;
     int l;
+    int rulestatus;
     int n;
     char *ofilename;
 
@@ -1358,7 +1377,8 @@ static int hook_fixup(request_rec *r)
     /*
      *  now apply the rules ...
      */
-    if (apply_rewrite_list(r, dconf->rewriterules, dconf->directory)) {
+    rulestatus = apply_rewrite_list(r, dconf->rewriterules, dconf->directory);
+    if (rulestatus) {
 
         if (strlen(r->filename) > 6 &&
             strncmp(r->filename, "proxy:", 6) == 0) {
@@ -1422,17 +1442,29 @@ static int hook_fixup(request_rec *r)
             for ( ; *cp != '/' && *cp != '\0'; cp++)
                 ;
             if (*cp != '\0') {
-                rewritelog(r, 1, "[per-dir %s] escaping %s for redirect",
-                           dconf->directory, r->filename);
-                cp2 = ap_escape_uri(r->pool, cp);
+                if (rulestatus != ACTION_NOESCAPE) {
+                    rewritelog(r, 1, "[per-dir %s] escaping %s for redirect",
+                               dconf->directory, r->filename);
+                    cp2 = ap_escape_uri(r->pool, cp);
+                }
+                else {
+                    cp2 = ap_pstrdup(r->pool, cp);
+                }
                 *cp = '\0';
                 r->filename = ap_pstrcat(r->pool, r->filename, cp2, NULL);
             }
 
             /* append the QUERY_STRING part */
             if (r->args != NULL) {
+                char *args;
+                if (rulestatus == ACTION_NOESCAPE) {
+                    args = r->args;
+                }
+                else {
+                    args = ap_escape_uri(r->pool, r->args);
+                }
                 r->filename = ap_pstrcat(r->pool, r->filename, "?", 
-                                         ap_escape_uri(r->pool, r->args), NULL);
+                                         args, NULL);
             }
 
             /* determine HTTP redirect response code */
@@ -1622,7 +1654,8 @@ static int apply_rewrite_list(request_rec *r, array_header *rewriterules,
              *  Indicate a change if this was not a match-only rule.
              */
             if (rc != 2) {
-                changed = 1;
+                changed = ((p->flags & RULEFLAG_NOESCAPE)
+                           ? ACTION_NOESCAPE : ACTION_NORMAL);
             }
 
             /*
@@ -1636,7 +1669,7 @@ static int apply_rewrite_list(request_rec *r, array_header *rewriterules,
                            "to next API URI-to-filename handler", r->filename);
                 r->filename = ap_pstrcat(r->pool, "passthrough:",
                                          r->filename, NULL);
-                changed = 1;
+                changed = ACTION_NORMAL;
                 break;
             }
 
@@ -1648,7 +1681,7 @@ static int apply_rewrite_list(request_rec *r, array_header *rewriterules,
                 rewritelog(r, 2, "forcing '%s' to be forbidden", r->filename);
                 r->filename = ap_pstrcat(r->pool, "forbidden:",
                                          r->filename, NULL);
-                changed = 1;
+                changed = ACTION_NORMAL;
                 break;
             }
 
@@ -1659,7 +1692,7 @@ static int apply_rewrite_list(request_rec *r, array_header *rewriterules,
             if (p->flags & RULEFLAG_GONE) {
                 rewritelog(r, 2, "forcing '%s' to be gone", r->filename);
                 r->filename = ap_pstrcat(r->pool, "gone:", r->filename, NULL);
-                changed = 1;
+                changed = ACTION_NORMAL;
                 break;
             }
 
@@ -2245,7 +2278,7 @@ static void do_expand(request_rec *r, char *input, char *buffer, int nbuf,
     space = nbuf - 1; /* room for '\0' */
 
     for (;;) {
-       span = strcspn(inp, "$%");
+       span = strcspn(inp, "\\$%");
        if (span > space) {
            span = space;
        }
@@ -2256,8 +2289,14 @@ static void do_expand(request_rec *r, char *input, char *buffer, int nbuf,
        if (space == 0 || *inp == '\0') {
            break;
        }
-       /* now we have a '$' or a '%' */
-       if (inp[1] == '{') {
+       /* now we have a '\', '$', or '%' */
+        if (inp[0] == '\\') {
+            if (inp[1] != '\0') {
+                inp++;
+                goto skip;
+            }
+        }
+       else if (inp[1] == '{') {
            char *endp;
            endp = find_closing_bracket(inp+2, '{', '}');
            if (endp == NULL) {
@@ -2288,14 +2327,16 @@ static void do_expand(request_rec *r, char *input, char *buffer, int nbuf,
                char xkey[MAX_STRING_LEN];
                char xdflt[MAX_STRING_LEN];
                key = find_char_in_brackets(inp+2, ':', '{', '}');
-               if (key == NULL)
+               if (key == NULL) {
                    goto skip;
+                }
                map  = ap_pstrndup(r->pool, inp+2, key-inp-2);
                dflt = find_char_in_brackets(key+1, '|', '{', '}');
                if (dflt == NULL) {
                    key  = ap_pstrndup(r->pool, key+1, endp-key-1);
                    dflt = "";
-               } else {
+               }
+                else {
                    key  = ap_pstrndup(r->pool, key+1, dflt-key-1);
                    dflt = ap_pstrndup(r->pool, dflt+1, endp-dflt-1);
                }
index f5804ff41d3842e9a23cfc9599d99e208b56c830..47c55dbdeb8323b6fe4945f124fad3235ca5a91c 100644 (file)
 #define RULEFLAG_GONE               1<<10
 #define RULEFLAG_QSAPPEND           1<<11
 #define RULEFLAG_NOCASE             1<<12
+#define RULEFLAG_NOESCAPE           1<<13
+
+#define ACTION_NORMAL               1<<0
+#define ACTION_NOESCAPE             1<<1
 
 #define MAPTYPE_TXT                 1<<0
 #define MAPTYPE_DBM                 1<<1