Author: markt Date: Mon Sep 12 16:00:27 2016 New Revision: 1760397 URL: http://svn.apache.org/viewvc?rev=1760397&view=rev Log: Follow-up for https://bz.apache.org/bugzilla/show_bug.cgi?id=60013 Fix some long lines and remove multiple calls to request.getConnector().getURIEncoding() Improve handling for QSA. Includes a test case provided by Santhana Preethi
Modified: tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteValve.java tomcat/trunk/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java tomcat/trunk/webapps/docs/changelog.xml 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=1760397&r1=1760396&r2=1760397&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteValve.java (original) +++ tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteValve.java Mon Sep 12 16:00:27 2016 @@ -323,12 +323,16 @@ public class RewriteValve extends ValveB // As long as MB isn't a char sequence or affiliated, this has to be // converted to a string - MessageBytes urlMB = context ? request.getRequestPathMB() : request.getDecodedRequestURIMB(); + String uriEncoding = request.getConnector().getURIEncoding(); + String originalQueryStringEncoded = request.getQueryString(); + MessageBytes urlMB = + context ? request.getRequestPathMB() : request.getDecodedRequestURIMB(); urlMB.toChars(); CharSequence urlDecoded = urlMB.getCharChunk(); CharSequence host = request.getServerName(); boolean rewritten = false; boolean done = false; + boolean qsa = false; for (int i = 0; i < rules.length; i++) { RewriteRule rule = rules[i]; CharSequence test = (rule.isHost()) ? host : urlDecoded; @@ -346,6 +350,13 @@ public class RewriteValve extends ValveB rewritten = true; } + // Check QSA before the final reply + if (!qsa && newtest != null && rule.isQsappend()) { + // TODO: This logic will need some tweaks if we add QSD + // support + qsa = true; + } + // Final reply // - forbidden @@ -360,10 +371,11 @@ public class RewriteValve extends ValveB done = true; break; } + // - redirect (code) if (rule.isRedirect() && newtest != null) { - // append the query string to the url if there is one and it hasn't been rewritten - String originalQueryStringEncoded = request.getQueryString(); + // Append the query string to the url if there is one and it + // hasn't been rewritten String urlStringDecoded = urlDecoded.toString(); int index = urlStringDecoded.indexOf("?"); String rewrittenQueryStringDecoded; @@ -374,16 +386,19 @@ public class RewriteValve extends ValveB urlStringDecoded = urlStringDecoded.substring(0, index); } - StringBuffer urlStringEncoded = new StringBuffer(ENCODER.encode(urlStringDecoded, request.getConnector().getURIEncoding())); - if (originalQueryStringEncoded != null && originalQueryStringEncoded.length() > 0) { + StringBuffer urlStringEncoded = + new StringBuffer(ENCODER.encode(urlStringDecoded, uriEncoding)); + if (originalQueryStringEncoded != null && + originalQueryStringEncoded.length() > 0) { if (rewrittenQueryStringDecoded == null) { urlStringEncoded.append('?'); urlStringEncoded.append(originalQueryStringEncoded); } else { - if (rule.isQsappend()) { + if (qsa) { // if qsa is specified append the query urlStringEncoded.append('?'); - urlStringEncoded.append(ENCODER.encode(rewrittenQueryStringDecoded, request.getConnector().getURIEncoding())); + urlStringEncoded.append( + ENCODER.encode(rewrittenQueryStringDecoded, uriEncoding)); urlStringEncoded.append('&'); urlStringEncoded.append(originalQueryStringEncoded); } else if (index == urlStringEncoded.length() - 1) { @@ -392,23 +407,27 @@ public class RewriteValve extends ValveB urlStringEncoded.deleteCharAt(index); } else { urlStringEncoded.append('?'); - urlStringEncoded.append(ENCODER.encode(rewrittenQueryStringDecoded, request.getConnector().getURIEncoding())); + urlStringEncoded.append( + ENCODER.encode(rewrittenQueryStringDecoded, uriEncoding)); } } } else if (rewrittenQueryStringDecoded != null) { urlStringEncoded.append('?'); - urlStringEncoded.append(ENCODER.encode(rewrittenQueryStringDecoded, request.getConnector().getURIEncoding())); + urlStringEncoded.append( + ENCODER.encode(rewrittenQueryStringDecoded, uriEncoding)); } // Insert the context if // 1. this valve is associated with a context // 2. the url starts with a leading slash // 3. the url isn't absolute - if (context && urlStringEncoded.charAt(0) == '/' && !UriUtil.hasScheme(urlStringEncoded)) { + if (context && urlStringEncoded.charAt(0) == '/' && + !UriUtil.hasScheme(urlStringEncoded)) { urlStringEncoded.insert(0, request.getContext().getEncodedPath()); } if (rule.isNoescape()) { - response.sendRedirect(URLDecoder.decode(urlStringEncoded.toString(), request.getConnector().getURIEncoding())); + response.sendRedirect( + URLDecoder.decode(urlStringEncoded.toString(), uriEncoding)); } else { response.sendRedirect(urlStringEncoded.toString()); } @@ -441,14 +460,6 @@ public class RewriteValve extends ValveB if (rule.isType() && newtest != null) { request.setContentType(rule.getTypeValue()); } - // - qsappend - if (rule.isQsappend() && newtest != null) { - String queryString = request.getQueryString(); - String urlString = urlDecoded.toString(); - if (urlString.indexOf('?') != -1 && queryString != null) { - urlDecoded = urlString + "&" + queryString; - } - } // Control flow processing @@ -501,7 +512,7 @@ public class RewriteValve extends ValveB // This is neither decoded nor normalized chunk.append(contextPath); } - chunk.append(ENCODER.encode(urlStringDecoded, request.getConnector().getURIEncoding())); + chunk.append(ENCODER.encode(urlStringDecoded, uriEncoding)); request.getCoyoteRequest().requestURI().toChars(); // Decoded and normalized URI // Rewriting may have denormalized the URL @@ -520,8 +531,14 @@ public class RewriteValve extends ValveB request.getCoyoteRequest().queryString().setString(null); chunk = request.getCoyoteRequest().queryString().getCharChunk(); chunk.recycle(); - chunk.append(ENCODER.encode(queryStringDecoded, request.getConnector().getURIEncoding())); - request.getCoyoteRequest().queryString().toChars(); + chunk.append(ENCODER.encode(queryStringDecoded, uriEncoding)); + if (qsa) { + chunk.append('&'); + chunk.append(originalQueryStringEncoded); + } + if (!chunk.isNull()) { + request.getCoyoteRequest().queryString().toChars(); + } } // Set the new host if it changed if (!host.equals(request.getServerName())) { 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=1760397&r1=1760396&r2=1760397&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java (original) +++ tomcat/trunk/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java Mon Sep 12 16:00:27 2016 @@ -131,6 +131,11 @@ public class TestRewriteValve extends To } @Test + public void testQueryStringRemove() throws Exception { + doTestRewrite("RewriteRule ^/b/(.*) /c/$1?", "/b/d?=1", "/c/d", null); + } + + @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", @@ -237,7 +242,7 @@ public class TestRewriteValve extends To // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [B,QSA]", "/b/%C2%A1/id=%C2%A1?di=%C2%AE", "/c/%C2%A1%25C2%25A1", - "id=%25C2%25A1&di=%25C2%25AE"); + "id=%25C2%25A1&di=%C2%AE"); } @@ -357,6 +362,15 @@ public class TestRewriteValve extends To } + @Test + public void testUtf8WithBothQsFlagsQSA() throws Exception { + // Note %C2%A1 == \u00A1 + doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [QSA]", + "/b/%C2%A1/id=%C2%A1?di=%C2%AE", "/c/%C2%A1%C2%A1", + "id=%C2%A1&di=%C2%AE"); + } + + @Test public void testUtf8WithRewriteQsFlagsRB() throws Exception { // Note %C2%A1 == \u00A1 Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1760397&r1=1760396&r2=1760397&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Mon Sep 12 16:00:27 2016 @@ -55,7 +55,9 @@ <fix> <bug>60013</bug>: Refactor the previous fix to align the behaviour of the Rewrite Valve with mod_rewite. As part of this, provide an - implementation for the <code>B</code> and <code>NE</code> flags. (markt) + implementation for the <code>B</code> and <code>NE</code> flags and + improve the handling for the <code>QSA</code> flag. Includes multiple + test cases by Santhana Preethi. (markt) </fix> </changelog> </subsection> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org