struts-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "ASF GitHub Bot (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (WW-4888) HTML escaping on the text tag
Date Thu, 09 Nov 2017 17:04:00 GMT

    [ https://issues.apache.org/jira/browse/WW-4888?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16246042#comment-16246042
] 

ASF GitHub Bot commented on WW-4888:
------------------------------------

lukaszlenart closed pull request #181: WW-4888 add escaping possibilities to text-tag
URL: https://github.com/apache/struts/pull/181
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/core/src/main/java/org/apache/struts2/components/Text.java b/core/src/main/java/org/apache/struts2/components/Text.java
index c7935ac7c..a5ea21715 100644
--- a/core/src/main/java/org/apache/struts2/components/Text.java
+++ b/core/src/main/java/org/apache/struts2/components/Text.java
@@ -19,6 +19,7 @@
 package org.apache.struts2.components;
 
 import com.opensymphony.xwork2.util.ValueStack;
+import org.apache.commons.lang3.StringEscapeUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -58,6 +59,10 @@
  *
  * <ul>
  *      <li>name* (String) - the i18n message key</li>
+ *      <li>escapeHtml (Boolean) - Escape HTML. Defaults to false</li>
+ *      <li>escapeJavaScript (Boolean) - Escape JavaScript. Defaults to false</li>
+ *      <li>escapeXml (Boolean) - Escape XML. Defaults to false</li>
+ *      <li>escapeCsv (Boolean) - Escape CSV. Defaults to false</li>
  * </ul>
  *
  * <!-- END SNIPPET: params -->
@@ -119,6 +124,10 @@
     protected String actualName;
     protected String name;
     protected String searchStack;
