Skip to content

Commit

Permalink
Merged from STRUTS_2_3_14_X
Browse files Browse the repository at this point in the history
Disable eval expressions [from revision 1469249]
WW-4063
Improved security  by making static method attribute immutable [from revision 1486054]
WW-4063
Skipping unneeded translation for included parameters [from revision 1486076]
WW-4063
Testcase modification after refactoring [from revision 1486164]
WW-4063
Testcases for double parameter evaluation problems [from revision 1486576]

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@1486633 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
rgielen committed May 27, 2013
1 parent eb2a9eb commit d934c6e
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 68 deletions.
Expand Up @@ -241,47 +241,45 @@ public void buildParametersString(Map<String, Object> params, StringBuilder link

private String buildParameterSubstring(String name, String value) {
StringBuilder builder = new StringBuilder();
builder.append(translateAndEncode(name));
builder.append(encode(name));
builder.append('=');
builder.append(translateAndEncode(value));
builder.append(encode(value));
return builder.toString();
}

/**
* Translates any script expressions using {@link com.opensymphony.xwork2.util.TextParseUtil#translateVariables} and
* encodes the URL using {@link java.net.URLEncoder#encode} with the encoding specified in the configuration.
*
* @param input
* @return the translated and encoded string
*/
public String translateAndEncode(String input) {
String translatedInput = translateVariable(input);
try {
return URLEncoder.encode(translatedInput, encoding);
} catch (UnsupportedEncodingException e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not encode URL parameter '#0', returning value un-encoded", input);
}
return translatedInput;
}
}

public String translateAndDecode(String input) {
String translatedInput = translateVariable(input);
try {
return URLDecoder.decode(translatedInput, encoding);
} catch (UnsupportedEncodingException e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not encode URL parameter '#0', returning value un-encoded", input);
}
return translatedInput;
}
}

private String translateVariable(String input) {
ValueStack valueStack = ServletActionContext.getContext().getValueStack();
return TextParseUtil.translateVariables(input, valueStack);
}
/**
* Encodes the URL using {@link java.net.URLEncoder#encode} with the encoding specified in the configuration.
*
* @param input the input to encode
* @return the encoded string
*/
public String encode( String input ) {
try {
return URLEncoder.encode(input, encoding);
} catch (UnsupportedEncodingException e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not encode URL parameter '#0', returning value un-encoded", input);
}
return input;
}
}

/**
* Decodes the URL using {@link java.net.URLDecoder#decode(String, String)} with the encoding specified in the configuration.
*
* @param input the input to decode
* @return the encoded string
*/
public String decode( String input ) {
try {
return URLDecoder.decode(input, encoding);
} catch (UnsupportedEncodingException e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not decode URL parameter '#0', returning value un-decoded", input);
}
return input;
}
}

