Author: markt
Date: Tue Sep  6 21:26:17 2016
New Revision: 1759516

URL: http://svn.apache.org/viewvc?rev=1759516&view=rev
Log:
Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=60013
Implement B and NE. Update unit tests to use B and/or NE where required.
Also make minor modifications to align unit tests with expected
behaviour of httpd.

Modified:
    tomcat/trunk/java/org/apache/catalina/valves/rewrite/Resolver.java
    tomcat/trunk/java/org/apache/catalina/valves/rewrite/ResolverImpl.java
    tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteRule.java
    tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteValve.java
    tomcat/trunk/java/org/apache/catalina/valves/rewrite/Substitution.java
    tomcat/trunk/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java

Modified: tomcat/trunk/java/org/apache/catalina/valves/rewrite/Resolver.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/rewrite/Resolver.java?rev=1759516&r1=1759515&r2=1759516&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/valves/rewrite/Resolver.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/valves/rewrite/Resolver.java Tue Sep  
6 21:26:17 2016
@@ -33,4 +33,6 @@ public abstract class Resolver {
     public abstract String resolveHttp(String key);
 
     public abstract boolean resolveResource(int type, String name);
+
+    public abstract String getUriEncoding();
 }

Modified: tomcat/trunk/java/org/apache/catalina/valves/rewrite/ResolverImpl.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/rewrite/ResolverImpl.java?rev=1759516&r1=1759515&r2=1759516&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/valves/rewrite/ResolverImpl.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/valves/rewrite/ResolverImpl.java Tue 
Sep  6 21:26:17 2016
@@ -177,4 +177,9 @@ public class ResolverImpl extends Resolv
             return value;
         }
     }
+
+    @Override
+    public String getUriEncoding() {
+        return request.getConnector().getURIEncoding();
+    }
 }

Modified: tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteRule.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteRule.java?rev=1759516&r1=1759515&r2=1759516&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteRule.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteRule.java Tue 
Sep  6 21:26:17 2016
@@ -37,6 +37,8 @@ public class RewriteRule {
             substitution = new Substitution();
             substitution.setSub(substitutionString);
             substitution.parse(maps);
+            substitution.setEscapeBackReferences(isEscapeBackReferences());
+            substitution.setNoEscape(isNoescape());
         }
         // Parse the pattern
         int flags = 0;
@@ -151,7 +153,7 @@ public class RewriteRule {
     }
 
 
