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

Unified Diff: tools/dom/src/Validators.dart

Issue 16374007: First rev of Safe DOM (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 4 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
« no previous file with comments | « tools/dom/src/NodeValidatorBuilder.dart ('k') | tools/dom/src/shared_SVGFactoryProviders.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/dom/src/Validators.dart
diff --git a/tools/dom/src/Validators.dart b/tools/dom/src/Validators.dart
new file mode 100644
index 0000000000000000000000000000000000000000..76e0fb4a9e12d587df788a2146ea1a044bc59a28
--- /dev/null
+++ b/tools/dom/src/Validators.dart
@@ -0,0 +1,200 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart.dom.html;
+
+
+/**
+ * Interface used to validate that only accepted elements and attributes are
+ * allowed while parsing HTML strings into DOM nodes.
+ *
+ * In general, customization of validation behavior should be done via the
+ * [NodeValidatorBuilder] class to mitigate the chances of incorrectly
+ * implementing validation rules.
+ */
+abstract class NodeValidator {
+
+ /**
+ * Construct a default NodeValidator which only accepts whitelisted HTML5
+ * elements and attributes.
+ *
+ * If a uriPolicy is not specified then the default uriPolicy will be used.
+ */
+ factory NodeValidator({UriPolicy uriPolicy}) =>
+ new _Html5NodeValidator(uriPolicy: uriPolicy);
+
+ factory NodeValidator.throws(NodeValidator base) =>
+ new _ThrowsNodeValidator(base);
+
+ /**
+ * Returns true if the tagName is an accepted type.
+ */
+ bool allowsElement(Element element);
+
+ /**
+ * Returns true if the attribute is allowed.
+ *
+ * The attributeName parameter will always be in lowercase.
+ *
+ * See [allowsElement] for format of tagName.
+ */
+ bool allowsAttribute(Element element, String attributeName, String value);
+}
+
+/**
+ * Performs sanitization of a node tree after construction to ensure that it
+ * does not contain any disallowed elements or attributes.
+ *
+ * In general custom implementations of this class should not be necessary and
+ * all validation customization should be done in custom NodeValidators, but
+ * custom implementations of this class can be created to perform more complex
+ * tree sanitization.
+ */
+abstract class NodeTreeSanitizer {
+
+ /**
+ * Constructs a default tree sanitizer which will remove all elements and
+ * attributes which are not allowed by the provided validator.
+ */
+ factory NodeTreeSanitizer(NodeValidator validator) =>
+ new _ValidatingTreeSanitizer(validator);
+
+ /**
+ * Called with the root of the tree which is to be sanitized.
+ *
+ * This method needs to walk the entire tree and either remove elements and
+ * attributes which are not recognized as safe or throw an exception which
+ * will mark the entire tree as unsafe.
+ */
+ void sanitizeTree(Node node);
+}
+
+/**
+ * Defines the policy for what types of uris are allowed for particular
+ * attribute values.
+ *
+ * This can be used to provide custom rules such as allowing all http:// URIs
+ * for image attributes but only same-origin URIs for anchor tags.
+ */
+abstract class UriPolicy {
+ /**
+ * Constructs the default UriPolicy which is to only allow Uris to the same
+ * origin as the application was launched from.
+ *
+ * This will block all ftp: mailto: URIs. It will also block accessing
+ * https://example.com if the app is running from http://example.com.
+ */
+ factory UriPolicy() => new _SameOriginUriPolicy();
+
+ /**
+ * Checks if the uri is allowed on the specified attribute.
+ *
+ * The uri provided may or may not be a relative path.
+ */
+ bool allowsUri(String uri);
+}
+
+/**
+ * Allows URIs to the same origin as the current application was loaded from
+ * (such as https://example.com:80).
+ */
+class _SameOriginUriPolicy implements UriPolicy {
+ final AnchorElement _hiddenAnchor = new AnchorElement();
+ final Location _loc = window.location;
+
+ bool allowsUri(String uri) {
+ _hiddenAnchor.href = uri;
+ return _hiddenAnchor.hostname == _loc.hostname &&
+ _hiddenAnchor.port == _loc.port &&
+ _hiddenAnchor.protocol == _loc.protocol;
+ }
+}
+
+
+class _ThrowsNodeValidator implements NodeValidator {
+ final NodeValidator validator;
+
+ _ThrowsNodeValidator(this.validator) {}
+
+ bool allowsElement(Element element) {
+ if (!validator.allowsElement(element)) {
+ throw new ArgumentError(element.tagName);
+ }
+ return true;
+ }
+
+ bool allowsAttribute(Element element, String attributeName, String value) {
+ if (!validator.allowsAttribute(element, attributeName, value)) {
+ throw new ArgumentError('${element.tagName}[$attributeName="$value"]');
+ }
+ }
+}
+
+
+/**
+ * Standard tree sanitizer which validates a node tree against the provided
+ * validator and removes any nodes or attributes which are not allowed.
+ */
+class _ValidatingTreeSanitizer implements NodeTreeSanitizer {
+ NodeValidator validator;
+ _ValidatingTreeSanitizer(this.validator) {}
+
+ void sanitizeTree(Node node) {
+ void walk(Node node) {
+ sanitizeNode(node);
+
+ var child = node.lastChild;
+ while (child != null) {
+ // Child may be removed during the walk.
+ var nextChild = child.previousNode;
+ walk(child);
+ child = nextChild;
+ }
+ }
+ walk(node);
+ }
+
+ void sanitizeNode(Node node) {
+ switch (node.nodeType) {
+ case Node.ELEMENT_NODE:
+ Element element = node;
+ var attrs = element.attributes;
+ if (!validator.allowsElement(element)) {
+ element.remove();
+ break;
+ }
+
+ var isAttr = attrs['is'];
+ if (isAttr != null) {
+ if (!validator.allowsAttribute(element, 'is', isAttr)) {
+ element.remove();
+ break;
+ }
+ }
+
+ // TODO(blois): Need to be able to get all attributes, irrespective of
+ // XMLNS.
+ var keys = attrs.keys.toList();
+ for (var i = attrs.length - 1; i >= 0; --i) {
+ var name = keys[i];
+ if (!validator.allowsAttribute(element, name, attrs[name])) {
+ attrs.remove(name);
+ }
+ }
+
+ if (element is TemplateElement) {
+ TemplateElement template = element;
+ sanitizeTree(template.content);
+ }
+ break;
+ case Node.COMMENT_NODE:
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ case Node.TEXT_NODE:
+ case Node.CDATA_SECTION_NODE:
+ break;
+ default:
+ node.remove();
+ }
+ }
+}
« 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