]> source.dussan.org Git - vaadin-framework.git/commitdiff
#7671 Do not permit HTML in system messages and normal error messages, XHTML mode...
authorHenri Sara <henri.sara@itmill.com>
Tue, 27 Sep 2011 08:35:12 +0000 (08:35 +0000)
committerHenri Sara <henri.sara@itmill.com>
Tue, 27 Sep 2011 08:35:12 +0000 (08:35 +0000)
svn changeset:21327/svn branch:6.6

src/com/vaadin/data/Validator.java
src/com/vaadin/data/validator/AbstractValidator.java
src/com/vaadin/terminal/SystemError.java
src/com/vaadin/terminal/UserError.java
src/com/vaadin/ui/AbstractComponent.java
src/com/vaadin/ui/Panel.java

index 21a9da9f9721ce891b859d7182a2c7d0a5104cca..b1dc5ffc14985895461367a1b1ed6ab1f9e4680d 100644 (file)
@@ -9,6 +9,7 @@ import java.io.Serializable;
 import com.vaadin.terminal.ErrorMessage;
 import com.vaadin.terminal.PaintException;
 import com.vaadin.terminal.PaintTarget;
+import com.vaadin.terminal.gwt.server.AbstractApplicationServlet;
 
 /**
  * Interface that implements a method for validating if an {@link Object} is
@@ -63,6 +64,12 @@ public interface Validator extends Serializable {
     /**
      * Exception that is thrown by a {@link Validator} when a value is invalid.
      * 
+     * <p>
+     * The default implementation of InvalidValueException does not support HTML
+     * in error messages. To enable HTML support, override
+     * {@link #getHtmlMessage()} and use the subclass in validators.
+     * </p>
+     * 
      * @author IT Mill Ltd.
      * @version
      * @VERSION@
@@ -154,7 +161,7 @@ public interface Validator extends Serializable {
             target.addAttribute("level", "error");
 
             // Error message
-            final String message = getLocalizedMessage();
+            final String message = getHtmlMessage();
             if (message != null) {
                 target.addText(message);
             }
@@ -167,6 +174,16 @@ public interface Validator extends Serializable {
             target.endTag("error");
         }
 
+        /**
+         * Returns the message of the error in HTML.
+         * 
+         * Note that this API may change in future versions.
+         */
+        protected String getHtmlMessage() {
+            return AbstractApplicationServlet
+                    .safeEscapeForHtml(getLocalizedMessage());
+        }
+
         /*
          * (non-Javadoc)
          * 
index 7d4f1c3a0d777e1eee82a138cdeda419fdc6847b..ee2fee893c9da245e53524a0ddb2eb92574bd8ba 100644 (file)
@@ -15,6 +15,12 @@ import com.vaadin.data.Validator;
  * (converted to string using {@link #toString()}) or "null" if the value is
  * null.
  * </p>
+ * <p>
+ * The default implementation of AbstractValidator does not support HTML in
+ * error messages. To enable HTML support, override
+ * {@link InvalidValueException#getHtmlMessage()} and throw such exceptions from
+ * {@link #validate(Object)}.
+ * </p>
  * 
  * @author IT Mill Ltd.
  * @version
index 8b721c07f5dc5e9e33e2acf530544c68dd71f139..fb1de0c4940cf97a4b2d1dd0ac0a253a70ef6fad 100644 (file)
@@ -7,12 +7,18 @@ package com.vaadin.terminal;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 
+import com.vaadin.terminal.gwt.server.AbstractApplicationServlet;
+
 /**
  * <code>SystemError</code> is a runtime exception caused by error in system.
  * The system error can be shown to the user as it implements
  * <code>ErrorMessage</code> interface, but contains technical information such
  * as stack trace and exception.
  * 
+ * SystemError does not support HTML in error messages or stack traces. If HTML
+ * messages are required, use {@link UserError} or a custom implementation of
+ * {@link ErrorMessage}.
+ * 
  * @author IT Mill Ltd.
  * @version
  * @VERSION@
@@ -75,11 +81,26 @@ public class SystemError extends RuntimeException implements ErrorMessage {
         target.startTag("error");
         target.addAttribute("level", "system");
 
+        String message = getHtmlMessage();
+
+        target.addXMLSection("div", message,
+                "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
+
+        target.endTag("error");
+
+    }
+
+    /**
+     * Returns the message of the error in HTML.
+     * 
+     * Note that this API may change in future versions.
+     */
+    protected String getHtmlMessage() {
         StringBuilder sb = new StringBuilder();
         final String message = getLocalizedMessage();
         if (message != null) {
             sb.append("<h2>");
-            sb.append(message);
+            sb.append(AbstractApplicationServlet.safeEscapeForHtml(message));
             sb.append("</h2>");
         }
 
@@ -89,15 +110,11 @@ public class SystemError extends RuntimeException implements ErrorMessage {
             final StringWriter buffer = new StringWriter();
             cause.printStackTrace(new PrintWriter(buffer));
             sb.append("<pre>");
-            sb.append(buffer.toString());
+            sb.append(AbstractApplicationServlet.safeEscapeForHtml(buffer
+                    .toString()));
             sb.append("</pre>");
         }
-
-        target.addXMLSection("div", sb.toString(),
-                "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
-
-        target.endTag("error");
-
+        return sb.toString();
     }
 
     /**
index bcce0ed2838fc8289b115a630562af40caabf8e2..d33c02d144285dbad984f9f5da49a324e27dcd1b 100644 (file)
@@ -4,6 +4,8 @@
 
 package com.vaadin.terminal;
 
+import com.vaadin.terminal.gwt.server.AbstractApplicationServlet;
+
 /**
  * <code>UserError</code> is a controlled error occurred in application. User
  * errors are occur in normal usage of the application and guide the user.
@@ -32,6 +34,11 @@ public class UserError implements ErrorMessage {
      */
     public static final int CONTENT_UIDL = 2;
 
+    /**
+     * Content mode, where the error contains XHTML.
+     */
+    public static final int CONTENT_XHTML = 3;
+
     /**
      * Content mode.
      */
@@ -80,24 +87,24 @@ public class UserError implements ErrorMessage {
         level = errorLevel;
     }
 
-    /* Documenten in interface */
+    /* Documented in interface */
     public int getErrorLevel() {
         return level;
     }
 
-    /* Documenten in interface */
+    /* Documented in interface */
     public void addListener(RepaintRequestListener listener) {
     }
 
-    /* Documenten in interface */
+    /* Documented in interface */
     public void removeListener(RepaintRequestListener listener) {
     }
 
-    /* Documenten in interface */
+    /* Documented in interface */
     public void requestRepaint() {
     }
 
-    /* Documenten in interface */
+    /* Documented in interface */
     public void paint(PaintTarget target) throws PaintException {
 
         target.startTag("error");
@@ -118,21 +125,25 @@ public class UserError implements ErrorMessage {
         // Paint the message
         switch (mode) {
         case CONTENT_TEXT:
-            target.addText(msg);
+            target.addText(AbstractApplicationServlet.safeEscapeForHtml(msg));
             break;
         case CONTENT_UIDL:
             target.addUIDL(msg);
             break;
         case CONTENT_PREFORMATTED:
-            target.startTag("pre");
+            target.addText("<pre>"
+                    + AbstractApplicationServlet.safeEscapeForHtml(msg)
+                    + "</pre>");
+            break;
+        case CONTENT_XHTML:
             target.addText(msg);
-            target.endTag("pre");
+            break;
         }
 
         target.endTag("error");
     }
 
-    /* Documenten in interface */
+    /* Documented in interface */
     public void requestRepaintRequests() {
     }
 
index 784ecb262b6232a8f1126b28acc4e5cdc608358d..da55aa7fa0ffbaeb85a41ee757efef8ee583172a 100644 (file)
@@ -449,9 +449,10 @@ public abstract class AbstractComponent implements Component, MethodEventSource
 
     /**
      * <p>
-     * Gets the component's description. The description can be used to briefly
-     * describe the state of the component to the user. The description string
-     * may contain certain XML tags:
+     * Gets the component's description, used in tooltips and can be displayed
+     * directly in certain other components such as forms. The description can
+     * be used to briefly describe the state of the component to the user. The
+     * description string may contain certain XML tags:
      * </p>
      * 
      * <p>
@@ -513,6 +514,10 @@ public abstract class AbstractComponent implements Component, MethodEventSource
      * {@link com.vaadin.terminal.Paintable.RepaintRequestEvent
      * RepaintRequestEvent}.
      * 
+     * The description is displayed as HTML/XHTML in tooltips or directly in
+     * certain components so care should be taken to avoid creating the
+     * possibility for HTML injection and possibly XSS vulnerabilities.
+     * 
      * @param description
      *            the new description string for the component.
      */
index 73140fd79a57e0b499927998a1147416431e4ee9..877171232ec2f9592ea74df1dd6016d12e9bd6d5 100644 (file)
@@ -105,7 +105,7 @@ public class Panel extends AbstractComponentContainer implements Scrollable,
      * Creates a new empty panel with caption. Default layout is used.
      * 
      * @param caption
-     *            the caption used in the panel.
+     *            the caption used in the panel (HTML/XHTML).
      */
     public Panel(String caption) {
         this(caption, null);
@@ -115,7 +115,7 @@ public class Panel extends AbstractComponentContainer implements Scrollable,
      * Creates a new empty panel with the given caption and content.
      * 
      * @param caption
-     *            the caption of the panel.
+     *            the caption of the panel (HTML/XHTML).
      * @param content
      *            the content used in the panel.
      */
@@ -124,6 +124,20 @@ public class Panel extends AbstractComponentContainer implements Scrollable,
         setCaption(caption);
     }
 
+    /**
+     * Sets the caption of the panel.
+     * 
+     * Note that the caption is interpreted as HTML/XHTML and therefore care
+     * should be taken not to enable HTML injection and XSS attacks using panel
+     * captions. This behavior may change in future versions.
+     * 
+     * @see AbstractComponent#setCaption(String)
+     */
+    @Override
+    public void setCaption(String caption) {
+        super.setCaption(caption);
+    }
+
     /**
      * Gets the current layout of the panel.
      *