001: package org.apache.velocity.test;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: import java.io.IOException;
023: import java.io.StringWriter;
024: import java.io.Writer;
025: import java.util.Collection;
026: import java.util.HashSet;
027:
028: import junit.framework.Test;
029: import junit.framework.TestSuite;
030:
031: import org.apache.velocity.VelocityContext;
032: import org.apache.velocity.app.VelocityEngine;
033: import org.apache.velocity.context.Context;
034: import org.apache.velocity.exception.MethodInvocationException;
035: import org.apache.velocity.exception.ParseErrorException;
036: import org.apache.velocity.exception.ResourceNotFoundException;
037: import org.apache.velocity.runtime.RuntimeConstants;
038: import org.apache.velocity.util.introspection.SecureUberspector;
039:
040: /**
041: * Checks that the secure introspector is working properly.
042: *
043: * @author <a href="Will Glass-Husain">wglass@forio.com</a>
044: * @version $Id: SecureIntrospectionTestCase.java 509906 2007-02-21 06:11:05Z wglass $
045: */
046: public class SecureIntrospectionTestCase extends BaseTestCase {
047:
048: /**
049: * Default constructor.
050: * @param name
051: */
052: public SecureIntrospectionTestCase(String name) {
053: super (name);
054: }
055:
056: public static Test suite() {
057: return new TestSuite(SecureIntrospectionTestCase.class);
058: }
059:
060: private String[] badTemplateStrings = { "$test.Class.Methods",
061: "$test.Class.ClassLoader",
062: "$test.Class.ClassLoader.loadClass('java.util.HashMap').newInstance().size()" };
063:
064: private String[] goodTemplateStrings = {
065: "#foreach($item in $test.collection)$item#end",
066: "$test.Class.Name",
067: "#set($test.Property = 'abc')$test.Property",
068: "$test.aTestMethod()" };
069:
070: /**
071: * Test to see that "dangerous" methods are forbidden
072: * @exception Exception
073: */
074: public void testBadMethodCalls() throws Exception {
075: VelocityEngine ve = new VelocityEngine();
076: ve.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME,
077: SecureUberspector.class.getName());
078: ve.init();
079:
080: /*
081: * all of the following method calls should not work
082: */
083: doTestMethods(ve, badTemplateStrings, false);
084: }
085:
086: /**
087: * Test to see that "dangerous" methods are forbidden
088: * @exception Exception
089: */
090: public void testGoodMethodCalls() throws Exception {
091: VelocityEngine ve = new VelocityEngine();
092: ve.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME,
093: SecureUberspector.class.getName());
094: ve.init();
095:
096: /*
097: * all of the following method calls should not work
098: */
099: doTestMethods(ve, goodTemplateStrings, true);
100: }
101:
102: private void doTestMethods(VelocityEngine ve,
103: String[] templateStrings, boolean shouldeval) {
104: Context c = new VelocityContext();
105: c.put("test", this );
106:
107: try {
108: for (int i = 0; i < templateStrings.length; i++) {
109: if (shouldeval
110: && !doesStringEvaluate(ve, c,
111: templateStrings[i])) {
112: fail("Should have evaluated: " + templateStrings[i]);
113: }
114:
115: if (!shouldeval
116: && doesStringEvaluate(ve, c, templateStrings[i])) {
117: fail("Should not have evaluated: "
118: + templateStrings[i]);
119: }
120: }
121:
122: } catch (Exception e) {
123: fail(e.toString());
124: }
125: }
126:
127: private boolean doesStringEvaluate(VelocityEngine ve, Context c,
128: String inputString) throws ParseErrorException,
129: MethodInvocationException, ResourceNotFoundException,
130: IOException {
131: // assume that an evaluation is bad if the input and result are the same (e.g. a bad reference)
132: // or the result is an empty string (e.g. bad #foreach)
133: Writer w = new StringWriter();
134: ve.evaluate(c, w, "foo", inputString);
135: String result = w.toString();
136: return (result.length() > 0) && !result.equals(inputString);
137: }
138:
139: private String testProperty;
140:
141: public String getProperty() {
142: return testProperty;
143: }
144:
145: public int aTestMethod() {
146: return 1;
147: }
148:
149: public void setProperty(String val) {
150: testProperty = val;
151: }
152:
153: public Collection getCollection() {
154: Collection c = new HashSet();
155: c.add("aaa");
156: c.add("bbb");
157: c.add("ccc");
158: return c;
159: }
160:
161: }
|