WCKET-6010 new encoder for header
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/7b4c7047 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/7b4c7047 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/7b4c7047 Branch: refs/heads/lambdas Commit: 7b4c7047b9b9189872f09409c6c7dada70fb648d Parents: 5d51aed Author: Sven Meier <[email protected]> Authored: Fri Oct 23 19:27:02 2015 +0200 Committer: Sven Meier <[email protected]> Committed: Wed Oct 28 14:41:15 2015 +0100 ---------------------------------------------------------------------- .../http/servlet/ServletWebResponseTest.java | 4 +- .../apache/wicket/request/http/WebResponse.java | 2 +- .../apache/wicket/util/encoding/UrlEncoder.java | 87 ++++++++++++-------- .../wicket/util/encoding/UrlEncoderTest.java | 43 ++++++++++ 4 files changed, 99 insertions(+), 37 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/7b4c7047/wicket-core/src/test/java/org/apache/wicket/protocol/http/servlet/ServletWebResponseTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/protocol/http/servlet/ServletWebResponseTest.java b/wicket-core/src/test/java/org/apache/wicket/protocol/http/servlet/ServletWebResponseTest.java index 5c5e9eb..e9fd4fa 100644 --- a/wicket-core/src/test/java/org/apache/wicket/protocol/http/servlet/ServletWebResponseTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/protocol/http/servlet/ServletWebResponseTest.java @@ -130,10 +130,10 @@ public class ServletWebResponseTest extends Assert HttpServletResponse httpResponse = new MockHttpServletResponse(httpRequest); ServletWebResponse response = new ServletWebResponse(webRequest, httpResponse); - response.setInlineHeader("name with spaces"); + response.setInlineHeader("name with spaces and;,"); String header = httpResponse.getHeader("Content-Disposition"); assertEquals( - "inline; filename=\"name%20with%20spaces\"; filename*=UTF-8''name%20with%20spaces", + "inline; filename=\"name%20with%20spaces%20and%3B%2C\"; filename*=UTF-8''name%20with%20spaces%20and%3B%2C", header); // says: "name with bulgarian" http://git-wip-us.apache.org/repos/asf/wicket/blob/7b4c7047/wicket-request/src/main/java/org/apache/wicket/request/http/WebResponse.java ---------------------------------------------------------------------- diff --git a/wicket-request/src/main/java/org/apache/wicket/request/http/WebResponse.java b/wicket-request/src/main/java/org/apache/wicket/request/http/WebResponse.java index a790d0b..4183940 100644 --- a/wicket-request/src/main/java/org/apache/wicket/request/http/WebResponse.java +++ b/wicket-request/src/main/java/org/apache/wicket/request/http/WebResponse.java @@ -175,7 +175,7 @@ public abstract class WebResponse extends Response { return (Strings.isEmpty(filename) ? "" : String.format( "; filename=\"%1$s\"; filename*=UTF-8''%1$s", - UrlEncoder.PATH_INSTANCE.encode(filename, "UTF-8"))); + UrlEncoder.HEADER_INSTANCE.encode(filename, "UTF-8"))); } /** http://git-wip-us.apache.org/repos/asf/wicket/blob/7b4c7047/wicket-util/src/main/java/org/apache/wicket/util/encoding/UrlEncoder.java ---------------------------------------------------------------------- diff --git a/wicket-util/src/main/java/org/apache/wicket/util/encoding/UrlEncoder.java b/wicket-util/src/main/java/org/apache/wicket/util/encoding/UrlEncoder.java index d03b7f1..85b18bd 100644 --- a/wicket-util/src/main/java/org/apache/wicket/util/encoding/UrlEncoder.java +++ b/wicket-util/src/main/java/org/apache/wicket/util/encoding/UrlEncoder.java @@ -42,17 +42,15 @@ public class UrlEncoder * encoder types */ public enum Type { - /** - * query type - */ QUERY, - /** - * path type - */ - PATH + PATH, + HEADER } - // list of what not to decode + /** + * List of what not to encode, i.e. characters (e.g. A-Z) and other allowed signs (e.g. !) + * that are allowed but don't have a special meaning. + */ protected BitSet dontNeedEncoding; // used in decoding @@ -67,7 +65,7 @@ public class UrlEncoder public static final UrlEncoder QUERY_INSTANCE = new UrlEncoder(Type.QUERY); /** - * Encoder used to encode components of a path.<br/> + * Encoder used to encode segments of a path.<br/> * <br/> * * For example: http://org.acme/foo/thispart/orthispart?butnot=thispart @@ -75,6 +73,11 @@ public class UrlEncoder public static final UrlEncoder PATH_INSTANCE = new UrlEncoder(Type.PATH); /** + * Encoder used to encode a header. + */ + public static final UrlEncoder HEADER_INSTANCE = new UrlEncoder(Type.HEADER); + + /** * Allow subclass to call constructor. * * @param type @@ -154,29 +157,25 @@ public class UrlEncoder // sub-delims dontNeedEncoding.set('!'); dontNeedEncoding.set('$'); - // "&" needs to be encoded for query stings - // "(" and ")" probably don't need encoding, but we'll be conservative - dontNeedEncoding.set('*'); - // "+" needs to be encoded for query strings (since it means = - dontNeedEncoding.set(','); - // ";" encoded due to use in path and/or query as delim in some - // instances (e.g., jsessionid) - // "=" needs to be encoded for query strings - - // pchar - dontNeedEncoding.set(':'); // allowed and used in wicket interface - // params - dontNeedEncoding.set('@'); // encoding type-specific switch (type) { - // this code consistent with java.net.URLEncoder version case QUERY : + // this code consistent with java.net.URLEncoder version# + // encoding a space to a + is done in the encode() method dontNeedEncoding.set(' '); - // to allow direct passing of URL in query - dontNeedEncoding.set('/'); + + // sub-delims continued + dontNeedEncoding.set('*'); + dontNeedEncoding.set('/'); // to allow direct passing of URL in query + dontNeedEncoding.set(','); + // "'" doesn't need encoding, but it will make it easier to use in in JavaScript + // "(" and ")" don't need encoding, but we'll be conservative + + dontNeedEncoding.set(':'); // allowed and used in wicket interface + dontNeedEncoding.set('@'); /* * the below encoding of a ? is disabled because it interferes in portlet @@ -185,21 +184,41 @@ public class UrlEncoder * re-enable it as portlet environments are not high priority. we can also add a * switch somewhere to enable/disable this on applicaiton level. (WICKET-4019) */ - - // to allow direct passing of URL in query - // dontNeedEncoding.set('?'); + // dontNeedEncoding.set('?'); // to allow direct passing of URL in query break; - // this added to deal with encoding a PATH component case PATH : - // encode ' ' with a % instead of + in path portion - - // path component sub-delim values we do not need to escape + // this added to deal with encoding a PATH segment + + // sub-delims continued + dontNeedEncoding.set('*'); dontNeedEncoding.set('&'); + dontNeedEncoding.set('+'); + // "'" doesn't need encoding, but it will make it easier to use in in JavaScript + // "(" and ")" don't need encoding, but we'll be conservative + dontNeedEncoding.set(','); + dontNeedEncoding.set(';'); // semicolon is used in ;jsessionid= dontNeedEncoding.set('='); + + dontNeedEncoding.set(':'); // allowed and used in wicket interface + dontNeedEncoding.set('@'); + + break; + + // this added to deal with encoding a PATH component + case HEADER : + // this added to deal with encoding of header + + // ' ' is encoded + + // sub-delims continued + dontNeedEncoding.set('#'); + dontNeedEncoding.set('&'); dontNeedEncoding.set('+'); - // don't encode semicolon because it is used in ;jsessionid= - dontNeedEncoding.set(';'); + + dontNeedEncoding.set('^'); + dontNeedEncoding.set('`'); + dontNeedEncoding.set('|'); break; } } http://git-wip-us.apache.org/repos/asf/wicket/blob/7b4c7047/wicket-util/src/test/java/org/apache/wicket/util/encoding/UrlEncoderTest.java ---------------------------------------------------------------------- diff --git a/wicket-util/src/test/java/org/apache/wicket/util/encoding/UrlEncoderTest.java b/wicket-util/src/test/java/org/apache/wicket/util/encoding/UrlEncoderTest.java index c88e74d..1f86c05 100644 --- a/wicket-util/src/test/java/org/apache/wicket/util/encoding/UrlEncoderTest.java +++ b/wicket-util/src/test/java/org/apache/wicket/util/encoding/UrlEncoderTest.java @@ -24,6 +24,49 @@ import org.junit.Test; @SuppressWarnings("javadoc") public class UrlEncoderTest extends Assert { + + // starts with ä + private static final char[] encodingCandidates = "\u00c4!\"§$%&/()=?`*'_:;><,.-#+´\\}][{|".toCharArray(); + + @Test + public void pathUnencoded() { + String unencoded = "azAZ09.-_~!$&*+,;=:@"; + + assertEquals(unencoded, UrlEncoder.PATH_INSTANCE.encode(unencoded, CharEncoding.UTF_8)); + + for (char candidate : encodingCandidates) { + if (unencoded.indexOf(candidate) == -1) { + assertNotEquals("" + candidate, UrlEncoder.PATH_INSTANCE.encode("" + candidate, CharEncoding.UTF_8)); + } + } + } + + @Test + public void queryStringUnencoded() { + String unencoded = "azAZ09.-_~!$*,:@/"; + + assertEquals(unencoded, UrlEncoder.QUERY_INSTANCE.encode(unencoded, CharEncoding.UTF_8)); + + for (char candidate : encodingCandidates) { + if (unencoded.indexOf(candidate) == -1) { + assertNotEquals("" + candidate, UrlEncoder.QUERY_INSTANCE.encode("" + candidate, CharEncoding.UTF_8)); + } + } + } + + @Test + public void headerUnencoded() { + String unencoded = "azAZ09.-_~!$&+#^`|"; + + assertEquals(unencoded, UrlEncoder.HEADER_INSTANCE.encode(unencoded, CharEncoding.UTF_8)); + + for (char candidate : encodingCandidates) { + if (unencoded.indexOf(candidate) == -1) { + assertNotEquals("" + candidate, UrlEncoder.HEADER_INSTANCE.encode("" + candidate, CharEncoding.UTF_8)); + } + } + } + /** * <a href="https://issues.apache.org/jira/browse/WICKET-3721">WICKET-3721</a> Encode * apostrophes because otherwise they get XML encoded by ComponentTag#writeOutput() to
