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

Side by Side Diff: sdk/lib/convert/html_escape.dart

Issue 1084473003: Make HtmlEscape escape '/' again in UNKNOWN mode. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 8 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/lib/convert/html_escape_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart.convert; 5 part of dart.convert;
6 6
7 // TODO(floitsch) - Document - Issue 13097 7 /**
8 * A `String` converter that converts characters to HTML entities.
9 *
10 * This is intended to sanitice text before inserting the text into an HTML
11 * document. Characters that are meaningful in HTML are converted to
12 * HTML entities (like `&` for `&`).
13 *
14 * The general converter escapes all characters that are meaningful in HTML
15 * attributes or normal element context. Elements with special content types
16 * (like CSS or JavaScript) may need a more specialized escaping that
17 * understands that content type.
18 *
19 * If the context where the text will be inserted is known in more detail,
20 * it's possible to omit escaping some characters (like quotes when not
21 * inside an attribute value).
22 *
23 * The escaped text should only be used inside quoted HTML attributes values
24 * or as text content of a normal element. Using the escaped text inside a
25 * tag, but not inside a quoted attribute value, is still dangerous.
26 */
8 const HtmlEscape HTML_ESCAPE = const HtmlEscape(); 27 const HtmlEscape HTML_ESCAPE = const HtmlEscape();
9 28
10 /** 29 /**
11 * HTML escape modes. 30 * HTML escape modes.
12 * 31 *
13 * Allows specifying a mode for HTML escaping that depend on the context 32 * Allows specifying a mode for HTML escaping that depend on the context
14 * where the escaped result is going to be used. 33 * where the escaped result is going to be used.
15 * The relevant contexts are: 34 * The relevant contexts are:
16 * 35 *
17 * * as text content of an HTML element. 36 * * as text content of an HTML element.
18 * * as value of a (single- or double-) quoted attribute value. 37 * * as value of a (single- or double-) quoted attribute value.
19 * 38 *
20 * All modes require escaping of `&` (ampersand) characters, and may 39 * All modes require escaping of `&` (ampersand) characters, and may
21 * enable escaping of more characters. 40 * enable escaping of more characters.
22 */ 41 */
23 class HtmlEscapeMode { 42 class HtmlEscapeMode {
24 final String _name; 43 final String _name;
25 /** Whether to escape '<' and '>'. */ 44 /** Whether to escape '<' and '>'. */
26 final bool escapeLtGt; 45 final bool escapeLtGt;
27 /** Whether to escape '"' (quote). */ 46 /** Whether to escape '"' (quote). */
28 final bool escapeQuot; 47 final bool escapeQuot;
29 /** Whether to escape "'" (apostrophe). */ 48 /** Whether to escape "'" (apostrophe). */
30 final bool escapeApos; 49 final bool escapeApos;
50 /**
51 * Whether to escape "/" (forward slash, solidus).
52 *
53 * Escaping a slash is recommended to avoid cross-site scripting attacks by
54 * [the Open Web Application Security Project](https://www.owasp.org/index.php /XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Befor e_Inserting_Untrusted_Data_into_HTML_Element_Content)
55 */
56 final bool escapeSlash;
31 57
32 /** 58 /**
33 * Default escaping mode which escape all characters. 59 * Default escaping mode which escape all characters.
34 * 60 *
35 * The result of such an escaping is usable both in element content and 61 * The result of such an escaping is usable both in element content and
36 * in any attribute value. 62 * in any attribute value.
37 * 63 *
38 * The escaping only works for elements with normal HTML content, 64 * The escaping only works for elements with normal HTML content,
39 * and not for, for example, script or style element content, 65 * and not for, for example, script or style element content,
40 * which require escapes matching their particular content syntax. 66 * which require escapes matching their particular content syntax.
41 */ 67 */
42 static const HtmlEscapeMode UNKNOWN = 68 static const HtmlEscapeMode UNKNOWN =
43 const HtmlEscapeMode._('unknown', true, true, true); 69 const HtmlEscapeMode._('unknown', true, true, true, true);
44 70
45 /** 71 /**
46 * Escaping mode for text going into double-quoted HTML attribute values. 72 * Escaping mode for text going into double-quoted HTML attribute values.
47 * 73 *
48 * The result should not be used as the content of an unquoted 74 * The result should not be used as the content of an unquoted
49 * or single-quoted attribute value. 75 * or single-quoted attribute value.
50 * 76 *
51 * Escapes only double quotes (`"`) but not single quotes (`'`). 77 * Escapes only double quotes (`"`) but not single quotes (`'`).
52 */ 78 */
53 static const HtmlEscapeMode ATTRIBUTE = 79 static const HtmlEscapeMode ATTRIBUTE =
54 const HtmlEscapeMode._('attribute', false, true, false); 80 const HtmlEscapeMode._('attribute', false, true, false, false);
55 81
56 /** 82 /**
57 * Escaping mode for text going into single-quoted HTML attribute values. 83 * Escaping mode for text going into single-quoted HTML attribute values.
58 * 84 *
59 * The result should not be used as the content of an unquoted 85 * The result should not be used as the content of an unquoted
60 * or double-quoted attribute value. 86 * or double-quoted attribute value.
61 * 87 *
62 * Escapes only single quotes (`'`) but not double quotes (`"`). 88 * Escapes only single quotes (`'`) but not double quotes (`"`).
63 */ 89 */
64 static const HtmlEscapeMode SQ_ATTRIBUTE = 90 static const HtmlEscapeMode SQ_ATTRIBUTE =
65 const HtmlEscapeMode._('attribute', false, false, true); 91 const HtmlEscapeMode._('attribute', false, false, true, false);
66 92
67 /** 93 /**
68 * Escaping mode for text going into HTML element content. 94 * Escaping mode for text going into HTML element content.
69 * 95 *
70 * The escaping only works for elements with normal HTML content, 96 * The escaping only works for elements with normal HTML content,
71 * and not for, for example, script or style element content, 97 * and not for, for example, script or style element content,
72 * which require escapes matching their particular content syntax. 98 * which require escapes matching their particular content syntax.
73 * 99 *
74 * Escapes `<` and `>` characters. 100 * Escapes `<` and `>` characters.
75 */ 101 */
76 static const HtmlEscapeMode ELEMENT = 102 static const HtmlEscapeMode ELEMENT =
77 const HtmlEscapeMode._('element', true, false, false); 103 const HtmlEscapeMode._('element', true, false, false, false);
78 104
79 const HtmlEscapeMode._( 105 const HtmlEscapeMode._(this._name,
80 this._name, this.escapeLtGt, this.escapeQuot, this.escapeApos); 106 this.escapeLtGt,
107 this.escapeQuot,
108 this.escapeApos,
109 this.escapeSlash);
81 110
82 /** 111 /**
83 * Create a custom escaping mode. 112 * Create a custom escaping mode.
84 * 113 *
85 * All modes escape `&`. 114 * All modes escape `&`.
86 * The mode can further be set to escape `<` and `>` ([escapeLtGt]), 115 * The mode can further be set to escape `<` and `>` ([escapeLtGt]),
87 * `"` ([escapeQuot]) and/or `'` ([escapeApos]). 116 * `"` ([escapeQuot]), `'` ([escapeApos]), and/or `/` ([escapeSlash]).
88 */ 117 */
89 const HtmlEscapeMode({String name: "custom", 118 const HtmlEscapeMode({String name: "custom",
90 this.escapeLtGt: false, 119 this.escapeLtGt: false,
91 this.escapeQuot: false, 120 this.escapeQuot: false,
92 this.escapeApos: false}) : _name = name; 121 this.escapeApos: false,
122 this.escapeSlash: false}) : _name = name;
93 123
94 String toString() => _name; 124 String toString() => _name;
95 } 125 }
96 126
97 /** 127 /**
98 * Converter which escapes characters with special meaning in HTML. 128 * Converter which escapes characters with special meaning in HTML.
99 * 129 *
100 * The converter finds characters that are siginificant in HTML source and 130 * The converter finds characters that are siginificant in HTML source and
101 * replaces them with corresponding HTML entities. 131 * replaces them with corresponding HTML entities.
102 * 132 *
103 * The characters that need escaping in HTML are: 133 * The characters that need escaping in HTML are:
104 * 134 *
105 * * `&` (ampersand) always need to be escaped. 135 * * `&` (ampersand) always need to be escaped.
106 * * `<` (less than) and '>' (greater than) when inside an element. 136 * * `<` (less than) and '>' (greater than) when inside an element.
107 * * `"` (quote) when inside a double-quoted attribute value. 137 * * `"` (quote) when inside a double-quoted attribute value.
108 * * `'` (apostrophe) when inside a single-quoted attribute value. 138 * * `'` (apostrophe) when inside a single-quoted attribute value.
109 * Apostrophe is escaped as `&#39;` instead of `&apos;` since 139 * Apostrophe is escaped as `&#39;` instead of `&apos;` since
110 * not all browsers understand `&apos;`. 140 * not all browsers understand `&apos;`.
141 * * `/` (slash) is recommended to be escaped because it may be used
142 * to terminate an element in some HTML dialects.
111 * 143 *
112 * Escaping `>` (greater than) isn't necessary, but the result is often 144 * Escaping `>` (greater than) isn't necessary, but the result is often
113 * found to be easier to read if greater-than is also escaped whenever 145 * found to be easier to read if greater-than is also escaped whenever
114 * less-than is. 146 * less-than is.
115 */ 147 */
116 class HtmlEscape extends Converter<String, String> { 148 class HtmlEscape extends Converter<String, String> {
117 149
118 /** The [HtmlEscapeMode] used by the converter. */ 150 /** The [HtmlEscapeMode] used by the converter. */
119 final HtmlEscapeMode mode; 151 final HtmlEscapeMode mode;
120 152
(...skipping 22 matching lines...) Expand all
143 StringBuffer result = null; 175 StringBuffer result = null;
144 for (int i = start; i < end; i++) { 176 for (int i = start; i < end; i++) {
145 var ch = text[i]; 177 var ch = text[i];
146 String replacement = null; 178 String replacement = null;
147 switch (ch) { 179 switch (ch) {
148 case '&': replacement = '&amp;'; break; 180 case '&': replacement = '&amp;'; break;
149 case '"': if (mode.escapeQuot) replacement = '&quot;'; break; 181 case '"': if (mode.escapeQuot) replacement = '&quot;'; break;
150 case "'": if (mode.escapeApos) replacement = '&#39;'; break; 182 case "'": if (mode.escapeApos) replacement = '&#39;'; break;
151 case '<': if (mode.escapeLtGt) replacement = '&lt;'; break; 183 case '<': if (mode.escapeLtGt) replacement = '&lt;'; break;
152 case '>': if (mode.escapeLtGt) replacement = '&gt;'; break; 184 case '>': if (mode.escapeLtGt) replacement = '&gt;'; break;
185 case '/': if (mode.escapeSlash) replacement = '&#46;'; break;
Siggi Cherem (dart-lang) 2015/04/15 22:09:52 should this be &#47; (or like it was before &#x2F;
Lasse Reichstein Nielsen 2015/04/16 06:42:21 Argh. Yes, ofcourse.
153 } 186 }
154 if (replacement != null) { 187 if (replacement != null) {
155 if (result == null) result = new StringBuffer(); 188 if (result == null) result = new StringBuffer();
156 if (i > start) result.write(text.substring(start, i)); 189 if (i > start) result.write(text.substring(start, i));
157 result.write(replacement); 190 result.write(replacement);
158 start = i + 1; 191 start = i + 1;
159 } 192 }
160 } 193 }
161 if (result == null) return null; 194 if (result == null) return null;
162 if (end > start) result.write(text.substring(start, end)); 195 if (end > start) result.write(text.substring(start, end));
(...skipping 19 matching lines...) Expand all
182 if(val == null) { 215 if(val == null) {
183 _sink.addSlice(chunk, start, end, isLast); 216 _sink.addSlice(chunk, start, end, isLast);
184 } else { 217 } else {
185 _sink.add(val); 218 _sink.add(val);
186 if (isLast) _sink.close(); 219 if (isLast) _sink.close();
187 } 220 }
188 } 221 }
189 222
190 void close() => _sink.close(); 223 void close() => _sink.close();
191 } 224 }
OLDNEW
« no previous file with comments | « no previous file | tests/lib/convert/html_escape_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698