diff --git a/source/Ox/js/HTML.js b/source/Ox/js/HTML.js index 2bbead00..739de3af 100644 --- a/source/Ox/js/HTML.js +++ b/source/Ox/js/HTML.js @@ -22,7 +22,7 @@ { 'name': 'div', 'optional': ['style'], - 'validation': { + 'validate': { 'style': /^direction: rtl$/ } }, @@ -51,7 +51,7 @@ { 'name': 'a', 'required': ['href'], - 'validation': { + 'validate': { 'href': /^((https?:\/\/|\/|mailto:).*?)/ } }, @@ -60,7 +60,7 @@ 'name': 'iframe', 'optional': ['width', 'height'], 'required': ['src'], - 'validation': { + 'validate': { 'width': /^\d+$/, 'height': /^\d+$/, 'src': /^((https?:\/\/|\/|mailto:).*?)/ @@ -70,7 +70,7 @@ 'name': 'img', 'optional': ['width', 'height'], 'required': ['src'], - 'validation': { + 'validate': { 'width': /^\d+$/, 'height': /^\d+$/, 'src': /^((https?:\/\/|\/|mailto:).*?)/ @@ -531,24 +531,26 @@ '"<foo value="http://foo.com"></foo>"' @*/ Ox.sanitizeHTML = function(html, tags, globalAttributes) { + tags = tags || defaultTags; globalAttributes = globalAttributes || []; + var escaped = {}, level = 0, matches = [], - nonClosingTags = ['img', 'br'], - validAttributes = {}, requiredAttributes = {}, validation = {}, + selfClosingTags = ['img', 'br'], + validAttributes = {}, requiredAttributes = {}, validate = {}, validTags = tags.map(function(tag) { validAttributes[tag.name] = globalAttributes .concat(tag.required || []) .concat(tag.optional || []); requiredAttributes[tag.name] = tag.required || []; - validation[tag.name] = tag.validation || {}; + validate[tag.name] = tag.validate || {}; return tag.name; }); // html = Ox.clean(html); fixme: can this be a parameter? - if (validTags.indexOf('[]') > -1) { + if (Ox.contains(validTags, '[]')) { html = html.replace( /\[((\/|https?:\/\/|mailto:).+?) (.+?)\]/gi, '$3' @@ -559,35 +561,42 @@ } html = splitHTMLTags(html).map(function(string, i) { - var attributes, - attrs = {}, + + var attrs = {}, + attrMatch, attrRegexp = /([^=\ ]+)="([^"]+)"/g, + attrString, isClosing, isTag = i % 2, isValid = true, - name, - match, tag, + tagMatch, tagRegexp = /<(\/)?([^\ \/]+)(.*?)(\/)?>/g; if (isTag) { - tag = tagRegexp.exec(string); - if (tag) { - isClosing = !Ox.isUndefined(tag[1]); - name = tag[2]; - attributes = tag[3].trim(); - while(match = attrRegexp.exec(attributes)) { - if (validAttributes[name] && validAttributes[name].indexOf(match[1]) > -1) { - attrs[match[1]] = match[2]; + tagMatch = tagRegexp.exec(string); + if (tagMatch) { + isClosing = !Ox.isUndefined(tagMatch[1]); + tag = tagMatch[2]; + attrString = tagMatch[3].trim(); + while (attrMatch = attrRegexp.exec(attrString)) { + if ( + validAttributes[tag] + && Ox.contains(validAttributes[tag], attrMatch[1]) + ) { + attrs[attrMatch[1]] = attrMatch[2]; } } - if (!isClosing && nonClosingTags.indexOf(name) == -1) { + if (!isClosing && !Ox.contains(selfClosingTags, tag)) { level++; } - if (Ox.isEmpty(attrs) && attributes.length || validTags.indexOf(name) == -1) { + if ( + !Ox.contains(validTags, tag) + || (attrString.length && Ox.isEmpty(attrs)) + ) { isValid = false; - } else if(!isClosing && requiredAttributes[name]) { - requiredAttributes[name].forEach(function(attr) { + } else if (!isClosing && requiredAttributes[tag]) { + requiredAttributes[tag].forEach(function(attr) { if (Ox.isUndefined(attrs[attr])) { isValid = false; } @@ -595,10 +604,12 @@ } if (isValid && !Ox.isEmpty(attrs)) { Ox.forEach(attrs, function(value, key) { - if (!Ox.isUndefined(validation[name][key]) - && !validation[name][key].exec(value)) { + if ( + !Ox.isUndefined(validate[tag][key]) + && !validate[tag][key].exec(value) + ) { isValid = false; - return false; + return false; // break } }); } @@ -608,12 +619,12 @@ escaped[level] = !isValid; } if (isClosing) { - level --; + level--; } if (isValid) { return '<' + (isClosing ? '/' : '') - + name + + tag + (!isClosing && !Ox.isEmpty(attrs) ? ' ' + Ox.values(Ox.map(attrs, function(value, key) { return key + '="' + value + '"'; @@ -623,14 +634,18 @@ } } } + return Ox.encodeHTMLEntities(Ox.decodeHTMLEntities(string)); + }).join(''); + //FIXME: dont add links to urls inside of escaped tags html = Ox.addLinks(html, true); html = html.replace(/\n\n/g, '

'); // Close extra opening and remove extra closing tags. // Note: this converts ''' to "'" and '"' to '"' return Ox.normalizeHTML(html); + }; /*@