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

Side by Side Diff: tools/dom/src/Validators.dart

Issue 23525003: Safe DOM w/ fixes (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 3 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 | « tools/dom/src/NodeValidatorBuilder.dart ('k') | tools/dom/src/shared_SVGFactoryProviders.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of dart.dom.html;
6
7
8 /**
9 * Interface used to validate that only accepted elements and attributes are
10 * allowed while parsing HTML strings into DOM nodes.
11 *
12 * In general, customization of validation behavior should be done via the
13 * [NodeValidatorBuilder] class to mitigate the chances of incorrectly
14 * implementing validation rules.
15 */
16 abstract class NodeValidator {
17
18 /**
19 * Construct a default NodeValidator which only accepts whitelisted HTML5
20 * elements and attributes.
21 *
22 * If a uriPolicy is not specified then the default uriPolicy will be used.
23 */
24 factory NodeValidator({UriPolicy uriPolicy}) =>
25 new _Html5NodeValidator(uriPolicy: uriPolicy);
26
27 factory NodeValidator.throws(NodeValidator base) =>
28 new _ThrowsNodeValidator(base);
29
30 /**
31 * Returns true if the tagName is an accepted type.
32 */
33 bool allowsElement(Element element);
34
35 /**
36 * Returns true if the attribute is allowed.
37 *
38 * The attributeName parameter will always be in lowercase.
39 *
40 * See [allowsElement] for format of tagName.
41 */
42 bool allowsAttribute(Element element, String attributeName, String value);
43 }
44
45 /**
46 * Performs sanitization of a node tree after construction to ensure that it
47 * does not contain any disallowed elements or attributes.
48 *
49 * In general custom implementations of this class should not be necessary and
50 * all validation customization should be done in custom NodeValidators, but
51 * custom implementations of this class can be created to perform more complex
52 * tree sanitization.
53 */
54 abstract class NodeTreeSanitizer {
55
56 /**
57 * Constructs a default tree sanitizer which will remove all elements and
58 * attributes which are not allowed by the provided validator.
59 */
60 factory NodeTreeSanitizer(NodeValidator validator) =>
61 new _ValidatingTreeSanitizer(validator);
62
63 /**
64 * Called with the root of the tree which is to be sanitized.
65 *
66 * This method needs to walk the entire tree and either remove elements and
67 * attributes which are not recognized as safe or throw an exception which
68 * will mark the entire tree as unsafe.
69 */
70 void sanitizeTree(Node node);
71 }
72
73 /**
74 * Defines the policy for what types of uris are allowed for particular
75 * attribute values.
76 *
77 * This can be used to provide custom rules such as allowing all http:// URIs
78 * for image attributes but only same-origin URIs for anchor tags.
79 */
80 abstract class UriPolicy {
81 /**
82 * Constructs the default UriPolicy which is to only allow Uris to the same
83 * origin as the application was launched from.
84 *
85 * This will block all ftp: mailto: URIs. It will also block accessing
86 * https://example.com if the app is running from http://example.com.
87 */
88 factory UriPolicy() => new _SameOriginUriPolicy();
89
90 /**
91 * Checks if the uri is allowed on the specified attribute.
92 *
93 * The uri provided may or may not be a relative path.
94 */
95 bool allowsUri(String uri);
96 }
97
98 /**
99 * Allows URIs to the same origin as the current application was loaded from
100 * (such as https://example.com:80).
101 */
102 class _SameOriginUriPolicy implements UriPolicy {
103 final AnchorElement _hiddenAnchor = new AnchorElement();
104 final Location _loc = window.location;
105
106 bool allowsUri(String uri) {
107 _hiddenAnchor.href = uri;
108 // IE leaves an empty hostname for same-origin URIs.
109 return (_hiddenAnchor.hostname == _loc.hostname &&
110 _hiddenAnchor.port == _loc.port &&
111 _hiddenAnchor.protocol == _loc.protocol) ||
112 (_hiddenAnchor.hostname == '' &&
113 _hiddenAnchor.port == '' &&
114 _hiddenAnchor.protocol == ':');
115 }
116 }
117
118
119 class _ThrowsNodeValidator implements NodeValidator {
120 final NodeValidator validator;
121
122 _ThrowsNodeValidator(this.validator) {}
123
124 bool allowsElement(Element element) {
125 if (!validator.allowsElement(element)) {
126 throw new ArgumentError(element.tagName);
127 }
128 return true;
129 }
130
131 bool allowsAttribute(Element element, String attributeName, String value) {
132 if (!validator.allowsAttribute(element, attributeName, value)) {
133 throw new ArgumentError('${element.tagName}[$attributeName="$value"]');
134 }
135 }
136 }
137
138
139 /**
140 * Standard tree sanitizer which validates a node tree against the provided
141 * validator and removes any nodes or attributes which are not allowed.
142 */
143 class _ValidatingTreeSanitizer implements NodeTreeSanitizer {
144 NodeValidator validator;
145 _ValidatingTreeSanitizer(this.validator) {}
146
147 void sanitizeTree(Node node) {
148 void walk(Node node) {
149 sanitizeNode(node);
150
151 var child = node.lastChild;
152 while (child != null) {
153 // Child may be removed during the walk.
154 var nextChild = child.previousNode;
155 walk(child);
156 child = nextChild;
157 }
158 }
159 walk(node);
160 }
161
162 void sanitizeNode(Node node) {
163 switch (node.nodeType) {
164 case Node.ELEMENT_NODE:
165 Element element = node;
166 var attrs = element.attributes;
167 if (!validator.allowsElement(element)) {
168 element.remove();
169 break;
170 }
171
172 var isAttr = attrs['is'];
173 if (isAttr != null) {
174 if (!validator.allowsAttribute(element, 'is', isAttr)) {
175 element.remove();
176 break;
177 }
178 }
179
180 // TODO(blois): Need to be able to get all attributes, irrespective of
181 // XMLNS.
182 var keys = attrs.keys.toList();
183 for (var i = attrs.length - 1; i >= 0; --i) {
184 var name = keys[i];
185 if (!validator.allowsAttribute(element, name, attrs[name])) {
186 attrs.remove(name);
187 }
188 }
189
190 if (element is TemplateElement) {
191 TemplateElement template = element;
192 sanitizeTree(template.content);
193 }
194 break;
195 case Node.COMMENT_NODE:
196 case Node.DOCUMENT_FRAGMENT_NODE:
197 case Node.TEXT_NODE:
198 case Node.CDATA_SECTION_NODE:
199 break;
200 default:
201 node.remove();
202 }
203 }
204 }
OLDNEW
« no previous file with comments | « tools/dom/src/NodeValidatorBuilder.dart ('k') | tools/dom/src/shared_SVGFactoryProviders.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698