public Map<String, Object> parseQueryString(String queryString, boolean forceValueArray) {
Map<String, Object> queryParams = new LinkedHashMap<String, Object>();
Expand All @@ -299,8 +297,8 @@ public Map<String, Object> parseQueryString(String queryString, boolean forceVal
paramValue = tmpParams[1];
}
if (paramName != null) {
paramName = translateAndDecode(paramName);
String translatedParamValue = translateAndDecode(paramValue);
paramName = decode(paramName);
String translatedParamValue = decode(paramValue);

if (queryParams.containsKey(paramName) || forceValueArray) {
// WW-1619 append new param value to existing value(s)
Expand Down
105 changes: 85 additions & 20 deletions core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java
Expand Up @@ -21,16 +21,12 @@

package org.apache.struts2.views.jsp;

import java.io.File;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspWriter;

import com.mockobjects.dynamic.Mock;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.DefaultActionInvocation;
import com.opensymphony.xwork2.DefaultActionProxyFactory;
import com.opensymphony.xwork2.inject.Container;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.components.URL;
import org.apache.struts2.dispatcher.ApplicationMap;
Expand All @@ -40,15 +36,14 @@
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.dispatcher.mapper.DefaultActionMapper;

import com.mockobjects.dynamic.Mock;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.DefaultActionInvocation;
import com.opensymphony.xwork2.DefaultActionProxy;
import com.opensymphony.xwork2.DefaultActionProxyFactory;
import com.opensymphony.xwork2.config.providers.XWorkConfigurationProvider;
import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
import com.opensymphony.xwork2.inject.Container;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspWriter;
import java.io.File;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Unit test for {@link URLTag}.
Expand Down Expand Up @@ -619,6 +614,69 @@ public void testEmptyActionCustomMapper() throws Exception {

}

public void testEmbeddedParamTagExpressionGetsEvaluatedCorrectly() throws Exception {
request.setRequestURI("/public/about");
request.setQueryString("section=team&company=acme inc");

tag.setAction("team");
tag.setIncludeParams("all");

tag.doStartTag();

Foo foo = new Foo("test");
stack.push(foo);

// include nested param tag
ParamTag paramTag = new ParamTag();
paramTag.setPageContext(pageContext);
paramTag.setName("title");
paramTag.setValue("%{title}");
paramTag.doStartTag();
paramTag.doEndTag();

tag.doEndTag();

assertEquals("/team.action?section=team&amp;company=acme+inc&amp;title=test", writer.toString());
}

public void testAccessToStackInternalsGetsHandledCorrectly() throws Exception {
Map<String, Object> params = new HashMap<String, Object>();
params.put("aaa", new String[] {"1${#session[\"foo\"]='true'}"});
params.put("aab", new String[] {"1${#session[\"bar\"]}"});
params.put("aac", new String[] {"1${#_memberAccess[\"allowStaticMethodAccess\"]='true'}"});
params.put("aad", new String[] {"1${#_memberAccess[\"allowStaticMethodAccess\"]}"});

request.setParameterMap(params);
request.setRequestURI("/public/about");
request.setQueryString("aae${%23session[\"bar\"]}=1%24%7B%23session%5B%22bar%22%5D%7D");
session.put("bar", "rab");

tag.setAction("team");
tag.setIncludeParams("all");

tag.doStartTag();
tag.doEndTag();

Object allowMethodAccess = stack.findValue("\u0023_memberAccess['allowStaticMethodAccess']");
assertNotNull(allowMethodAccess);
assertEquals(Boolean.FALSE, allowMethodAccess);

assertNull(session.get("foo"));

assertEquals("/team.action?" +
"aab=1%24%7B%23session%5B%22bar%22%5D%7D" +
"&amp;" +
"aac=1%24%7B%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3D%27true%27%7D" +
"&amp;" +
"aaa=1%24%7B%23session%5B%22foo%22%5D%3D%27true%27%7D" +
"&amp;" +
"aad=1%24%7B%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%7D" +
"&amp;"+
"aae%24%7B%23session%5B%22bar%22%5D%7D=1%24%7B%23session%5B%22bar%22%5D%7D"
, writer.toString()
);
}

protected void setUp() throws Exception {
super.setUp();

Expand All @@ -635,7 +693,14 @@ protected void setUp() throws Exception {
public static class Foo {
private String title;

public void setTitle(String title) {
public Foo() {
}

public Foo( String title ) {
this.title = title;
}

public void setTitle(String title) {
this.title = title;
}

Expand Down
Expand Up @@ -378,17 +378,17 @@ public void testParseNullQuery() throws Exception {
}


public void testTranslateAndEncode() throws Exception {
public void testEncode() throws Exception {
setProp(StrutsConstants.STRUTS_I18N_ENCODING, "UTF-8");
String result = urlHelper.translateAndEncode("\u65b0\u805e");
String result = urlHelper.encode("\u65b0\u805e");
String expectedResult = "%E6%96%B0%E8%81%9E";

assertEquals(result, expectedResult);
}

public void testTranslateAndDecode() throws Exception {
public void testDecode() throws Exception {
setProp(StrutsConstants.STRUTS_I18N_ENCODING, "UTF-8");
String result = urlHelper.translateAndDecode("%E6%96%B0%E8%81%9E");
String result = urlHelper.decode("%E6%96%B0%E8%81%9E");
String expectedResult = "\u65b0\u805e";

assertEquals(result, expectedResult);
Expand Down
Expand Up @@ -32,7 +32,7 @@
*/
public class SecurityMemberAccess extends DefaultMemberAccess {

private boolean allowStaticMethodAccess;
private final boolean allowStaticMethodAccess;
Set<Pattern> excludeProperties = Collections.emptySet();
Set<Pattern> acceptProperties = Collections.emptySet();

Expand All @@ -45,10 +45,6 @@ public boolean getAllowStaticMethodAccess() {
return allowStaticMethodAccess;
}

public void setAllowStaticMethodAccess(boolean allowStaticMethodAccess) {
this.allowStaticMethodAccess = allowStaticMethodAccess;
}

@Override
public boolean isAccessible(Map context, Object target, Member member,
String propertyName) {
Expand Down

0 comments on commit d934c6e

Please sign in to comment.