diff --git a/pom.xml b/pom.xml index 11207258c..0b468a70f 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ apache-site - scp://people.apache.org/www/struts.apache.org/2.3.1.1/ + scp://people.apache.org/www/struts.apache.org/2.x/ @@ -85,7 +85,7 @@ ${project.version} 3.0.5.RELEASE - 3.0.3 + 3.0.4 3.3 2.0.6 diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java b/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java index 5b94a79ac..d10451b56 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java @@ -135,7 +135,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor { static boolean devMode = false; // Allowed names of parameters - private String acceptedParamNames = "[a-zA-Z0-9\\.\\]\\[\\(\\)_']+"; + private String acceptedParamNames = "\\w+((\\.\\w+)|(\\[\\d+\\])|(\\(\\d+\\))|(\\['\\w+'\\])|(\\('\\w+'\\)))*"; private Pattern acceptedPattern = Pattern.compile(acceptedParamNames); private ValueStackFactory valueStackFactory; @@ -289,7 +289,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor { String name = entry.getKey(); Object value = entry.getValue(); try { - newStack.setValue(name, value); + newStack.setParameter(name, value); } catch (RuntimeException e) { if (devMode) { String developerNotification = LocalizedTextUtil.findText(ParametersInterceptor.class, "devmode.notification", ActionContext.getContext().getLocale(), "Developer Notification:\n{0}", new Object[]{ diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java b/xwork-core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java index 539410f8c..b4ae6d9c8 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java @@ -206,7 +206,23 @@ public class OgnlUtil { * Ideally, this should be handled by OGNL directly. */ public void setValue(String name, Map context, Object root, Object value) throws OgnlException { - Ognl.setValue(compile(name), context, root, value); + setValue(name, context, root, value, true); + } + + protected void setValue(String name, Map context, Object root, Object value, boolean evalName) throws OgnlException { + Object tree = compile(name); + if (!evalName && isEvalExpression(tree, context)) { + throw new OgnlException("Eval expression cannot be used as parameter name"); + } + Ognl.setValue(tree, context, root, value); + } + + private boolean isEvalExpression(Object tree, Map context) throws OgnlException { + if (tree instanceof SimpleNode) { + SimpleNode node = (SimpleNode) tree; + return node.isEvalChain((OgnlContext) context); + } + return false; } public Object getValue(String name, Map context, Object root) throws OgnlException { @@ -245,7 +261,7 @@ public class OgnlUtil { public void copy(Object from, Object to, Map context, Collection exclusions, Collection inclusions) { if (from == null || to == null) { if (LOG.isWarnEnabled()) { - LOG.warn("Attempting to copy from or to a null source. This is illegal and is bein skipped. This may be due to an error in an OGNL expression, action chaining, or some other event."); + LOG.warn("Attempting to copy from or to a null source. This is illegal and is bein skipped. This may be due to an error in an OGNL expression, action chaining, or some other event."); } return; @@ -284,7 +300,7 @@ public class OgnlUtil { copy = false; } - if (copy == true) { + if (copy) { PropertyDescriptor toPd = toPdHash.get(fromPd.getName()); if ((toPd != null) && (toPd.getWriteMethod() != null)) { try { diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStack.java b/xwork-core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStack.java index 7e66683b7..bf6ee9351 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStack.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStack.java @@ -144,6 +144,15 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS return root; } + /** + * @see com.opensymphony.xwork2.util.ValueStack#setParameter(String, Object) + */ + public void setParameter(String expr, Object value) { + setValue(expr, value, devMode, false); + } + + /** + /** * @see com.opensymphony.xwork2.util.ValueStack#setValue(java.lang.String, java.lang.Object) */ @@ -155,9 +164,13 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS * @see com.opensymphony.xwork2.util.ValueStack#setValue(java.lang.String, java.lang.Object, boolean) */ public void setValue(String expr, Object value, boolean throwExceptionOnFailure) { + setValue(expr, value, throwExceptionOnFailure, true); + } + + private void setValue(String expr, Object value, boolean throwExceptionOnFailure, boolean evalExpression) { Map context = getContext(); try { - trySetValue(expr, value, throwExceptionOnFailure, context); + trySetValue(expr, value, throwExceptionOnFailure, context, evalExpression); } catch (OgnlException e) { handleOgnlException(expr, value, throwExceptionOnFailure, e); } catch (RuntimeException re) { //XW-281 @@ -167,10 +180,10 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS } } - private void trySetValue(String expr, Object value, boolean throwExceptionOnFailure, Map context) throws OgnlException { + private void trySetValue(String expr, Object value, boolean throwExceptionOnFailure, Map context, boolean evalExpression) throws OgnlException { context.put(XWorkConverter.CONVERSION_PROPERTY_FULLNAME, expr); context.put(REPORT_ERRORS_ON_NO_PROP, (throwExceptionOnFailure) ? Boolean.TRUE : Boolean.FALSE); - ognlUtil.setValue(expr, context, root, value); + ognlUtil.setValue(expr, context, root, value, evalExpression); } private void cleanUpContext(Map context) { diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/util/ValueStack.java b/xwork-core/src/main/java/com/opensymphony/xwork2/util/ValueStack.java index c2a208634..b59bceedb 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/util/ValueStack.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/util/ValueStack.java @@ -74,6 +74,14 @@ public interface ValueStack { */ public abstract void setValue(String expr, Object value); + /** + * Attempts to set a property on a bean in the stack with the given expression using the default search order. + * N.B.: unlike #setValue(String,Object) it doesn't allow eval expression. + * @param expr the expression defining the path to the property to be set. + * @param value the value to be set into the named property + */ + void setParameter(String expr, Object value); + /** * Attempts to set a property on a bean in the stack with the given expression using the default search order. * diff --git a/xwork-core/src/test/java/com/opensymphony/xwork2/StubValueStack.java b/xwork-core/src/test/java/com/opensymphony/xwork2/StubValueStack.java index 563cf5b39..8432f2af8 100644 --- a/xwork-core/src/test/java/com/opensymphony/xwork2/StubValueStack.java +++ b/xwork-core/src/test/java/com/opensymphony/xwork2/StubValueStack.java @@ -50,6 +50,10 @@ public class StubValueStack implements ValueStack { ctx.put(expr, value); } + public void setParameter(String expr, Object value) { + throw new UnsupportedOperationException("not implemented"); + } + public void setValue(String expr, Object value, boolean throwExceptionOnFailure) { ctx.put(expr, value); } diff --git a/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java b/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java index c6fe41db8..5e9a9d683 100644 --- a/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java +++ b/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java @@ -509,6 +509,10 @@ public class ParametersInterceptorTest extends XWorkTestCase { public void setValue(String expr, Object value) { actual.put(expr, value); } + @Override + public void setParameter(String expr, Object value) { + actual.put(expr, value); + } }; container.inject(stack); return stack;