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

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 if (Device.isIE &&
Jennifer Messerly 2013/08/27 20:12:12 Would this logic work without the Device.isIE chec
blois 2013/08/27 21:08:32 Updated to do this- tested on IE11 and it wasn't w
110 _hiddenAnchor.hostname == '' &&
111 _hiddenAnchor.port == '' &&
112 _hiddenAnchor.protocol == ':') {
113 return true;
114 }
115 return _hiddenAnchor.hostname == _loc.hostname &&
116 _hiddenAnchor.port == _loc.port &&
117 _hiddenAnchor.protocol == _loc.protocol;
118 }
119 }
120
121
122 class _ThrowsNodeValidator implements NodeValidator {
123 final NodeValidator validator;
124
125 _ThrowsNodeValidator(this.validator) {}
126
127 bool allowsElement(Element element) {
128 if (!validator.allowsElement(element)) {
129 throw new ArgumentError(element.tagName);
130 }
131 return true;
132 }
133
134 bool allowsAttribute(Element element, String attributeName, String value) {
135 if (!validator.allowsAttribute(element, attributeName, value)) {
136 throw new ArgumentError('${element.tagName}[$attributeName="$value"]');
137 }
138 }
139 }
140
141
142 /**
143 * Standard tree sanitizer which validates a node tree against the provided
144 * validator and removes any nodes or attributes which are not allowed.
145 */
146 class _ValidatingTreeSanitizer implements NodeTreeSanitizer {
147 NodeValidator validator;
148 _ValidatingTreeSanitizer(this.validator) {}
149
150 void sanitizeTree(Node node) {
151 void walk(Node node) {
152 sanitizeNode(node);
153
154 var child = node.lastChild;
155 while (child != null) {
156 // Child may be removed during the walk.
157 var nextChild = child.previousNode;
158 walk(child);
159 child = nextChild;
160 }
161 }
162 walk(node);
163 }
164
165 void sanitizeNode(Node node) {
166 switch (node.nodeType) {
167 case Node.ELEMENT_NODE:
168 Element element = node;
169 var attrs = element.attributes;
170 if (!validator.allowsElement(element)) {
171 element.remove();
172 break;
173 }
174
175 var isAttr = attrs['is'];
176 if (isAttr != null) {
177 if (!validator.allowsAttribute(element, 'is', isAttr)) {
178 element.remove();
179 break;
180 }
181 }
182
183 // TODO(blois): Need to be able to get all attributes, irrespective of
184 // XMLNS.
185 var keys = attrs.keys.toList();
186 for (var i = attrs.length - 1; i >= 0; --i) {
187 var name = keys[i];
188 if (!validator.allowsAttribute(element, name, attrs[name])) {
189 attrs.remove(name);
190 }
191 }
192
193 if (element is TemplateElement) {
194 TemplateElement template = element;
195 sanitizeTree(template.content);
196 }
197 break;
198 case Node.COMMENT_NODE:
199 case Node.DOCUMENT_FRAGMENT_NODE:
200 case Node.TEXT_NODE:
201 case Node.CDATA_SECTION_NODE:
202 break;
203 default:
204 node.remove();
205 }
206 }
207 }
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