Escape single characters in SafeHtmlBuilder/SafeHtmlUtils (external issue 6222)
Review at http://gwt-code-reviews.appspot.com/1413802
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9979 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/safehtml/shared/SafeHtmlBuilder.java b/user/src/com/google/gwt/safehtml/shared/SafeHtmlBuilder.java
index b906d93..34b14de 100644
--- a/user/src/com/google/gwt/safehtml/shared/SafeHtmlBuilder.java
+++ b/user/src/com/google/gwt/safehtml/shared/SafeHtmlBuilder.java
@@ -80,9 +80,10 @@
*
* @param c the character whose string representation to append
* @return a reference to this object
+ * @see SafeHtmlUtils#htmlEscape(char)
*/
public SafeHtmlBuilder append(char c) {
- sb.append(c);
+ sb.append(SafeHtmlUtils.htmlEscape(c));
return this;
}
@@ -147,6 +148,7 @@
*
* @param text the string to append
* @return a reference to this object
+ * @see SafeHtmlUtils#htmlEscape(String)
*/
public SafeHtmlBuilder appendEscaped(String text) {
sb.append(SafeHtmlUtils.htmlEscape(text));
@@ -156,10 +158,11 @@
/**
* Appends a string consisting of several newline-separated lines after
* HTML-escaping it. Newlines in the original string are converted to {@code
- * <br>}.
+ * <br>} tags.
*
* @param text the string to append
* @return a reference to this object
+ * @see SafeHtmlUtils#htmlEscape(String)
*/
public SafeHtmlBuilder appendEscapedLines(String text) {
sb.append(SafeHtmlUtils.htmlEscape(text).replaceAll("\n", "<br>"));
diff --git a/user/src/com/google/gwt/safehtml/shared/SafeHtmlUtils.java b/user/src/com/google/gwt/safehtml/shared/SafeHtmlUtils.java
index 48b202b..1ea9c38 100644
--- a/user/src/com/google/gwt/safehtml/shared/SafeHtmlUtils.java
+++ b/user/src/com/google/gwt/safehtml/shared/SafeHtmlUtils.java
@@ -37,7 +37,7 @@
private static final RegExp QUOT_RE = RegExp.compile("\"", "g");
/**
- * Returns a SafeHtml constructed from a safe string, i.e., without escaping
+ * Returns a {@link SafeHtml} constructed from a safe string, i.e., without escaping
* the string.
*
* <p>
@@ -85,7 +85,7 @@
* Returns a {@link SafeHtml} containing the escaped string.
*
* @param s the input String
- * @return a SafeHtml instance
+ * @return a {@link SafeHtml} instance
*/
public static SafeHtml fromString(String s) {
return new SafeHtmlString(htmlEscape(s));
@@ -94,24 +94,59 @@
/**
* Returns a {@link SafeHtml} constructed from a trusted string, i.e., without
* escaping the string. No checks are performed. The calling code should be
- * carefully reviewed to ensure the argument meets the SafeHtml contract.
+ * carefully reviewed to ensure the argument meets the {@link SafeHtml} contract.
*
* @param s the input String
- * @return a SafeHtml instance
+ * @return a {@link SafeHtml} instance
*/
public static SafeHtml fromTrustedString(String s) {
return new SafeHtmlString(s);
}
/**
+ * HTML-escapes a character. HTML meta characters
+ * will be escaped as follows:
+ *
+ * <pre>
+ * & - &amp;
+ * < - &lt;
+ * > - &gt;
+ * " - &quot;
+ * ' - &#39;
+ * </pre>
+ *
+ * @param c the character to be escaped
+ * @return a string containing either the input character
+ * or an equivalent HTML Entity Reference
+ */
+ public static String htmlEscape(char c) {
+ switch (c) {
+ case '&':
+ return "&";
+ case '<':
+ return "<";
+ case '>':
+ return ">";
+ case '"':
+ return """;
+ case '\'':
+ return "'";
+ default:
+ return "" + c;
+ }
+ }
+
+ /**
* HTML-escapes a string.
*
* Note: The following variants of this function were profiled on FF36,
* Chrome6, IE8:
- * #1) for each case, check indexOf, then use s.replace(regex, string)
- * #2) for each case, check indexOf, then use s.replaceAll()
- * #3) check if any metachar is present using a regex, then use #1
- * #4) for each case, use s.replace(regex, string)
+ * <ol>
+ * <li>For each case, check indexOf, then use s.replace(regex, string)</li>
+ * <li>For each case, check indexOf, then use s.replaceAll()</li>
+ * <li>Check if any metachar is present using a regex, then use #1</li>
+ * <li>For each case, use s.replace(regex, string)</li>
+ * </ol>
*
* #1 was found to be the fastest, and is used below.
*
diff --git a/user/test/com/google/gwt/safehtml/shared/GwtSafeHtmlBuilderTest.java b/user/test/com/google/gwt/safehtml/shared/GwtSafeHtmlBuilderTest.java
index 1704e51..354ee5d 100644
--- a/user/test/com/google/gwt/safehtml/shared/GwtSafeHtmlBuilderTest.java
+++ b/user/test/com/google/gwt/safehtml/shared/GwtSafeHtmlBuilderTest.java
@@ -70,6 +70,24 @@
}
}
+ public void testAppendChars() {
+ SafeHtmlBuilder b = new SafeHtmlBuilder();
+ b.append('a');
+ b.append('&');
+ b.append('b');
+ b.append('<');
+ b.append('c');
+ b.append('>');
+ b.append('d');
+ b.append('"');
+ b.append('e');
+ b.append('\'');
+ b.append('f');
+
+ SafeHtml html = b.toSafeHtml();
+ assertEquals("a&b<c>d"e'f", html.asString());
+ }
+
@Override
public String getModuleName() {
return "com.google.gwt.safehtml.SafeHtmlTestsModule";
diff --git a/user/test/com/google/gwt/safehtml/shared/GwtSafeHtmlUtilsTest.java b/user/test/com/google/gwt/safehtml/shared/GwtSafeHtmlUtilsTest.java
index fd1d648..e00d5fc 100644
--- a/user/test/com/google/gwt/safehtml/shared/GwtSafeHtmlUtilsTest.java
+++ b/user/test/com/google/gwt/safehtml/shared/GwtSafeHtmlUtilsTest.java
@@ -101,6 +101,26 @@
assertEquals(SafeHtmlUtils.htmlEscape(CONSTANT_HTML), h.asString());
}
+ public void testEscape_chars() {
+ String escaped = SafeHtmlUtils.htmlEscape('a');
+ assertEquals("a", escaped);
+
+ escaped = SafeHtmlUtils.htmlEscape('&');
+ assertEquals("&", escaped);
+
+ escaped = SafeHtmlUtils.htmlEscape('<');
+ assertEquals("<", escaped);
+
+ escaped = SafeHtmlUtils.htmlEscape('>');
+ assertEquals(">", escaped);
+
+ escaped = SafeHtmlUtils.htmlEscape('"');
+ assertEquals(""", escaped);
+
+ escaped = SafeHtmlUtils.htmlEscape('\'');
+ assertEquals("'", escaped);
+ }
+
@Override
public String getModuleName() {
return "com.google.gwt.safehtml.SafeHtmlTestsModule";