+    private boolean escapeHtml = false;
+    private boolean escapeJavaScript = false;
+    private boolean escapeXml = false;
+    private boolean escapeCsv = false;
 
     public Text(ValueStack stack) {
         super(stack);
@@ -134,6 +143,26 @@ public void setSearchValueStack(String searchStack) {
         this.searchStack = searchStack;
     }
 
+    @StrutsTagAttribute(description="Whether to escape HTML", type="Boolean", defaultValue="false")
+    public void setEscapeHtml(boolean escape) {
+        this.escapeHtml = escape;
+    }
+    
+    @StrutsTagAttribute(description="Whether to escape Javascript", type="Boolean", defaultValue="false")
+    public void setEscapeJavaScript(boolean escapeJavaScript) {
+        this.escapeJavaScript = escapeJavaScript;
+    }
+
+    @StrutsTagAttribute(description="Whether to escape XML", type="Boolean", defaultValue="false")
+    public void setEscapeXml(boolean escapeXml) {
+        this.escapeXml = escapeXml;
+    }
+
+    @StrutsTagAttribute(description="Whether to escape CSV (useful to escape a value for
a column)", type="Boolean", defaultValue="false")
+    public void setEscapeCsv(boolean escapeCsv) {
+        this.escapeCsv = escapeCsv;
+    }
+
     public boolean usesBody() {
         // overriding this to true such that EVAL_BODY_BUFFERED is return and
         // bodyContent will be valid hence, text between start & end tag will
@@ -161,7 +190,7 @@ public boolean end(Writer writer, String body) {
         if (msg != null) {
             try {
                 if (getVar() == null) {
-                    writer.write(msg);
+                    writer.write(prepare(msg));
                 } else {
                     putInContext(msg);
                 }
@@ -184,4 +213,22 @@ public void addParameter(Object value) {
 
         values.add(value);
     }
+
+    private String prepare(String value) {
+        String result = value;
+        if (escapeHtml) {
+            result = StringEscapeUtils.escapeHtml4(result);
+        }
+        if (escapeJavaScript) {
+            result = StringEscapeUtils.escapeEcmaScript(result);
+        }
+        if (escapeXml) {
+            result = StringEscapeUtils.escapeXml(result);
+        }
+        if (escapeCsv) {
+            result = StringEscapeUtils.escapeCsv(result);
+        }
+
+        return result;
+    }
 }
diff --git a/core/src/main/java/org/apache/struts2/views/jsp/TextTag.java b/core/src/main/java/org/apache/struts2/views/jsp/TextTag.java
index 6407954fa..c0420dfad 100644
--- a/core/src/main/java/org/apache/struts2/views/jsp/TextTag.java
+++ b/core/src/main/java/org/apache/struts2/views/jsp/TextTag.java
@@ -35,6 +35,10 @@
 
     protected String name;
     protected String searchValueStack;
+    private boolean escapeHtml = false;
+    private boolean escapeJavaScript = false;
+    private boolean escapeXml = false;
+    private boolean escapeCsv = false;
 
     public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse
res) {
         return new Text(stack);
@@ -46,6 +50,10 @@ protected void populateParams() {
         Text text = (Text) component;
         text.setName(name);
         text.setSearchValueStack(searchValueStack);
+        text.setEscapeHtml(escapeHtml);
+        text.setEscapeJavaScript(escapeJavaScript);
+        text.setEscapeXml(escapeXml);
+        text.setEscapeCsv(escapeCsv);
     }
 
     public void setName(String name) {
@@ -55,4 +63,21 @@ public void setName(String name) {
     public void setSearchValueStack(String searchStack) {
         this.searchValueStack = searchStack;
     }
+
+    public void setEscapeHtml(boolean escapeHtml) {
+        this.escapeHtml = escapeHtml;
+    }
+
+    public void setEscapeJavaScript(boolean escapeJavaScript) {
+        this.escapeJavaScript = escapeJavaScript;
+    }
+    
+    public void setEscapeXml(boolean escapeXml) {
+        this.escapeXml = escapeXml;
+    }
+
+    public void setEscapeCsv(boolean escapeCsv) {
+        this.escapeCsv = escapeCsv;
+    }
+
 }
diff --git a/core/src/site/resources/tags/text.html b/core/src/site/resources/tags/text.html
index bd2e51115..f068caddb 100644
--- a/core/src/site/resources/tags/text.html
+++ b/core/src/site/resources/tags/text.html
@@ -34,6 +34,38 @@
 				<th align="left" valign="top"><h4>Description</h4></th>
 			</tr>
 				<tr>
+					<td align="left" valign="top">escapeCsv</td>
+					<td align="left" valign="top">false</td>
+					<td align="left" valign="top">false</td>
+					<td align="left" valign="top">false</td>
+					<td align="left" valign="top">Boolean</td>
+					<td align="left" valign="top">Whether to escape CSV (useful to escape a value
for a column)</td>
+				</tr>
+				<tr>
+					<td align="left" valign="top">escapeHtml</td>
+					<td align="left" valign="top">false</td>
+					<td align="left" valign="top">false</td>
+					<td align="left" valign="top">false</td>
+					<td align="left" valign="top">Boolean</td>
+					<td align="left" valign="top">Whether to escape HTML</td>
+				</tr>
+				<tr>
+					<td align="left" valign="top">escapeJavaScript</td>
+					<td align="left" valign="top">false</td>
+					<td align="left" valign="top">false</td>
+					<td align="left" valign="top">false</td>
+					<td align="left" valign="top">Boolean</td>
+					<td align="left" valign="top">Whether to escape Javascript</td>
+				</tr>
+				<tr>
+					<td align="left" valign="top">escapeXml</td>
+					<td align="left" valign="top">false</td>
+					<td align="left" valign="top">false</td>
+					<td align="left" valign="top">false</td>
+					<td align="left" valign="top">Boolean</td>
+					<td align="left" valign="top">Whether to escape XML</td>
+				</tr>
+				<tr>
 					<td align="left" valign="top">name</td>
 					<td align="left" valign="top"><strong>true</strong></td>
 					<td align="left" valign="top"></td>
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/TextTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/TextTagTest.java
index dae0d532a..856b9335b 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/TextTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/TextTagTest.java
@@ -305,6 +305,46 @@ public void testPutId() throws Exception {
         assertEquals("No foo here", stack.findString("myId")); // is in stack now
     }
 
+    public void testEscapeHtml() throws Exception {
+        final String key = "foo.escape.html";
+        final String value = "1 &lt; 2";
+        tag.setName(key);
+        tag.setEscapeHtml(true);
+        tag.doStartTag();
+        tag.doEndTag();
+        assertEquals(value, writer.toString());
+    }
+
+    public void testEscapeXml() throws Exception {
+        final String key = "foo.escape.xml";
+        final String value = "&lt;&gt;&apos;&quot;&amp;";
+        tag.setName(key);
+        tag.setEscapeXml(true);
+        tag.doStartTag();
+        tag.doEndTag();
+        assertEquals(value, writer.toString());
+    }
+
+    public void testEscapeJavaScript() throws Exception {
+        final String key = "foo.escape.javascript";
+        final String value = "\\t\\b\\n\\f\\r\\\"\\\'\\/\\\\";
+        tag.setName(key);
+        tag.setEscapeJavaScript(true);
+        tag.doStartTag();
+        tag.doEndTag();
+        assertEquals(value, writer.toString());
+    }
+
+    public void testEscapeCsv() throws Exception {
+        final String key = "foo.escape.csv";
+        final String value = "\"something,\"\",\"\"\"";
+        tag.setName(key);
+        tag.setEscapeCsv(true);
+        tag.doStartTag();
+        tag.doEndTag();
+        assertEquals(value, writer.toString());
+    }
+
     /**
      * todo remove ActionContext set after LocalizedTextUtil is fixed to not use ThreadLocal
      *
diff --git a/core/src/test/resources/org/apache/struts2/TestAction.properties b/core/src/test/resources/org/apache/struts2/TestAction.properties
index 1ecb4cdfc..cd2ce8914 100644
--- a/core/src/test/resources/org/apache/struts2/TestAction.properties
+++ b/core/src/test/resources/org/apache/struts2/TestAction.properties
@@ -21,4 +21,8 @@ expressionKey=Foo is ${foo}
 messageFormatKey=Params are {0} {1} {2}
 foo.bar.baz=This should start with foo
 bar.baz=No foo here
-some.image.from.properties=some.gif
\ No newline at end of file
+some.image.from.properties=some.gif
+foo.escape.html=1 < 2
+foo.escape.xml=<>''\"&
+foo.escape.javascript=\u0009\u0008\n\u000C\u000D\"''/\u005C
+foo.escape.csv=something,","


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


> HTML escaping on the text tag
> -----------------------------
>
>                 Key: WW-4888
>                 URL: https://issues.apache.org/jira/browse/WW-4888
>             Project: Struts 2
>          Issue Type: Improvement
>          Components: Core Tags
>    Affects Versions: 2.5.13
>            Reporter: Pierre-Yves Soblet
>             Fix For: 2.5.14
>
>         Attachments: text-vs-property.png
>
>
> Assuming an i18n bundle with the following entry:
> {code}
> sample.message=This is a dumb smiley <:‑|
> {code}
> The following tag produces a value that is properly escaped for HTML:
> {code}
> <s:property value="%{getText('sample.message')}"/>
> {code}
> However, the *text* tag does not escape the "<" character and cannot be safely used
in HTML:
> {code}
> <s:text name="sample.message"/>
> {code}
> The text tag documentation (http://struts.apache.org/tag-developers/text-tag.html) neither
states HTML escaping is performed nor warns it is not.
> In the FAQ, the "How to escape special chars in resource bundles" article (https://struts.apache.org/docs/how-to-escape-special-chars-in-resource-bundles.html)
describes how to escape special characters of the MessageFormat syntax but does not mention
HTML escaping.
> I assume HTML escaping on the text tag cannot be added now without breaking backward
compatibility, but maybe an "escapeHtml" attribute could be added (as with the property tag)?




--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Mime
View raw message