Commits

Anonymous committed b43885f

- resolves the escaping issue, WW-278
- merged the ViewToolBean with the WebWorkUtil object
- modify tag libraries to use $webwork to htmlEncode the values for the various tags
- removed a hard coded

git-svn-id: http://svn.opensymphony.com/svn/webwork/trunk@243573baa09-0c28-0410-bef9-dab3c582ae83

  • Participants
  • Parent commits 01eb1b6

Comments (0)

Files changed (17)

src/java/com/opensymphony/webwork/util/WebWorkUtil.java

  */
 package com.opensymphony.webwork.util;
 
-import javax.servlet.*;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletRequest;
+import com.opensymphony.util.TextUtils;
+
+import com.opensymphony.webwork.views.util.UrlHelper;
+
+import com.opensymphony.xwork.Action;
+
+import org.apache.commons.logging.*;
+
+import org.apache.velocity.app.Velocity;
+import org.apache.velocity.context.Context;
+import org.apache.velocity.exception.MethodInvocationException;
+import org.apache.velocity.exception.ParseErrorException;
+import org.apache.velocity.exception.ResourceNotFoundException;
+
 import java.io.*;
+
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
+
+import java.net.URLEncoder;
+
+import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Map;
-import java.util.HashMap;
 
-import org.apache.commons.logging.*;
-import org.apache.velocity.app.Velocity;
-import org.apache.velocity.context.Context;
-import org.apache.velocity.exception.ResourceNotFoundException;
-import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.ParseErrorException;
-import com.opensymphony.xwork.Action;
-import com.opensymphony.webwork.views.util.UrlHelper;
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
 
 /**
- *	WebWork utility methods for Velocity templates
+ *        WebWork utility methods for Velocity templates
  *
- *	@author Rickard Öberg (rickard@dreambean.com)
- *	@version $Revision$
+ *        @author Rickard Öberg (rickard@dreambean.com)
+ *        @version $Revision$
  */
 public final class WebWorkUtil {
+    //~ Static fields/initializers /////////////////////////////////////////////
+
     private static final Log log = LogFactory.getLog(WebWorkUtil.class);
 
-    private Context ctx;
+    //~ Instance fields ////////////////////////////////////////////////////////
+
     Map classes = new Hashtable();
+    private Context ctx;
+
+    //~ Constructors ///////////////////////////////////////////////////////////
 
     public WebWorkUtil(Context ctx) {
         this.ctx = ctx;
     }
 
-    public Object bean(Object aName)
-            throws Exception {
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public Object bean(Object aName) throws Exception {
         String name = aName.toString();
         Class c = (Class) classes.get(name);
+
         if (c == null) {
             c = ClassLoaderUtils.loadClass(name, WebWorkUtil.class);
             classes.put(name, c);
         }
+
         return c.newInstance();
     }
 
-    public String include(Object aName, ServletRequest aRequest, ServletResponse aResponse)
-            throws Exception {
+    public String evaluate(String expression) throws IOException, ResourceNotFoundException, MethodInvocationException, ParseErrorException {
+        CharArrayWriter writer = new CharArrayWriter();
+        Velocity.evaluate(ctx, writer, "Error parsing " + expression, expression);
+
+        return writer.toString();
+    }
+
+    public String htmlEncode(String s) {
+        return TextUtils.htmlEncode(s);
+    }
+
+    public String include(Object aName, ServletRequest aRequest, ServletResponse aResponse) throws Exception {
         try {
             RequestDispatcher dispatcher = aRequest.getRequestDispatcher(aName.toString());
+
             if (dispatcher == null) {
                 throw new IllegalArgumentException("Cannot find included file " + aName);
             }
+
             ServletResponseHandler responseHandler = new ServletResponseHandler(aResponse);
-            Class[] interfaces = new Class[]{HttpServletResponse.class};
+            Class[] interfaces = new Class[] {HttpServletResponse.class};
             HttpServletResponse response = (HttpServletResponse) Proxy.newProxyInstance(getClass().getClassLoader(), interfaces, responseHandler);
 
             dispatcher.include(aRequest, response);
         }
     }
 
+    public String textToHtml(String s) {
+        return TextUtils.plainTextToHtml(s);
+    }
+
+    public int toInt(long aLong) {
+        return (int) aLong;
+    }
+
     public long toLong(int anInt) {
         return (long) anInt;
     }
         return Long.parseLong(aLong);
     }
 
-    public int toInt(long aLong) {
-        return (int) aLong;
-    }
-
     public String toString(long aLong) {
         return Long.toString(aLong);
     }
         return Integer.toString(anInt);
     }
 
-    public String evaluate(String expression) throws IOException, ResourceNotFoundException, MethodInvocationException, ParseErrorException {
-        CharArrayWriter writer = new CharArrayWriter();
-        Velocity.evaluate(ctx, writer, "Error parsing " + expression, expression);
-        return writer.toString();
+    public String urlEncode(String s) {
+        return URLEncoder.encode(s);
     }
 
-    static class ServletResponseHandler
-            implements InvocationHandler {
-        ServletResponse response;
+    //~ Inner Classes //////////////////////////////////////////////////////////
+
+    static class ServletOutputStreamWrapper extends ServletOutputStream {
+        ByteArrayOutputStream stream;
+
+        ServletOutputStreamWrapper(ByteArrayOutputStream aStream) {
+            stream = aStream;
+        }
+
+        public void write(int aByte) {
+            stream.write(aByte);
+        }
+    }
+
+    static class ServletResponseHandler implements InvocationHandler {
         ByteArrayOutputStream bout;
         PrintWriter writer;
         ServletOutputStream sout;
+        ServletResponse response;
 
         ServletResponseHandler(ServletResponse aResponse) {
             response = aResponse;
             writer = new PrintWriter(new OutputStreamWriter(bout));
         }
 
-        public Object invoke(Object proxy,
-                             Method method,
-                             Object[] args)
-                throws Throwable {
+        public String getData() {
+            writer.flush();
+
+            return bout.toString();
+        }
+
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
             if (method.getName().equals("getOutputStream")) {
                 return getOutputStream();
             } else if (method.getName().equals("getWriter")) {
         ServletOutputStream getOutputStream() {
             return sout;
         }
-
-        public String getData() {
-            writer.flush();
-            return bout.toString();
-        }
     }
-
-    static class ServletOutputStreamWrapper
-            extends ServletOutputStream {
-        ByteArrayOutputStream stream;
-
-        ServletOutputStreamWrapper(ByteArrayOutputStream aStream) {
-            stream = aStream;
-        }
-
-        public void write(int aByte) {
-            stream.write(aByte);
-        }
-    }
-
 }

src/java/com/opensymphony/webwork/views/velocity/ParamDirective.java

 
 import com.opensymphony.webwork.views.jsp.ParameterizedTag;
 
-import com.opensymphony.xwork.util.OgnlValueStack;
 import com.opensymphony.xwork.ActionContext;
+import com.opensymphony.xwork.util.OgnlValueStack;
 
 import org.apache.velocity.context.InternalContextAdapter;
 import org.apache.velocity.exception.MethodInvocationException;
 import java.io.IOException;
 import java.io.Writer;
 
+
 /**
  * <p>
  * The ParamDirective allows for additional parameters to be passed in to a given tag before the tag is rendered.  By
         Object object = contextAdapter.get(VelocityManager.TAG);
 
         if ((object != null) && (object instanceof ParameterizedTag)) {
-            if (node.jjtGetNumChildren() != 2 || node.jjtGetNumChildren() != 3) {
+            if ((node.jjtGetNumChildren() != 2) && (node.jjtGetNumChildren() != 3)) {
                 throw new ParseErrorException("#param directive requires two parameters, a key and a value.  an optional flag to evaluate it may be included.");
             }
 
             Object value = node.jjtGetChild(1).value(contextAdapter);
 
             // if there are ever 3 params, the we should look up the value against the value stack
-            if (node.jjtGetNumChildren() == 3 && "TRUE".equalsIgnoreCase(node.jjtGetChild(2).value(contextAdapter).toString())) {
+            if ((node.jjtGetNumChildren() == 3) && "TRUE".equalsIgnoreCase(node.jjtGetChild(2).value(contextAdapter).toString())) {
                 OgnlValueStack valueStack = ActionContext.getContext().getValueStack();
                 value = valueStack.findValue(value.toString());
             }

src/java/com/opensymphony/webwork/views/velocity/VelocityManager.java

 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import org.apache.velocity.VelocityContext;
 import org.apache.velocity.app.Velocity;
 import org.apache.velocity.app.VelocityEngine;
 import org.apache.velocity.context.Context;
-import org.apache.velocity.VelocityContext;
 
 import java.io.File;
 import java.io.FileInputStream;
     public static final String STACK = "stack";
     public static final String OGNL = "ognl";
     public static final String WEBWORK = "webwork";
-    public static final String UI = "ui";
     public static final String ACTION = "action";
-    public static final String TOOLS = "tools";
 
     /** the parent JSP tag */
     public static final String PARENT = "parent";
     //~ Instance fields ////////////////////////////////////////////////////////
 
     private OgnlTool ognlTool = OgnlTool.getInstance();
-    private ViewToolsBean viewTools = new ViewToolsBean();
     private VelocityEngine velocityEngine;
     private VelocityContext[] chainedContexts;
 
     //~ Methods ////////////////////////////////////////////////////////////////
 
     /**
-     * performs one-time initializations
-     */
-    protected void init() {
-        /**
-         * allow users to specify via the webwork.properties file a set of additional VelocityContexts to chain to the
-         * the WebWorkVelocityContext.  The intent is to allow these contexts to store helper objects that the ui
-         * developer may want access to.  Examples of reasonable VelocityContexts would be an IoCVelocityContext, a
-         * SpringReferenceVelocityContext, and a ToolboxVelocityContext
-         */
-        if (Configuration.isSet("webwork.velocity.contexts")) {
-
-            // we expect contexts to be a comma separated list of classnames
-            String contexts = Configuration.get("webwork.velocity.contexts").toString();
-            StringTokenizer st = new StringTokenizer(contexts, ",");
-            List contextList = new ArrayList();
-            while (st.hasMoreTokens()) {
-                String classname = st.nextToken();
-                try {
-                    VelocityContext velocityContext = (VelocityContext) Class.forName(classname).newInstance();
-                    contextList.add(velocityContext);
-                } catch (Exception e) {
-                    log.warn("Warning.  " + e.getClass().getName() + " caught while attempting to instantiate a chained VelocityContext, " + classname + " -- skipping");
-                }
-            }
-
-            if (contextList.size() > 0) {
-                VelocityContext[] chainedContexts = new VelocityContext[contextList.size()];
-                contextList.toArray(chainedContexts);
-                this.chainedContexts = chainedContexts;
-            } else {
-                this.chainedContexts = null;
-            }
-        }
-    }
-
-    /**
      * retrieve an instance to the current VelocityManager
      *
      * @return
      * <li><strong>ognl</strong> - an {@link OgnlTool}</li>
      * <li><strong>webwork</strong> - an instance of {@link WebWorkUtil}</li>
      * <li><strong>action</strong> - the current WebWork action</li>
-     * <li><strong>tools</strong> - an instance of {@link ViewToolsBean}</li>
      * </ul>
      *
      * @return a new WebWorkVelocityContext
         context.put(RESPONSE, servletResponse);
         context.put(STACK, stack);
         context.put(OGNL, ognlTool);
-        context.put(TOOLS, viewTools);
         context.put(WEBWORK, new WebWorkUtil(context));
 
         ActionInvocation invocation = (ActionInvocation) stack.getContext().get(ActionContext.ACTION_INVOCATION);
             log.debug("Initializing Velocity with the following properties ...");
 
             for (Iterator iter = properties.keySet().iterator();
-                 iter.hasNext();) {
+                    iter.hasNext();) {
                 String key = (String) iter.next();
                 String value = properties.getProperty(key);
 
     }
 
     /**
+     * performs one-time initializations
+     */
+    protected void init() {
+        /**
+         * allow users to specify via the webwork.properties file a set of additional VelocityContexts to chain to the
+         * the WebWorkVelocityContext.  The intent is to allow these contexts to store helper objects that the ui
+         * developer may want access to.  Examples of reasonable VelocityContexts would be an IoCVelocityContext, a
+         * SpringReferenceVelocityContext, and a ToolboxVelocityContext
+         */
+        if (Configuration.isSet("webwork.velocity.contexts")) {
+            // we expect contexts to be a comma separated list of classnames
+            String contexts = Configuration.get("webwork.velocity.contexts").toString();
+            StringTokenizer st = new StringTokenizer(contexts, ",");
+            List contextList = new ArrayList();
+
+            while (st.hasMoreTokens()) {
+                String classname = st.nextToken();
+
+                try {
+                    VelocityContext velocityContext = (VelocityContext) Class.forName(classname).newInstance();
+                    contextList.add(velocityContext);
+                } catch (Exception e) {
+                    log.warn("Warning.  " + e.getClass().getName() + " caught while attempting to instantiate a chained VelocityContext, " + classname + " -- skipping");
+                }
+            }
+
+            if (contextList.size() > 0) {
+                VelocityContext[] chainedContexts = new VelocityContext[contextList.size()];
+                contextList.toArray(chainedContexts);
+                this.chainedContexts = chainedContexts;
+            } else {
+                this.chainedContexts = null;
+            }
+        }
+    }
+
+    /**
      * <p/>
      * instantiate a new VelocityEngine
      * </p>
          */
         String userdirective = p.getProperty("userdirective");
         String directives = "com.opensymphony.webwork.views.velocity.ParamDirective" + "," + "com.opensymphony.webwork.views.velocity.TagDirective" + "," + "com.opensymphony.webwork.views.velocity.BodyTagDirective";
-        p.setProperty("velocimacro.library", "webwork.vm");
 
         if ((userdirective == null) || userdirective.trim().equals("")) {
             userdirective = directives;
         } else {
-            userdirective = directives + "," + userdirective.trim();
+            userdirective = userdirective.trim() + "," + directives;
         }
 
         p.setProperty("userdirective", userdirective);

src/java/com/opensymphony/webwork/views/velocity/ViewToolsBean.java

-package com.opensymphony.webwork.views.velocity;
-
-import com.opensymphony.util.TextUtils;
-
-import java.net.URLEncoder;
-
-/**
- * A simple bean with some useful utility methods for use in Velocity views.
- *
- * It's added as $tools in the Velocity context.
- */
-public class ViewToolsBean
-{
-    public String urlEncode(String s)
-    {
-        return URLEncoder.encode(s);
-    }
-
-    public String htmlEncode(String s)
-    {
-        return TextUtils.htmlEncode(s);
-    }
-
-    public String textToHtml(String s)
-    {
-        return TextUtils.plainTextToHtml(s);
-    }
-}

src/java/template/xhtml/checkbox.vm

             <tr><td valign="top">
                 <input type="checkbox"
                        name="$!parameters.name"
-                       value="$!parameters.fieldValue"
+                       value="$!webwork.htmlEncode($parameters.fieldValue)"
                 #if ($parameters.nameValue)        checked="checked" #end
                 #if ($parameters.disabled == true) disabled="disabled"                #end
                 #if ($parameters.tabindex)         tabindex="$parameters.tabindex"    #end

src/java/template/xhtml/checkboxlist.vm

         #end
 
   <div>
-   <input type="checkbox" name="$!{parameters.name}" value="$!{itemKey}" #if( $tag.contains($parameters.nameValue, $itemKey) ) checked #end/>
+   <input type="checkbox" name="$!{parameters.name}" value="$!webwork.htmlEncode($itemKey)" #if( $tag.contains($parameters.nameValue, $itemKey) ) checked #end/>
    <label class="label">$!itemValue</label>
   </div>
 

src/java/template/xhtml/combobox.vm

        name="$!parameters.name"
 #if ($parameters.size)             size="$parameters.size"            #end
 #if ($parameters.maxlength)        maxlength="$parameters.maxlength"  #end
-#if ($parameters.nameValue)        value="$parameters.nameValue"      #end
+#if ($parameters.nameValue)        value="$webwork.htmlEncode($parameters.nameValue)"      #end
 #if ($parameters.disabled == true) disabled="disabled"                #end
 #if ($parameters.onkeyup)          onkeyup="$parameters.onkeyup"      #end
 #if ($parameters.tabindex)         tabindex="$parameters.tabindex"    #end
          #if ($parameters.disabled == true) disabled="disabled" #end
       >
             #foreach ($param in $parameters.list)
-                <option value="$!param" #if ($parameters.name == $param) selected="selected" #end >$!param</option>
+                <option value="$webwork.htmlEncode($param)" #if ($parameters.name == $param) selected="selected" #end >$!param</option>
             #end
       </select>
 #end

src/java/template/xhtml/doubleselect.vm

   #else
       #set( $itemValue = $item.toString() )
   #end
-  <option value="$!{itemValue}"#if( $tag.contains($tag.ActualValue, $itemValue) ) selected#end>$!{itemKey}</option>
+  <option value="$!webwork.htmlEncode($itemValue)"#if( $tag.contains($tag.ActualValue, $itemValue) ) selected#end>$!{itemKey}</option>
 #end
 </select>
 

src/java/template/xhtml/file.vm

 <input type="file"
                                    name="$!parameters.name"
 #if ($parameters.size)             size="$parameters.size"            #end
-#if ($parameters.nameValue)        value="$parameters.nameValue"      #end
+#if ($parameters.nameValue)        value="$webwork.htmlEncode($parameters.nameValue)"      #end
 #if ($parameters.disabled == true) disabled="disabled"                #end
 #if ($parameters.id)               id="$parameters.id"                #end
 #if ($parameters.accept)           accept="$parameters.accept"        #end

src/java/template/xhtml/hidden.vm

 <input
     type="hidden"
     #if ($parameters.name)      name="$parameters.name"       #end
-    #if ($parameters.nameValue) value="$parameters.nameValue" #end
+    #if ($parameters.nameValue) value="$webwork.htmlEncode($parameters.nameValue)" #end
 />

src/java/template/xhtml/password.vm

 #if ($parameters.size)             size="$parameters.size"            #end
 #if ($parameters.maxlength)        maxlength="$parameters.maxlength"  #end
 
-#if ($parameters.nameValue && $parameters.showPassword == true)        value="$parameters.nameValue"      #end
+#if ($parameters.nameValue && $parameters.showPassword == true)        value="$webwork.htmlEncode($parameters.nameValue)"      #end
 
 #if ($parameters.disabled == true) disabled="disabled"                #end
 #if ($parameters.readonly)         readonly="readonly"                #end

src/java/template/xhtml/radiomap.vm

             type="radio"
             #if( $tag.contains($parameters.nameValue, $itemKey) )checked="checked"#end
             #if ($parameters.name)      name="$parameters.name"         #end
-            #if ($itemKey)              value="$itemKey"                #end
+            #if ($itemKey)              value="$webwork.htmlEncode($itemKey)"                #end
             #if ($parameters.disabled)  disabled="disabled"             #end
             #if ($parameters.tabindex)  tabindex="$parameters.tabindex" #end
             #if ($parameters.onchange)  onchange="$parameters.onchange" #end

src/java/template/xhtml/select.vm

 >
 
 #if ($parameters.headerKey && $parameters.headerValue)
-    <option value="$parameters.headerKey">$parameters.headerValue</option>
+    <option value="$webwork.htmlEncode($parameters.headerKey)">$parameters.headerValue</option>
 #end
 
 #if ($parameters.emptyOption)
             #set( $itemValue = $item )
         #end
 
-        <option value="$!itemKey"
+        <option value="$!webwork.htmlEncode($itemKey)"
             #if( $tag.contains($parameters.nameValue, $itemKey) )selected#end
         >$!itemValue</option>
 

src/java/template/xhtml/submit.vm

         ><input
             type="submit"
             #if ($parameters.name)       name="$parameters.name"           #end
-            #if ($parameters.nameValue)  value="$parameters.nameValue"     #end
+            #if ($parameters.nameValue)  value="$webwork.htmlEncode($parameters.nameValue)"     #end
         /></div>
 #parse( "/template/xhtml/controlfooter.vm" )

src/java/template/xhtml/text.vm

                                    name="$!parameters.name"
 #if ($parameters.size)             size="$parameters.size"            #end
 #if ($parameters.maxlength)        maxlength="$parameters.maxlength"  #end
-#if ($parameters.nameValue)        value="$parameters.nameValue"      #end
+#if ($parameters.nameValue)        value="$webwork.htmlEncode($parameters.nameValue)"      #end
 #if ($parameters.disabled == true) disabled="disabled"                #end
 #if ($parameters.readonly)         readonly="readonly"                #end
 #if ($parameters.onkeyup)          onkeyup="$parameters.onkeyup"      #end

src/java/template/xhtml/textarea.vm

 <textarea name="$!parameters.name"
           cols="$!parameters.cols"
           rows="$!parameters.rows"
-#if ($parameters.nameValue)        value="$parameters.nameValue"      #end
+#if ($parameters.nameValue)        value="$webwork.htmlEncode($parameters.nameValue)"      #end
 #if ($parameters.disabled == true) disabled="disabled"                #end
 #if ($parameters.readonly)         readonly="readonly"                #end
 #if ($parameters.onkeyup)          onkeyup="$parameters.onkeyup"      #end

src/java/template/xhtml/token.vm

-<input type="hidden" name="$!{tag.tokenNameField}" value="$!parameters.name"/>
-<input type="hidden" name="$!parameters.name" value="$!parameters.token"/>
+<input type="hidden" name="$!{tag.tokenNameField}" value="$webwork.htmlEncode($!parameters.name)"/>
+<input type="hidden" name="$!parameters.name" value="$webwork.htmlEncode($!parameters.token)"/>