mirror of
https://github.com/apache/struts.git
synced 2026-08-06 07:06:58 +00:00
WW-4628: proper decoding of parameters in query-string
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user