Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1417)

Unified Diff: tool/input_sdk/lib/convert/html_escape.dart

Issue 1965563003: Update dart:convert and dart:core Uri. (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tool/input_sdk/lib/convert/html_escape.dart
diff --git a/tool/input_sdk/lib/convert/html_escape.dart b/tool/input_sdk/lib/convert/html_escape.dart
index 512d9c31f2bf4da229779f9a6dba2d21d6869946..7efe317c7bf93f56ebf3d6b4af9744089bd365d3 100644
--- a/tool/input_sdk/lib/convert/html_escape.dart
+++ b/tool/input_sdk/lib/convert/html_escape.dart
@@ -4,42 +4,167 @@
part of dart.convert;
-// TODO(floitsch) - Document - Issue 13097
+/**
+ * A `String` converter that converts characters to HTML entities.
+ *
+ * This is intended to sanitice text before inserting the text into an HTML
+ * document. Characters that are meaningful in HTML are converted to
+ * HTML entities (like `&` for `&`).
+ *
+ * The general converter escapes all characters that are meaningful in HTML
+ * attributes or normal element context. Elements with special content types
+ * (like CSS or JavaScript) may need a more specialized escaping that
+ * understands that content type.
+ *
+ * If the context where the text will be inserted is known in more detail,
+ * it's possible to omit escaping some characters (like quotes when not
+ * inside an attribute value).
+ *
+ * The escaped text should only be used inside quoted HTML attributes values
+ * or as text content of a normal element. Using the escaped text inside a
+ * tag, but not inside a quoted attribute value, is still dangerous.
+ */
const HtmlEscape HTML_ESCAPE = const HtmlEscape();
+/**
+ * HTML escape modes.
+ *
+ * Allows specifying a mode for HTML escaping that depend on the context
+ * where the escaped result is going to be used.
+ * The relevant contexts are:
+ *
+ * * as text content of an HTML element.
+ * * as value of a (single- or double-) quoted attribute value.
+ *
+ * All modes require escaping of `&` (ampersand) characters, and may
+ * enable escaping of more characters.
+ *
+ * Custom escape modes can be created using the [HtmlEscapeMode.HtmlEscapeMode]
+ * constructor.
+ */
class HtmlEscapeMode {
final String _name;
+ /** Whether to escape '<' and '>'. */
final bool escapeLtGt;
+ /** Whether to escape '"' (quote). */
final bool escapeQuot;
+ /** Whether to escape "'" (apostrophe). */
final bool escapeApos;
+ /**
+ * Whether to escape "/" (forward slash, solidus).
+ *
+ * Escaping a slash is recommended to avoid cross-site scripting attacks by
+ * [the Open Web Application Security Project](https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content)
+ */
final bool escapeSlash;
- // TODO(floitsch) - Document - Issue 13097
+ /**
+ * Default escaping mode which escape all characters.
+ *
+ * The result of such an escaping is usable both in element content and
+ * in any attribute value.
+ *
+ * The escaping only works for elements with normal HTML content,
+ * and not for, for example, script or style element content,
+ * which require escapes matching their particular content syntax.
+ */
static const HtmlEscapeMode UNKNOWN =
- const HtmlEscapeMode._('unknown', true, true, true, true);
-
- // TODO(floitsch) - Document - Issue 13097
+ const HtmlEscapeMode._('unknown', true, true, true, true);
+
+ /**
+ * Escaping mode for text going into double-quoted HTML attribute values.
+ *
+ * The result should not be used as the content of an unquoted
+ * or single-quoted attribute value.
+ *
+ * Escapes double quotes (`"`) but not single quotes (`'`),
+ * and escapes `<` and `>` characters because they are not allowed
+ * in strict XHTML attributes
+ */
static const HtmlEscapeMode ATTRIBUTE =
- const HtmlEscapeMode._('attribute', false, true, false, false);
-
- // TODO(floitsch) - Document - Issue 13097
+ const HtmlEscapeMode._('attribute', true, true, false, false);
+
+ /**
+ * Escaping mode for text going into single-quoted HTML attribute values.
+ *
+ * The result should not be used as the content of an unquoted
+ * or double-quoted attribute value.
+ *
+ * Escapes single quotes (`'`) but not double quotes (`"`),
+ * and escapes `<` and `>` characters because they are not allowed
+ * in strict XHTML attributes
+ */
+ static const HtmlEscapeMode SQ_ATTRIBUTE =
+ const HtmlEscapeMode._('attribute', true, false, true, false);
+
+ /**
+ * Escaping mode for text going into HTML element content.
+ *
+ * The escaping only works for elements with normal HTML content,
+ * and not for, for example, script or style element content,
+ * which require escapes matching their particular content syntax.
+ *
+ * Escapes `<` and `>` characters.
+ */
static const HtmlEscapeMode ELEMENT =
- const HtmlEscapeMode._('element', true, false, false, true);
-
- // TODO(floitsch) - Document - Issue 13097
- const HtmlEscapeMode._(this._name, this.escapeLtGt, this.escapeQuot,
- this.escapeApos, this.escapeSlash);
+ const HtmlEscapeMode._('element', true, false, false, false);
+
+ const HtmlEscapeMode._(this._name,
+ this.escapeLtGt,
+ this.escapeQuot,
+ this.escapeApos,
+ this.escapeSlash);
+
+ /**
+ * Create a custom escaping mode.
+ *
+ * All modes escape `&`.
+ * The mode can further be set to escape `<` and `>` ([escapeLtGt]),
+ * `"` ([escapeQuot]), `'` ([escapeApos]), and/or `/` ([escapeSlash]).
+ */
+ const HtmlEscapeMode({String name: "custom",
+ this.escapeLtGt: false,
+ this.escapeQuot: false,
+ this.escapeApos: false,
+ this.escapeSlash: false}) : _name = name;
String toString() => _name;
}
- // TODO(floitsch) - Document - Issue 13097
-class HtmlEscape extends Converter<String, String> {
-
- // TODO(floitsch) - Document - Issue 13097
+/**
+ * Converter which escapes characters with special meaning in HTML.
+ *
+ * The converter finds characters that are siginificant in HTML source and
+ * replaces them with corresponding HTML entities.
+ *
+ * The characters that need escaping in HTML are:
+ *
+ * * `&` (ampersand) always need to be escaped.
+ * * `<` (less than) and '>' (greater than) when inside an element.
+ * * `"` (quote) when inside a double-quoted attribute value.
+ * * `'` (apostrophe) when inside a single-quoted attribute value.
+ * Apostrophe is escaped as `&#39;` instead of `&apos;` since
+ * not all browsers understand `&apos;`.
+ * * `/` (slash) is recommended to be escaped because it may be used
+ * to terminate an element in some HTML dialects.
+ *
+ * Escaping `>` (greater than) isn't necessary, but the result is often
+ * found to be easier to read if greater-than is also escaped whenever
+ * less-than is.
+ */
+class HtmlEscape extends ChunkedConverter<String, String, String, String> {
+
+ /** The [HtmlEscapeMode] used by the converter. */
final HtmlEscapeMode mode;
- // TODO(floitsch) - Document - Issue 13097
+ /**
+ * Create converter that escapes HTML characters.
+ *
+ * If [mode] is provided as either [HtmlEscapeMode.ATTRIBUTE] or
+ * [HtmlEscapeMode.ELEMENT], only the corresponding subset of HTML
+ * characters are escaped.
+ * The default is to escape all HTML characters.
+ */
const HtmlEscape([this.mode = HtmlEscapeMode.UNKNOWN]);
String convert(String text) {
@@ -47,29 +172,35 @@ class HtmlEscape extends Converter<String, String> {
return val == null ? text : val;
}
+ /**
+ * Converts the substring of text from start to end.
+ *
+ * Returns `null` if no changes were necessary, otherwise returns
+ * the converted string.
+ */
String _convert(String text, int start, int end) {
StringBuffer result = null;
for (int i = start; i < end; i++) {
var ch = text[i];
- String replace = null;
+ String replacement = null;
switch (ch) {
- case '&': replace = '&amp;'; break;
- case '\u00A0'/*NO-BREAK SPACE*/: replace = '&nbsp;'; break;
- case '"': if (mode.escapeQuot) replace = '&quot;'; break;
- case "'": if (mode.escapeApos) replace = '&#x27;'; break;
- case '<': if (mode.escapeLtGt) replace = '&lt;'; break;
- case '>': if (mode.escapeLtGt) replace = '&gt;'; break;
- case '/': if (mode.escapeSlash) replace = '&#x2F;'; break;
+ case '&': replacement = '&amp;'; break;
+ case '"': if (mode.escapeQuot) replacement = '&quot;'; break;
+ case "'": if (mode.escapeApos) replacement = '&#39;'; break;
+ case '<': if (mode.escapeLtGt) replacement = '&lt;'; break;
+ case '>': if (mode.escapeLtGt) replacement = '&gt;'; break;
+ case '/': if (mode.escapeSlash) replacement = '&#47;'; break;
}
- if (replace != null) {
- if (result == null) result = new StringBuffer(text.substring(start, i));
- result.write(replace);
- } else if (result != null) {
- result.write(ch);
+ if (replacement != null) {
+ if (result == null) result = new StringBuffer();
+ if (i > start) result.write(text.substring(start, i));
+ result.write(replacement);
+ start = i + 1;
}
}
-
- return result != null ? result.toString() : null;
+ if (result == null) return null;
+ if (end > start) result.write(text.substring(start, end));
+ return result.toString();
}
StringConversionSink startChunkedConversion(Sink<String> sink) {
@@ -96,5 +227,5 @@ class _HtmlEscapeSink extends StringConversionSinkBase {
}
}
- void close() => _sink.close();
+ void close() { _sink.close(); }
}

Powered by Google App Engine
This is Rietveld 408576698