From 94207f8fb6ee8fe26fe18657f6b5aca6def99605 Mon Sep 17 00:00:00 2001 From: Igor Minar Date: Fri, 7 Aug 2015 09:30:26 -0700 Subject: [PATCH] fix($sanitize): support void elements, fixups, remove dead code, typos Closes #12524 --- .../$sanitize/{ddns.ngdoc => noinert.ngdoc} | 6 +-- src/ngSanitize/sanitize.js | 49 ++++++------------- test/ngSanitize/sanitizeSpec.js | 28 +++-------- 3 files changed, 25 insertions(+), 58 deletions(-) rename docs/content/error/$sanitize/{ddns.ngdoc => noinert.ngdoc} (60%) diff --git a/docs/content/error/$sanitize/ddns.ngdoc b/docs/content/error/$sanitize/noinert.ngdoc similarity index 60% rename from docs/content/error/$sanitize/ddns.ngdoc rename to docs/content/error/$sanitize/noinert.ngdoc index a1f6f77390c8..0562016bede1 100644 --- a/docs/content/error/$sanitize/ddns.ngdoc +++ b/docs/content/error/$sanitize/noinert.ngdoc @@ -1,9 +1,9 @@ @ngdoc error -@name $sanitize:ddns -@fullName DOMDocument not supported +@name $sanitize:noinert +@fullName Can't create an inert html document @description -This error occurs when `$sanitize` sanitizer determines that `DOMDocument` api is not supported by the current browser. +This error occurs when `$sanitize` sanitizer determines that `document.implementation.createHTMLDocument ` api is not supported by the current browser. This api is necessary for safe parsing of HTML strings into DOM trees and without it the sanitizer can't sanitize the input. diff --git a/src/ngSanitize/sanitize.js b/src/ngSanitize/sanitize.js index d423fef72180..70797a1c9267 100644 --- a/src/ngSanitize/sanitize.js +++ b/src/ngSanitize/sanitize.js @@ -149,7 +149,7 @@ function sanitizeText(chars) { // Regular Expressions for parsing tags and attributes var SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g, // Match everything outside of normal chars and " (quote character) - NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; + NON_ALPHANUMERIC_REGEXP = /([^\#-~ |!])/g; // Good source of info about elements and attributes @@ -236,28 +236,24 @@ function toMap(str, lowercaseKeys) { return obj; } -var baseNode; +var inertBodyElement; (function(window) { var doc; - if (window.DOMDocument) { - doc = new window.DOMDocument(); - } else if (window.document && window.document.implementation) { + if (window.document && window.document.implementation) { doc = window.document.implementation.createHTMLDocument("inert"); - } else if (window.ActiveXObject) { - doc = new window.ActiveXObject("Msxml.DOMDocument"); } else { - throw $sanitizeMinErr('ddns', "DOMDocument not supported"); + throw $sanitizeMinErr('noinert', "Can't create an inert html document"); } var docElement = doc.documentElement || doc.getDocumentElement(); var bodyElements = docElement.getElementsByTagName('body'); // usually there should be only one body element in the document, but IE doesn't have any, so we need to create one if (bodyElements.length === 1) { - baseNode = bodyElements[0]; + inertBodyElement = bodyElements[0]; } else { var html = doc.createElement('html'); - baseNode = doc.createElement('body'); - html.appendChild(baseNode); + inertBodyElement = doc.createElement('body'); + html.appendChild(inertBodyElement); doc.appendChild(html); } })(window); @@ -280,8 +276,8 @@ function htmlParser(html, handler) { } else if (typeof html !== 'string') { html = '' + html; } - baseNode.innerHTML = html; - var node = baseNode.firstChild; + inertBodyElement.innerHTML = html; + var node = inertBodyElement.firstChild; while (node) { switch (node.nodeType) { case 1: // ELEMENT_NODE @@ -290,9 +286,6 @@ function htmlParser(html, handler) { case 3: // TEXT NODE handler.chars(node.textContent); break; - case 8: // COMMENT NODE - handler.comment(node.textContent); - break; } var nextNode; @@ -304,7 +297,7 @@ function htmlParser(html, handler) { if (!nextNode) { while (nextNode == null) { node = node.parentNode; - if (node === baseNode) break; + if (node === inertBodyElement) break; nextNode = node.nextSibling; if (node.nodeType == 1) { handler.end(node.nodeName.toLowerCase()); @@ -315,8 +308,8 @@ function htmlParser(html, handler) { node = nextNode; } - while (node = baseNode.firstChild) { - baseNode.removeChild(node); + while (node = inertBodyElement.firstChild) { + inertBodyElement.removeChild(node); } } @@ -329,20 +322,6 @@ function attrToMap(attrs) { return map; } -var hiddenPre=document.createElement("pre"); -/** - * decodes all entities into regular string - * @param value - * @returns {string} A string with decoded entities. - */ -function decodeEntities(value) { - if (!value) { return ''; } - - hiddenPre.innerHTML = value.replace(/'); diff --git a/test/ngSanitize/sanitizeSpec.js b/test/ngSanitize/sanitizeSpec.js index 068991e72282..0f25caa53229 100644 --- a/test/ngSanitize/sanitizeSpec.js +++ b/test/ngSanitize/sanitizeSpec.js @@ -50,9 +50,9 @@ describe('HTML', function() { }; }); - it('should parse comments', function() { + it('should not parse comments', function() { htmlParser('', handler); - expect(comment).toEqual('FOOBAR'); + expect(comment).not.toBeDefined(); }); it('should parse basic format', function() { @@ -66,18 +66,6 @@ describe('HTML', function() { toBe('<- text1 text2 <1 text1 text2 <{'); }); - it('should throw badparse if text content contains "<" followed by "/" without matching ">"', function() { - htmlParser('foo "', function() { - htmlParser('foo 10 < 100

', handler); @@ -103,8 +91,8 @@ describe('HTML', function() { }); it('should parse empty value attribute of node', function() { - htmlParser('', handler); - expect(start).toEqual({tag:'option', attrs:{selected:'', value:''}}); + htmlParser('abc', handler); + expect(start).toEqual({tag:'test-foo', attrs:{selected:'', value:''}}); expect(text).toEqual('abc'); }); }); @@ -165,7 +153,7 @@ describe('HTML', function() { }); it('should handle self closed elements', function() { - expectHTML('a
c').toEqual('a
c'); + expectHTML('a
c').toEqual('a
c'); }); it('should handle namespace', function() { @@ -192,7 +180,7 @@ describe('HTML', function() { it('should ignore back slash as escape', function() { expectHTML('xxx\\'). - toEqual('xxx\\'); + toEqual('xxx\\'); }); it('should ignore object attributes', function() { @@ -415,11 +403,11 @@ describe('HTML', function() { inject(function() { $$sanitizeUri.andReturn('someUri'); - expectHTML('').toEqual(''); + expectHTML('').toEqual(''); expect($$sanitizeUri).toHaveBeenCalledWith('someUri', true); $$sanitizeUri.andReturn('unsafe:someUri'); - expectHTML('').toEqual(''); + expectHTML('').toEqual(''); }); });