You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2014/04/06 16:03:29 UTC
[16/50] [abbrv] git commit: Extends parser to allow parse collections
Extends parser to allow parse collections
Project: http://git-wip-us.apache.org/repos/asf/struts/repo
Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/c03962c8
Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/c03962c8
Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/c03962c8
Branch: refs/heads/master
Commit: c03962c8c0d972c7e17a9f6d247887754fbe7f3f
Parents: 49ecb5f
Author: Lukasz Lenart <lu...@apache.org>
Authored: Sat Mar 22 09:41:00 2014 +0100
Committer: Lukasz Lenart <lu...@apache.org>
Committed: Sat Mar 22 09:41:00 2014 +0100
----------------------------------------------------------------------
.../opensymphony/xwork2/util/TextParseUtil.java | 87 ++++++++++++++++++++
.../xwork2/util/TextParseUtilTest.java | 45 +++++++++-
2 files changed, 130 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/struts/blob/c03962c8/xwork-core/src/main/java/com/opensymphony/xwork2/util/TextParseUtil.java
----------------------------------------------------------------------
diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/util/TextParseUtil.java b/xwork-core/src/main/java/com/opensymphony/xwork2/util/TextParseUtil.java
index 4b54e81..a3938ef 100644
--- a/xwork-core/src/main/java/com/opensymphony/xwork2/util/TextParseUtil.java
+++ b/xwork-core/src/main/java/com/opensymphony/xwork2/util/TextParseUtil.java
@@ -16,9 +16,13 @@
package com.opensymphony.xwork2.util;
import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
import com.opensymphony.xwork2.inject.Container;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
@@ -168,6 +172,89 @@ public class TextParseUtil {
}
/**
+ * @see #translateVariablesCollection(char[], String, ValueStack, boolean, ParsedValueEvaluator, int)
+ *
+ * @param expression
+ * @param stack
+ * @param excludeEmptyElements
+ * @param evaluator
+ * @return
+ */
+ public static Collection<String> translateVariablesCollection(String expression, ValueStack stack, boolean excludeEmptyElements, ParsedValueEvaluator evaluator) {
+ return translateVariablesCollection(new char[]{'$', '%'}, expression, stack, excludeEmptyElements, evaluator, MAX_RECURSION);
+ }
+
+ /**
+ * Resolves given expression on given ValueStack. If found element is a
+ * collection each element will be converted to String. If just a single
+ * object is found it is converted to String and wrapped in a collection.
+ *
+ * @param openChars
+ * @param expression
+ * @param stack
+ * @param excludeEmptyElements
+ * @param evaluator
+ * @param maxLoopCount
+ * @return
+ */
+ public static Collection<String> translateVariablesCollection(
+ char[] openChars, String expression, final ValueStack stack, boolean excludeEmptyElements,
+ final ParsedValueEvaluator evaluator, int maxLoopCount) {
+
+ ParsedValueEvaluator ognlEval = new ParsedValueEvaluator() {
+ public Object evaluate(String parsedValue) {
+ return stack.findValue(parsedValue); // no asType !!!
+ }
+ };
+
+ Map<String, Object> context = stack.getContext();
+ TextParser parser = ((Container)context.get(ActionContext.CONTAINER)).getInstance(TextParser.class);
+
+ Object result = parser.evaluate(openChars, expression, ognlEval, maxLoopCount);
+
+ XWorkConverter conv = ((Container)context.get(ActionContext.CONTAINER)).getInstance(XWorkConverter.class);
+
+ Collection<String> resultCol;
+ if (result instanceof Collection) {
+ @SuppressWarnings("unchecked")
+ Collection<Object> casted = (Collection<Object>)result;
+ resultCol = new ArrayList<String>(casted.size());
+ for (Object element : casted) {
+ String stringElement = (String)conv.convertValue(context, element, String.class);
+ if (shallBeIncluded(stringElement, excludeEmptyElements)) {
+ if (evaluator != null) {
+ stringElement = evaluator.evaluate(stringElement).toString();
+ }
+ resultCol.add(stringElement);
+ }
+ }
+ } else {
+ resultCol = new ArrayList<String>(1);
+ String stringResult = (String)conv.convertValue(context, result, String.class);
+ if (shallBeIncluded(stringResult, excludeEmptyElements)) {
+ if (evaluator != null) {
+ stringResult = evaluator.evaluate(stringResult).toString();
+ }
+ resultCol.add(stringResult);
+ }
+ }
+
+ return resultCol;
+ }
+
+ /**
+ * Tests if given string is not null and not empty when excluding of empty
+ * elements is requested.
+ *
+ * @param str String to check.
+ * @param excludeEmptyElements Whether empty elements shall be excluded.
+ * @return True if given string can be included in collection.
+ */
+ private static boolean shallBeIncluded(String str, boolean excludeEmptyElements) {
+ return !excludeEmptyElements || ((str != null) && (str.length() > 0));
+ }
+
+ /**
* Returns a set from comma delimted Strings.
* @param s The String to parse.
* @return A set from comma delimted Strings.
http://git-wip-us.apache.org/repos/asf/struts/blob/c03962c8/xwork-core/src/test/java/com/opensymphony/xwork2/util/TextParseUtilTest.java
----------------------------------------------------------------------
diff --git a/xwork-core/src/test/java/com/opensymphony/xwork2/util/TextParseUtilTest.java b/xwork-core/src/test/java/com/opensymphony/xwork2/util/TextParseUtilTest.java
index 45e7970..a624a10 100644
--- a/xwork-core/src/test/java/com/opensymphony/xwork2/util/TextParseUtilTest.java
+++ b/xwork-core/src/test/java/com/opensymphony/xwork2/util/TextParseUtilTest.java
@@ -15,11 +15,19 @@
*/
package com.opensymphony.xwork2.util;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Assert;
+
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.XWorkTestCase;
-import java.util.*;
-
/**
* Unit test of {@link TextParseUtil}.
*
@@ -177,4 +185,37 @@ public class TextParseUtilTest extends XWorkTestCase {
assertEquals("foo: ", s);
}
+ public void testTranslateVariablesCollection() {
+ ValueStack stack = ActionContext.getContext().getValueStack();
+ final List<String> list = new ArrayList<String>() {{
+ add("val 1");
+ add("val 2");
+ }};
+ stack.push(new HashMap<String, Object>() {{ put("list", list); }});
+
+ Collection<String> collection = TextParseUtil.translateVariablesCollection("${list}", stack, true, null);
+
+ Assert.assertNotNull(collection);
+ Assert.assertEquals(2, collection.size());
+ }
+
+ public void testTranslateVariablesCollectionWithExpressions() {
+ ValueStack stack = ActionContext.getContext().getValueStack();
+ final List<String> list = new ArrayList<String>() {{
+ add("${val1}");
+ add("%{val2}");
+ }};
+ stack.push(new HashMap<String, Object>() {{ put("list", list); put("val1", 1); put("val2", "Value 2"); }});
+
+ Collection<String> collection = TextParseUtil.translateVariablesCollection("${list}", stack, true, null);
+
+ Assert.assertNotNull(collection);
+ Assert.assertEquals(2, collection.size());
+
+ // if this starts passing, probably an double evaluation expression vulnerability was introduced
+ // carefully review changes as this can affect users and allows break in intruders
+ Assert.assertEquals("${val1}", collection.toArray()[0]);
+ Assert.assertEquals("%{val2}", collection.toArray()[1]);
+ }
+
}