AjxDefangFilter.js
Summary
No overview generated for 'AjxDefangFilter.js'
AjxDefangFilter._inited = false;
function AjxDefangFilter(neuterImages) {
this.mNeuterImages = neuterImages;
if (!AjxDefangFilter._inited) {
AjxDefangFilter._inited = true;
AjxDefangFilter._init();
}
}
AjxDefangFilter.ENABLE_INPUT_TAGS = true;
AjxDefangFilter.ENABLE_TABLE_TAGS = true;
AjxDefangFilter.ENABLE_PHRASE_TAGS = true;
AjxDefangFilter.ENABLE_LIST_TAGS = true;
AjxDefangFilter.ENABLE_FONT_STYLE_TAGS = true;
AjxDefangFilter.NULL = new Object();
AjxDefangFilter.AV_JS_ENTITY = new RegExp().compile("&\\{[^}]*\\}");
AjxDefangFilter.AV_JS_COLON = new RegExp().compile("script:","gi");
AjxDefangFilter.AV_SCRIPT_TAG = new RegExp().compile("</?script/?>","i");
AjxDefangFilter.TAG_REGEX = /<([a-zA-Z0-9]+)[\s]*[^>]*>/gi;
AjxDefangFilter.ATTR_REGEX = /([a-zA-Z]+)\s*=\s*([^\s^\"^\']*) | ([a-zA-Z]+)\s*=\s*[\"\']([^\"^\']*)[\"\']/gi;
AjxDefangFilter.ID_REGEX = /id\s*=\s*[\"\']?([^\s^\"^\']*)[\"\']?/i;
AjxDefangFilter.SRC_REGEX = /src\s*=\s*[\"\']?([^\s^\"^\']*)[\"\']?/i;
AjxDefangFilter.TARGET_REGEX = /target\s*=\s*[\"\']?([^\s^\"^\']*)[\"\']?/i;
// regex for URL. TODO: beef this up
AjxDefangFilter.ABSOLUTE_URL = new RegExp("^(https?:
AjxDefangFilter.mAttrSetCache = new Object();
AjxDefangFilter.mAcceptedElements = new Object();
AjxDefangFilter.mRemovedElements = new Object();
AjxDefangFilter.CORE = "id,class,title,";
AjxDefangFilter.LANG = "dir,lang,xml:lang,language";
AjxDefangFilter.CORE_LANG = AjxDefangFilter.CORE+AjxDefangFilter.LANG;
AjxDefangFilter.KBD = "accesskey,tabindex,";
AjxDefangFilter._init = function () {
var CORE = AjxDefangFilter.CORE;
var LANG = AjxDefangFilter.LANG;
var CORE_LANG = AjxDefangFilter.CORE_LANG;
var KBD = AjxDefangFilter.KBD;
AjxDefangFilter.acceptElement("a", CORE+KBD+",charset,coords,href,hreflang,name,rel,rev,shape,target,type");
AjxDefangFilter.acceptElement("address", CORE_LANG);
AjxDefangFilter.acceptElement("bdo", CORE_LANG);
AjxDefangFilter.acceptElement("blockquote", CORE_LANG+"cite");
AjxDefangFilter.acceptElement("body", CORE_LANG+"alink,background,bgcolor,link,text,vlink");
AjxDefangFilter.acceptElement("br", CORE);
AjxDefangFilter.acceptElement("center", CORE_LANG);
AjxDefangFilter.acceptElement("del", CORE_LANG+"cite,datetime");
AjxDefangFilter.acceptElement("div", CORE_LANG+"align");
AjxDefangFilter.acceptElement("head", LANG);
AjxDefangFilter.acceptElement("h1", CORE_LANG+"align");
AjxDefangFilter.acceptElement("h2", CORE_LANG+"align");
AjxDefangFilter.acceptElement("h3", CORE_LANG+"align");
AjxDefangFilter.acceptElement("h4", CORE_LANG+"align");
AjxDefangFilter.acceptElement("h5", CORE_LANG+"align");
AjxDefangFilter.acceptElement("h6", CORE_LANG+"align");
AjxDefangFilter.acceptElement("hr", CORE_LANG+"align,noshade,size,width");
AjxDefangFilter.acceptElement("html", LANG+"xlmns");
AjxDefangFilter.acceptElement("document", CORE_LANG+"language,datafld");
AjxDefangFilter.acceptElement("img", CORE_LANG+"align,alt,border,height,hspace,ismap,longdesc,src,usemap,vspace,width");
AjxDefangFilter.acceptElement("ins", CORE_LANG+"cite");
AjxDefangFilter.acceptElement("label", CORE_LANG+"for");
AjxDefangFilter.acceptElement("p", CORE_LANG+"align");
AjxDefangFilter.acceptElement("pre", CORE_LANG+"width");
AjxDefangFilter.acceptElement("q", CORE_LANG+"cite");
AjxDefangFilter.acceptElement("span", CORE_LANG);
AjxDefangFilter.acceptElement("sub", CORE_LANG);
AjxDefangFilter.acceptElement("sup", CORE_LANG);
AjxDefangFilter.acceptElement("title", "");
AjxDefangFilter.acceptElement("iframe", CORE_LANG+"width,height,top,left");
if (AjxDefangFilter.ENABLE_FONT_STYLE_TAGS) {
AjxDefangFilter.acceptElement("b", CORE_LANG);
AjxDefangFilter.acceptElement("basefont", CORE_LANG+"color,face,size");
AjxDefangFilter.acceptElement("big", CORE_LANG);
AjxDefangFilter.acceptElement("font", CORE_LANG+"color,face,size");
AjxDefangFilter.acceptElement("i", CORE_LANG);
AjxDefangFilter.acceptElement("s", CORE_LANG);
AjxDefangFilter.acceptElement("small", CORE_LANG);
AjxDefangFilter.acceptElement("strike", CORE_LANG);
AjxDefangFilter.acceptElement("tt", CORE_LANG);
AjxDefangFilter.acceptElement("u", CORE_LANG);
} else {
}
if (AjxDefangFilter.ENABLE_LIST_TAGS) {
AjxDefangFilter.acceptElement("dir", CORE_LANG+"compact");
AjxDefangFilter.acceptElement("dl", CORE_LANG);
AjxDefangFilter.acceptElement("dt", CORE_LANG);
AjxDefangFilter.acceptElement("li", CORE_LANG+"type,value");
AjxDefangFilter.acceptElement("ol", CORE_LANG+"compact,start,type");
AjxDefangFilter.acceptElement("ul", CORE_LANG+"compact,type");
AjxDefangFilter.acceptElement("dd", CORE_LANG);
AjxDefangFilter.acceptElement("menu", CORE_LANG+"compact");
} else {
}
if (AjxDefangFilter.ENABLE_PHRASE_TAGS) {
AjxDefangFilter.acceptElement("abbr", CORE_LANG);
AjxDefangFilter.acceptElement("acronym", CORE_LANG);
AjxDefangFilter.acceptElement("cite", CORE_LANG);
AjxDefangFilter.acceptElement("code", CORE_LANG);
AjxDefangFilter.acceptElement("dfn", CORE_LANG);
AjxDefangFilter.acceptElement("em", CORE_LANG);
AjxDefangFilter.acceptElement("kbd", CORE_LANG);
AjxDefangFilter.acceptElement("samp", CORE_LANG);
AjxDefangFilter.acceptElement("strong", CORE_LANG);
AjxDefangFilter.acceptElement("var", CORE_LANG);
} else {
}
if (AjxDefangFilter.ENABLE_TABLE_TAGS) {
AjxDefangFilter.acceptElement("caption", CORE_LANG+"align");
AjxDefangFilter.acceptElement("col",CORE_LANG+"alink,char,charoff,span,valign,width");
AjxDefangFilter.acceptElement("colgroup", CORE_LANG+"alink,char,charoff,span,valign,width");
AjxDefangFilter.acceptElement("table", CORE_LANG+"align,bgcolor,border,cellpadding,cellspacing,frame,rules,summary,width");
AjxDefangFilter.acceptElement("tbody", CORE_LANG+"align,char,charoff,valign");
AjxDefangFilter.acceptElement("td", CORE_LANG+"abbr,align,axis,bgcolor,char,charoff,colspan,headers,height,nowrap,rowspan,scope,,valign,width");
AjxDefangFilter.acceptElement("tfoot", CORE_LANG+"align,char,charoff,valign");
AjxDefangFilter.acceptElement("th", CORE_LANG+"abbr,align,axis,bgcolor,char,charoff,colspan,headers,height,nowrap,rowspan,scope,valign,width");
AjxDefangFilter.acceptElement("thead", CORE_LANG+"align,char,charoff,valign");
AjxDefangFilter.acceptElement("tr", CORE_LANG+"align,bgcolor,char,charoff,valign,height,width");
} else {
}
if (AjxDefangFilter.ENABLE_INPUT_TAGS) {
AjxDefangFilter.acceptElement("area", CORE_LANG+KBD+"alt,coords,href,nohref,shape,target");
AjxDefangFilter.acceptElement("button", CORE_LANG+KBD+"disabled,name,type,value");
AjxDefangFilter.acceptElement("fieldset", CORE_LANG);
AjxDefangFilter.acceptElement("form", CORE_LANG+"action,accept,acceptcharset,enctype,method,name,target");
AjxDefangFilter.acceptElement("input", CORE_LANG+"accept,align,alt,checked,disabled,maxlength,name,readonly,size,src,type,value");
AjxDefangFilter.acceptElement("legend", CORE_LANG+"align");
AjxDefangFilter.acceptElement("map", CORE_LANG+"name");
AjxDefangFilter.acceptElement("optgroup", CORE_LANG+"disabled,label");
AjxDefangFilter.acceptElement("option", CORE_LANG+KBD+"disabled,label,selected,value");
AjxDefangFilter.acceptElement("select", CORE_LANG+KBD+"disabled,multiple,name,size");
AjxDefangFilter.acceptElement("textarea", CORE_LANG+"cols,disabled,name,readonly,rows");
} else {
AjxDefangFilter.removeElement("area");
AjxDefangFilter.removeElement("button");
AjxDefangFilter.removeElement("fieldset");
AjxDefangFilter.removeElement("form");
AjxDefangFilter.removeElement("input");
AjxDefangFilter.removeElement("legend");
AjxDefangFilter.removeElement("map");
AjxDefangFilter.removeElement("optgroup");
AjxDefangFilter.removeElement("option");
AjxDefangFilter.removeElement("select");
AjxDefangFilter.removeElement("textarea");
}
AjxDefangFilter.removeElement("applet");
AjxDefangFilter.removeElement("frame");
AjxDefangFilter.removeElement("frameset");
AjxDefangFilter.removeElement("iframe");
AjxDefangFilter.removeElement("object");
AjxDefangFilter.removeElement("script");
AjxDefangFilter.removeElement("style");
};
AjxDefangFilter.acceptElement = function (element, attributes) {
element = element.toLowerCase();
var set = AjxDefangFilter.mAttrSetCache[attributes];
if (set != null) {
AjxDefangFilter.mAcceptedElements[element] = set;
return;
}
set = new Object();
var attrs = attributes.toLowerCase().split(",");
if (attrs != null && attrs.length > 0) {
for (var i=0; i < attrs.length; i++) {
if (attrs[i].length > 0) {
set[attrs[i]] = attrs[i];
}
}
}
AjxDefangFilter.mAcceptedElements[element] = set;
AjxDefangFilter.mAttrSetCache[attributes] = set;
};
AjxDefangFilter.removeElement = function (element) {
var key = element.toLowerCase();
var value = element;
AjxDefangFilter.mRemovedElements[key] = value;
};
AjxDefangFilter.prototype.elementAccepted = function (element) {
var key = element.toLowerCase();
return (AjxDefangFilter.mAcceptedElements[key] != null);
};
AjxDefangFilter.prototype.elementRemoved = function (element) {
var key = element.toLowerCase();
return (AjxDefangFilter.mRemovedElements[key] != null);
};
AjxDefangFilter.prototype.handleElement = function (element) {
var rawName = element.tagName;
var attributes = element.attributes
if (this.elementAccepted(rawName)) {
var eName = rawName.toLowerCase();
var value = AjxDefangFilter.mAcceptedElements[eName];
if (value != null) {
var anames = value;
var removalArr = new Array();
var attrCount = attributes.length;
var i = 0;
var aName = null;
for (; i < attrCount; ++i) {
aName = attributes[i].nodeName.toLowerCase();
if (!anames[aName]) {
removalArr.push(aName);
} else {
this.sanatizeAttrValue(eName, aName, element, i);
}
}
for (i=0; i < removalArr.length; ++i){
aName = removalArr.pop();
if (AjxEnv.isIE && aName.match(/^on/)){
element[aName] = null;
} else {
element.removeAttribute(aName);
}
}
} else {
element.clearAttributes();
}
if (eName == "img" && this.mNeuterImages) {
this.neuterImageTag(element);
} else if (eName == "a") {
this.fixATag(element);
}
} else if (this.elementRemoved(rawName)) {
this._elementsForRemoval.push(element);
}
};
AjxDefangFilter.prototype.cleanHTML = function (dirtyHTML) {
var re = AjxDefangFilter.TAG_REGEX;
re.lastIndex = 0;
var cleanHTML = dirtyHTML;
var tags = re.exec(dirtyHTML);
var removalArray = new Array();
var sanitizedArray = new Array();
var tag = null;
while (tags != null){
var tagName = tags[1];
var fullTag = tags[0];
var eName = tagName.toLowerCase();
if (this.elementAccepted(tagName)) {
var aNames = AjxDefangFilter.mAcceptedElements[eName];
if (aNames != null) {
var newTag = fullTag;
var attrRegex = AjxDefangFilter.ATTR_REGEX;
attrRegex.lastIndex = 0;
var attrMatch = null;
var attrName = null;
var attrValue = null;
while(attrMatch = attrRegex.exec(fullTag)){
attrName = attrMatch[1]? attrMatch[1]: attrMatch[3];
attrValue = attrMatch[2]? attrMatch[2]: attrMatch[4];
if (!aNames[attrName]){
newTag = newTag.replace(attrMatch[0], "");
} else {
var newVal = this.sanatizeAttrValueStr(eName, attrName,
fullTag,
attrValue);
if (newVal != attrValue){
newTag = newTag.replace(attrMatch[0], " " +
attrName + "='" +
newVal + "' ");
}
}
}
if (eName == "img" && this.mNeuterImages) {
newTag = this.neuterImageTagStr(newTag);
} else if (eName == "a") {
newTag = this.fixATagStr(newTag);
}
if (fullTag != newTag){
sanitizedArray[sanitizedArray.length] = {fullTag: fullTag,
newTag: newTag};
}
} else {
}
} else {
var newTag = "<" + tagName + ">";
sanitizedArray[sanitizedArray.length] = {fullTag: fullTag,
newTag: newTag};
}
if (this.elementRemoved(tagName)) {
var ere = new RegExp("/"+tagName,"i");
var start = tags.index;
var end = cleanHTML.indexOf("/" + tagName, tags.index);
if (end != -1) {
var close = cleanHTML.indexOf(">", end);
end = end + 1 + tagName.length;
if (close != -1){
end = close + 1;
}
var element = cleanHTML.substring(start, end);
removalArray[removalArray.length] = {element: element,
end: end,
start: start};
re.lastIndex = end;
}
}
var tags = re.exec(dirtyHTML);
}
var x = 0;
for (; x < removalArray.length; ++x){
var el = removalArray[x].element;
cleanHTML = cleanHTML.replace(el, "");
}
for (x = 0; x < sanitizedArray.length; ++x) {
var obj = sanitizedArray[x];
var ft = obj.fullTag;
var nt = obj.newTag;
cleanHTML = cleanHTML.replace(ft, nt);
}
return cleanHTML;
};
AjxDefangFilter.prototype.neuterImageTagStr = function (element) {
var idRegex = AjxDefangFilter.ID_REGEX;
var idMatch = idRegex.exec(element);
var srcRegex = AjxDefangFilter.SRC_REGEX
var srcMatch = srcRegex.exec(element);
var src;
var id;
var retStr = null;
if (srcMatch) {
retStr = element;
src = srcMatch[1];
if (idMatch) {
id = idMatch[1];
retStr =
retStr.replace(idMatch[0],idMatch[1]+"=\"" + src + "\"");
} else {
retStr = retStr.replace(">", " id='" + src + "'>");
}
retStr = retStr.replace(srcMatch[0], "src='' ");
}
return retStr;
};
AjxDefangFilter.prototype.neuterImageTag = function (element) {
if (element.src){
element.id = element.src;
element.src = void 0;
}
};
AjxDefangFilter.prototype.fixATagStr = function (element) {
var targetRegex = AjxDefangFilter.TARGET_REGEX;
var targetMatch = targetRegex.exec(element);
var retStr = null;
if (targetMatch) {
retStr = element.replace(targetMatch[0], " target='_blank'");
} else {
retStr = element.replace(">", " target='_blank'>");
}
return retStr;
};
AjxDefangFilter.prototype.fixATag = function (element) {
element.target = "_blank";
};
AjxDefangFilter.prototype.sanatizeAttrValue = function (eName, aName, element,i){
var value = element.getAttribute(aName);
value = value? value: element[aName];
if (typeof(value) != 'string') return;
if (value) {
var result = value.replace(AjxDefangFilter.AV_JS_ENTITY,
"JS-ENTITY-BLOCKED");
result = result.replace(AjxDefangFilter.AV_JS_COLON, "SCRIPT-BLOCKED");
result = result.replace(AjxDefangFilter.AV_SCRIPT_TAG,
"SCRIPT-TAG-BLOCKED");
if (eName !="img" &&(aName == "href" || aName == "src" ||
aName == "longdesc" || aName == "usemap")){
if (!result.search(AjxDefangFilter.ABSOLUTE_URL)) {
result = "about:blank";
}
}
if (result != value) {
if (AjxEnv.isIE){
element[aName] = result;
} else {
element.setAttribute(aName, result);
}
}
}
};
AjxDefangFilter.prototype.sanatizeAttrValueStr = function (eName, aName,
element, value){
if (typeof(value) != 'string') return;
if (value) {
var result = value.replace(AjxDefangFilter.AV_JS_ENTITY,
"JS-ENTITY-BLOCKED");
result = result.replace(AjxDefangFilter.AV_JS_COLON, "SCRIPT-BLOCKED");
result = result.replace(AjxDefangFilter.AV_SCRIPT_TAG,
"SCRIPT-TAG-BLOCKED");
if (eName !="img" &&(aName == "href" || aName == "src" ||
aName == "longdesc" || aName == "usemap")){
if (!result.search(AjxDefangFilter.ABSOLUTE_URL)) {
result = "about:blank";
}
}
}
return result;
};
AjxDefangFilter.prototype._traverseTree = function (nodes) {
var stack = new Array();
var pushFrame = false;
var node = null;
for (var i = 0; i < nodes.length; ++i ) {
node = nodes[i];
switch (node.nodeType) {
case 1:
if (node.nodeName != 'document'){
this.handleElement(node);
}
pushFrame = true;
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
if (AjxEnv.isIE){
} else {
node.parentNode.removeChild(node);
}
break;
case 10:
break;
case 9:
pushFrame = true;
break;
case 11:
pushFrame = true;
break;
case 12:
break;
default:
break;
}
if (pushFrame){
stackObj = {nodes: nodes, index: i};
stack.push(stackObj);
nodes = nodes[i].childNodes;
i = -1;
pushFrame = false;
}
while (i == (nodes.length - 1)){
oldFrame = stack.pop();
if (oldFrame){
nodes = oldFrame.nodes;
i = oldFrame.index;
} else {
break;
}
}
}
var arr = this._elementsForRemoval;
var len = arr.length;
var el = null;
for (var j = 0 ; j < len ; ++j){
el = arr.pop();
if (el.parentNode != null) {
el.parentNode.removeChild(el);
}
}
};
AjxDefangFilter.prototype.parse = function (htmlStr) {
this._elementsForRemoval = new Array();
var htmlEl = null;
if (AjxEnv.isIE) {
return this.cleanHTML(htmlStr);
} else {
htmlEl = document.createElement('html');
htmlEl.innerHTML = htmlStr;
this._traverseTree(htmlEl.childNodes);
return htmlEl.innerHTML;
}
};
Documentation generated by
JSDoc on Thu Apr 27 13:58:41 2006