-    private boolean escapeBackreferences = false;
+    private boolean escapeBackReferences = false;
 
     /**
      *  This flag chains the current rule with the next rule (which itself
@@ -328,11 +330,11 @@ public class RewriteRule {
     protected boolean type = false;
     protected String typeValue = null;
 
-    public boolean isEscapeBackreferences() {
-        return escapeBackreferences;
+    public boolean isEscapeBackReferences() {
+        return escapeBackReferences;
     }
-    public void setEscapeBackreferences(boolean escapeBackreferences) {
-        this.escapeBackreferences = escapeBackreferences;
+    public void setEscapeBackReferences(boolean escapeBackReferences) {
+        this.escapeBackReferences = escapeBackReferences;
     }
     public boolean isChain() {
         return chain;

Modified: tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteValve.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteValve.java?rev=1759516&r1=1759515&r2=1759516&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteValve.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteValve.java Tue 
Sep  6 21:26:17 2016
@@ -44,10 +44,10 @@ import org.apache.catalina.Pipeline;
 import org.apache.catalina.connector.Connector;
 import org.apache.catalina.connector.Request;
 import org.apache.catalina.connector.Response;
-import org.apache.catalina.util.URLEncoder;
 import org.apache.catalina.valves.ValveBase;
 import org.apache.tomcat.util.buf.CharChunk;
 import org.apache.tomcat.util.buf.MessageBytes;
+import org.apache.tomcat.util.buf.UDecoder;
 import org.apache.tomcat.util.buf.UriUtil;
 import org.apache.tomcat.util.http.RequestUtil;
 
@@ -439,7 +439,7 @@ public class RewriteValve extends ValveB
                     if (context) {
                         chunk.append(contextPath);
                     }
-                    chunk.append(URLEncoder.DEFAULT.encode(urlString, 
"UTF-8"));
+                    chunk.append(urlString);
                     request.getCoyoteRequest().requestURI().toChars();
                     // Decoded and normalized URI
                     request.getCoyoteRequest().decodedURI().setString(null);
@@ -448,7 +448,8 @@ public class RewriteValve extends ValveB
                     if (context) {
                         chunk.append(contextPath);
                     }
-                    chunk.append(RequestUtil.normalize(urlString));
+                    chunk.append(RequestUtil.normalize(UDecoder.URLDecode(
+                            urlString, 
request.getConnector().getURIEncoding())));
                     request.getCoyoteRequest().decodedURI().toChars();
                     // Set the new Query if there is one
                     if (queryString != null) {
@@ -641,7 +642,7 @@ public class RewriteValve extends ValveB
      */
     protected static void parseRuleFlag(String line, RewriteRule rule, String 
flag) {
         if (flag.equals("B")) {
-            rule.setEscapeBackreferences(true);
+            rule.setEscapeBackReferences(true);
         } else if (flag.equals("chain") || flag.equals("C")) {
             rule.setChain(true);
         } else if (flag.startsWith("cookie=") || flag.startsWith("CO=")) {

Modified: tomcat/trunk/java/org/apache/catalina/valves/rewrite/Substitution.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/rewrite/Substitution.java?rev=1759516&r1=1759515&r2=1759516&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/valves/rewrite/Substitution.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/valves/rewrite/Substitution.java Tue 
Sep  6 21:26:17 2016
@@ -20,8 +20,25 @@ import java.util.ArrayList;
 import java.util.Map;
 import java.util.regex.Matcher;
 
+import org.apache.catalina.util.URLEncoder;
+
 public class Substitution {
 
+    private static URLEncoder STATIC_ENCODER = new URLEncoder();
+    static {
+        // Defaults
+        STATIC_ENCODER.addSafeCharacter('~');
+        STATIC_ENCODER.addSafeCharacter('-');
+        STATIC_ENCODER.addSafeCharacter('_');
+        STATIC_ENCODER.addSafeCharacter('.');
+        STATIC_ENCODER.addSafeCharacter('*');
+        STATIC_ENCODER.addSafeCharacter('/');
+        // httpd doesn't encode these either
+        STATIC_ENCODER.addSafeCharacter('?');
+        STATIC_ENCODER.addSafeCharacter('=');
+    }
+
+
     public abstract class SubstitutionElement {
         public abstract String evaluate(Matcher rule, Matcher cond, Resolver 
resolver);
     }
@@ -31,7 +48,11 @@ public class Substitution {
 
         @Override
         public String evaluate(Matcher rule, Matcher cond, Resolver resolver) {
-            return value;
+            if (noEscape) {
+                return value;
+            } else {
+                return STATIC_ENCODER.encode(value, resolver.getUriEncoding());
+            }
         }
 
     }
@@ -40,7 +61,15 @@ public class Substitution {
         public int n;
         @Override
         public String evaluate(Matcher rule, Matcher cond, Resolver resolver) {
-            return rule.group(n);
+            if (escapeBackReferences) {
+                // Note: This should be consistent with the way httpd behaves.
+                //       We might want to consider providing a dedicated 
decoder
+                //       with an option to add additional safe characters to
+                //       provide users with more flexibility
+                return URLEncoder.DEFAULT.encode(rule.group(n), 
resolver.getUriEncoding());
+            } else {
+                return rule.group(n);
+            }
         }
     }
 
@@ -105,6 +134,16 @@ public class Substitution {
     public String getSub() { return sub; }
     public void setSub(String sub) { this.sub = sub; }
 
+    private boolean escapeBackReferences;
+    void setEscapeBackReferences(boolean escapeBackReferences) {
+        this.escapeBackReferences = escapeBackReferences;
+    }
+
+    private boolean noEscape;
+    void setNoEscape(boolean noEscape) {
+        this.noEscape = noEscape;
+    }
+
     public void parse(Map<String, RewriteMap> maps) {
 
         ArrayList<SubstitutionElement> elements = new ArrayList<>();

Modified: 
tomcat/trunk/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java?rev=1759516&r1=1759515&r2=1759516&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java 
(original)
+++ tomcat/trunk/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java 
Tue Sep  6 21:26:17 2016
@@ -41,17 +41,17 @@ public class TestRewriteValve extends To
 
     @Test
     public void testNoopRewrite() throws Exception {
-        doTestRewrite("RewriteRule ^(.*) $1", "/a/%255A", "/a/%255A");
+        doTestRewrite("RewriteRule ^(.*) $1 [B]", "/a/%255A", "/a/%255A");
     }
 
     @Test
     public void testPathRewrite() throws Exception {
-        doTestRewrite("RewriteRule ^/b(.*) /a$1", "/b/%255A", "/a/%255A");
+        doTestRewrite("RewriteRule ^/b(.*) /a$1 [B]", "/b/%255A", "/a/%255A");
     }
 
     @Test
     public void testNonNormalizedPathRewrite() throws Exception {
-        doTestRewrite("RewriteRule ^/b/(.*) /b/../a/$1", "/b/%255A", 
"/b/../a/%255A");
+        doTestRewrite("RewriteRule ^/b/(.*) /b/../a/$1 [B]", "/b/%255A", 
"/b/../a/%255A");
     }
 
     // BZ 57863
@@ -116,13 +116,13 @@ public class TestRewriteValve extends To
 
     @Test
     public void testNonAsciiPath() throws Exception {
-        doTestRewrite("RewriteRule ^/b/(.*) /c/$1", 
"/b/%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95",
+        doTestRewrite("RewriteRule ^/b/(.*) /c/$1 [B]", 
"/b/%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95",
                 "/c/%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95");
     }
 
     @Test
     public void testNonAsciiPathRedirect() throws Exception {
-        doTestRewrite("RewriteRule ^/b/(.*) /c/$1 [R]",
+        doTestRewrite("RewriteRule ^/b/(.*) /c/$1 [R,B]",
                 "/b/%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95",
                 "/c/%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95");
     }
@@ -134,21 +134,23 @@ public class TestRewriteValve extends To
 
     @Test
     public void testNonAsciiQueryString() throws Exception {
-        doTestRewrite("RewriteRule ^/b/(.*) /c?$1", 
"/b/id=%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95",
+        doTestRewrite("RewriteRule ^/b/id=(.*) /c?id=$1 [B]",
+                "/b/id=%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95",
                 "/c", "id=%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95");
     }
 
 
     @Test
     public void testNonAsciiQueryStringAndPath() throws Exception {
-        doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/$1?$2", 
"/b/%E5%9C%A8%E7%BA%BF/id=%E6%B5%8B%E8%AF%95",
+        doTestRewrite("RewriteRule ^/b/(.*)/id=(.*) /c/$1?id=$2 [B]",
+                "/b/%E5%9C%A8%E7%BA%BF/id=%E6%B5%8B%E8%AF%95",
                 "/c/%E5%9C%A8%E7%BA%BF", "id=%E6%B5%8B%E8%AF%95");
     }
 
 
     @Test
     public void testNonAsciiQueryStringRedirect() throws Exception {
-        doTestRewrite("RewriteRule ^/b/(.*) /c?$1 [R]",
+        doTestRewrite("RewriteRule ^/b/id=(.*) /c?id=$1 [R,B]",
                 "/b/id=%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95",
                 "/c", "id=%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95");
     }
@@ -156,7 +158,7 @@ public class TestRewriteValve extends To
 
     @Test
     public void testNonAsciiQueryStringAndRedirectPath() throws Exception {
-        doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/$1?$2 [R]",
+        doTestRewrite("RewriteRule ^/b/(.*)/id=(.*) /c/$1?id=$2 [R,B]",
                 "/b/%E5%9C%A8%E7%BA%BF/id=%E6%B5%8B%E8%AF%95",
                 "/c/%E5%9C%A8%E7%BA%BF", "id=%E6%B5%8B%E8%AF%95");
     }



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to