In my application, I need to send and receive HTML in string form. I would like everything to be safe, and because of this, I need to check if the dom elements in the tags are compatible with the string, and if the style declarations are valid and if there are no nested scripts. The first thing that comes to mind, of course, is the regular expression of the string, but it is tedious, it can be a mistake and, of course, inefficient. The second idea is to use something called XPath, but although I read some materials on the MDN website, I still don't know how to implement this code example:
const XPathResult = Components.interfaces.nsIDOMXPathResult;
const ALLOWED_TAGS = ['div', 'span', 'b', 'i', 'u', 'br', 'font', 'img'];
const ALLOWED_STYLES = ['font-weight', 'font-size', 'font-family', 'text-decoration', 'color', 'background-color'];
const ALLOWED_ATTRIBUTES = ['style', 'name'];
const XPATH_PART_TAGS = ALLOWED_TAGS.map(function (v) {
return "name() != '" + v + "' and name() != '" + v.toUpperCase() + "'";
}).join(' and ');
const XPATH_PART_ATTRS = ALLOWED_ATTRIBUTES.map(function (v) {
return "name() != '" + v + "' and name() != '" + v.toUpperCase() + "'";
}).join(' and ');
const XPATH_BAD_TAGS = "//*[(namespace-uri() != 'http://www.w3.org/1999/xhtml') or (" + XPATH_PART_TAGS + ")]";
const XPATH_BAD_ATTRIBUTES = "//@*[((namespace-uri() != 'http://www.w3.org/1999/xhtml') and (namespace-uri() != '')) or (" + XPATH_PART_ATTRS+ ")]";
const XPATH_STYLE = "//@*[name() = 'style']";
function isStyleSecure(styleValue) {
var styles = styleValue.split(';'),
style,
name, value,
i, l;
for (i = 0, l = styles.length; i < l; i++) {
style = styles[i].trim();
if (style === '') {
continue;
}
style = style.split(':', 2);
if (style.length !== 2) {
return false;
}
name = style[0].trim().toLowerCase();
value = style[1].trim();
if (ALLOWED_STYLES.indexOf(name) === -1) {
return false;
}
}
return true;
}
var MessageSecurityFilter = {
isSecure: function SecurityFilter_isSecure(element) {
var document = element.ownerDocument,
result,
attr;
result = document.evaluate('//*', element, null, XPathResult.ANY_TYPE, null);
result = document.evaluate(XPATH_BAD_TAGS, element, null, XPathResult.ANY_TYPE, null);
if (result.iterateNext()) {
return false;
}
result = document.evaluate(XPATH_BAD_ATTRIBUTES, element, null, XPathResult.ANY_TYPE, null);
if ((attr = result.iterateNext())) {
return false;
}
result = document.evaluate(XPATH_STYLE, element, null, XPathResult.ANY_TYPE, null);
while ((attr = result.iterateNext())) {
if (!isStyleSecure(attr.nodeValue)) {
return false;
}
}
return true;
}
};
, documentFragment, treeWalker .firstChild .. , , . ?
?