Repository: struts Updated Branches: refs/heads/master 50328ffe1 -> 9b38ad8fc
WW-4628: proper decoding of parameters in query-string Project: http://git-wip-us.apache.org/repos/asf/struts/repo Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/9b38ad8f Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/9b38ad8f Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/9b38ad8f Branch: refs/heads/master Commit: 9b38ad8fcf20bdbdb6baacd5812bcf196d80ea07 Parents: 50328ff Author: cnenning <cnenn...@apache.org> Authored: Wed Aug 3 13:02:16 2016 +0200 Committer: cnenning <cnenn...@apache.org> Committed: Wed Sep 28 13:09:40 2016 +0200 ---------------------------------------------------------------------- .../org/apache/struts2/util/URLDecoderUtil.java | 12 ++++ .../struts2/views/util/DefaultUrlHelper.java | 27 +++++--- .../apache/struts2/util/URLDecoderUtilTest.java | 7 ++ .../views/util/DefaultUrlHelperTest.java | 71 +++++--------------- 4 files changed, 53 insertions(+), 64 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/struts/blob/9b38ad8f/core/src/main/java/org/apache/struts2/util/URLDecoderUtil.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/struts2/util/URLDecoderUtil.java b/core/src/main/java/org/apache/struts2/util/URLDecoderUtil.java index 10f2a78..3c61d1e 100644 --- a/core/src/main/java/org/apache/struts2/util/URLDecoderUtil.java +++ b/core/src/main/java/org/apache/struts2/util/URLDecoderUtil.java @@ -19,4 +19,16 @@ public class URLDecoderUtil { return UDecoder.URLDecode(sequence, charset); } + /** + * Decodes a <code>x-www-form-urlencoded</code> string. + * @param sequence the String to decode + * @param charset The name of a supported character encoding. + * @param isQueryString whether input is a query string. If <code>true</code> other decoding rules apply. + * @return the newly decoded <code>String</code> + * @exception IllegalArgumentException If the encoding is not valid + */ + public static String decode(String sequence, String charset, boolean isQueryString) { + return UDecoder.URLDecode(sequence, charset, isQueryString); + } + } http://git-wip-us.apache.org/repos/asf/struts/blob/9b38ad8f/core/src/main/java/org/apache/struts2/views/util/DefaultUrlHelper.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/struts2/views/util/DefaultUrlHelper.java b/core/src/main/java/org/apache/struts2/views/util/DefaultUrlHelper.java index 16739af..668d1a9 100644 --- a/core/src/main/java/org/apache/struts2/views/util/DefaultUrlHelper.java +++ b/core/src/main/java/org/apache/struts2/views/util/DefaultUrlHelper.java @@ -284,14 +284,25 @@ public class DefaultUrlHelper implements UrlHelper { * @return the encoded string */ public String decode( String input ) { - try { - return URLDecoderUtil.decode(input, encoding); - } catch (Exception e) { - LOG.warn("Could not decode URL parameter '{}', returning value un-decoded", input); - return input; - } + return URLDecoderUtil.decode(input, encoding, false); } + /** + * Decodes the URL using {@link URLDecoderUtil#decode(String, String, boolean)} with the encoding specified in the configuration. + * + * @param input the input to decode + * @param isQueryString whether input is a query string. If <code>true</code> other decoding rules apply. + * @return the encoded string + */ + public String decode( String input, boolean isQueryString ) { + try { + return URLDecoderUtil.decode(input, encoding, isQueryString); + } catch (Exception e) { + LOG.warn("Could not decode URL parameter '{}', returning value un-decoded", input); + return input; + } + } + public Map<String, Object> parseQueryString(String queryString, boolean forceValueArray) { Map<String, Object> queryParams = new LinkedHashMap<String, Object>(); if (queryString != null) { @@ -308,8 +319,8 @@ public class DefaultUrlHelper implements UrlHelper { paramValue = tmpParams[1]; } if (paramName != null) { - paramName = decode(paramName); - String translatedParamValue = decode(paramValue); + paramName = decode(paramName, true); + String translatedParamValue = decode(paramValue, true); if (queryParams.containsKey(paramName) || forceValueArray) { // WW-1619 append new param value to existing value(s) http://git-wip-us.apache.org/repos/asf/struts/blob/9b38ad8f/core/src/test/java/org/apache/struts2/util/URLDecoderUtilTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/struts2/util/URLDecoderUtilTest.java b/core/src/test/java/org/apache/struts2/util/URLDecoderUtilTest.java index f21c08f..fd274bf 100644 --- a/core/src/test/java/org/apache/struts2/util/URLDecoderUtilTest.java +++ b/core/src/test/java/org/apache/struts2/util/URLDecoderUtilTest.java @@ -68,4 +68,11 @@ public class URLDecoderUtilTest { assertEquals("xxxx\u00ea", result); } + @Test + public void testURLDecodePlusCharAsSpace() { + + String result = URLDecoderUtil.decode("a+b", "UTF-8", true); + assertEquals("a b", result); + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/struts/blob/9b38ad8f/core/src/test/java/org/apache/struts2/views/util/DefaultUrlHelperTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/struts2/views/util/DefaultUrlHelperTest.java b/core/src/test/java/org/apache/struts2/views/util/DefaultUrlHelperTest.java index 57786c4..b4a5b26 100644 --- a/core/src/test/java/org/apache/struts2/views/util/DefaultUrlHelperTest.java +++ b/core/src/test/java/org/apache/struts2/views/util/DefaultUrlHelperTest.java @@ -21,22 +21,23 @@ package org.apache.struts2.views.util; -import com.mockobjects.dynamic.Mock; -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Scope.Strategy; -import org.apache.struts2.StrutsConstants; -import org.apache.struts2.StrutsInternalTestCase; -import org.junit.Ignore; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.TreeMap; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.StrutsConstants; +import org.apache.struts2.StrutsInternalTestCase; + +import com.mockobjects.dynamic.Mock; +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.inject.Container; +import com.opensymphony.xwork2.inject.Scope.Strategy; + /** * Test case for DefaultUrlHelper. @@ -129,34 +130,6 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { expectedUrl, url.toString()); } - @Ignore - public void ignoreTestBuildUrlWithJavaScriptInjected() throws Exception { - String expectedUrl = "http://localhost:8080/myContext/myPage.jsp?initParam=initValue&param1=value1&param2=value2&param3%22%3Cscript+type%3D%22text%2Fjavascript%22%3Ealert%281%29%3B%3C%2Fscript%3E=value3"; - - // there is explicit escaping for EcmaScript before URL encoding - String expectedUrlBeforeEncoding = "http:\\/\\/localhost:8080\\/myContext\\/myPage.jsp?initParam=initValue&param1=value1&param2=value2&param3\\\"<script type=\\\"text\\/javascript\\\">alert(1);<\\/script>=value3"; - - Mock mockHttpServletRequest = new Mock(HttpServletRequest.class); - mockHttpServletRequest.expectAndReturn("getScheme", "http"); - mockHttpServletRequest.expectAndReturn("getServerName", "localhost"); - mockHttpServletRequest.expectAndReturn("getContextPath", "/myContext"); - mockHttpServletRequest.expectAndReturn("getServerPort", 8080); - - Mock mockHttpServletResponse = new Mock(HttpServletResponse.class); - mockHttpServletResponse.expectAndReturn("encodeURL", expectedUrlBeforeEncoding, expectedUrl); - - Map parameters = new LinkedHashMap(); - parameters.put("param1", "value1"); - parameters.put("param2", "value2"); - parameters.put("param3\"<script type=\"text/javascript\">alert(1);</script>","value3"); - - String result = urlHelper.buildUrl("/myPage.jsp?initParam=initValue", (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), parameters, "http", true, true, true); - - assertEquals( - expectedUrl, result); - mockHttpServletRequest.verify(); - } - public void testForceAddNullSchemeHostAndPort() throws Exception { String expectedUrl = "http://localhost/contextPath/path1/path2/myAction.action"; @@ -423,25 +396,11 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { assertEquals(result, expectedResult); } - @Ignore - public void ignoreTestDontEncode() throws Exception { - String expectedUrl = "http://localhost/contextPath/myAction.action?param1=value+with+spaces"; + public void testDecodeSpacesInQueryString() throws Exception { + Map<String, Object> queryParameters = urlHelper.parseQueryString("name=value+with+space", false); - Mock mockHttpServletRequest = new Mock(HttpServletRequest.class); - mockHttpServletRequest.expectAndReturn("getScheme", "http"); - mockHttpServletRequest.expectAndReturn("getServerName", "localhost"); - mockHttpServletRequest.expectAndReturn("getContextPath", "/contextPath"); - mockHttpServletRequest.expectAndReturn("getServerPort", 80); - - Mock mockHttpServletResponse = new Mock(HttpServletResponse.class); - - Map parameters = new LinkedHashMap(); - parameters.put("param1", "value+with+spaces"); - - String result = urlHelper.buildUrl("/myAction.action", (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), parameters, "http", true, false, true); - - assertEquals( - expectedUrl, result); + assertTrue(queryParameters.containsKey("name")); + assertEquals("value with space", queryParameters.get("name")); }