1 /**
  2  * Validator for W3C Standard Engine
  3  */
  4 xq.ValidatorW3 = xq.Class(xq.Validator, {
  5 	validate: function(element, fullValidation) {
  6 		element = element.cloneNode(true);
  7 
  8 		var rdom = xq.RichDom.createInstance();
  9 		rdom.setRoot(element);
 10 		rdom.removePlaceHoldersAndEmptyNodes(element);
 11 		this.removeDangerousElements(element);
 12 		this.validateFontColor(element);
 13 
 14 		var content = element.innerHTML;
 15 		
 16 		try {
 17 			content = this.replaceTag(content, "b", "strong");
 18 			content = this.replaceTag(content, "i", "em");
 19 			
 20 			content = this.validateStrike(content);
 21 			content = this.validateUnderline(content);
 22 			content = this.addNbspToEmptyBlocks(content);
 23 			
 24 			if(fullValidation) content = this.performFullValidation(content);
 25 		} catch(ignored) {}
 26 
 27 		// insert newline between block-tags
 28 		var blocks = rdom.tree.getBlockTags().join("|");
 29 		var regex = new RegExp("</(" + blocks + ")>([^\n])", "img");
 30 		content = content.replace(regex, '</$1>\n$2');
 31 		
 32 		return content;
 33 	},
 34 	invalidate: function(element) {
 35 		var rdom = xq.RichDom.createInstance();
 36 		rdom.setRoot(element);
 37 		
 38 		// <span class="strike"> -> <strike>
 39 		var strikes = xq.getElementsByClassName(rdom.getRoot(), "strike");
 40 		for(var i = 0; i < strikes.length; i++) {
 41 			if("SPAN" == strikes[i].nodeName) rdom.replaceTag("strike", strikes[i]).removeAttribute("class");
 42 		}
 43 		
 44 		// <em|i class="underline"> -> <u>
 45 		var underlines = xq.getElementsByClassName(rdom.getRoot(), "underline");
 46 		for(var i = 0; i < underlines.length; i++) {
 47 			if(["EM", "I"].indexOf(underlines[i].nodeName) != -1) rdom.replaceTag("u", underlines[i]).removeAttribute("class");
 48 		}
 49 		
 50 		var content = rdom.getRoot().innerHTML;
 51 		
 52 		content = this.replaceTag(content, "strong", "b");
 53 		content = this.replaceTag(content, "em", "i");
 54 		content = this.removeComments(content);
 55 		content = this.replaceNbspToBr(content);
 56 		
 57 		return content;
 58 	},
 59 	
 60 	performFullValidation: function(content) {
 61 		content = this.validateSelfClosingTags(content);
 62 		content = this.applyWhitelist(content);
 63 		
 64 		if(this.urlValidationMode == 'relative') {
 65 			content = this.makeUrlsRelative(content);
 66 		} else if(this.urlValidationMode == 'host_relative') {
 67 			content = this.makeUrlsHostRelative(content);
 68 		} else if(this.urlValidationMode == 'absolute') {
 69 			content = this.makeUrlsAbsolute(content);
 70 		}
 71 
 72 		return content;
 73 	},
 74 	
 75 	validateFontColor: function(element) {
 76 		var rdom = xq.RichDom.createInstance();
 77 		rdom.setRoot(element);
 78 
 79 		var fonts = xq.$A(element.getElementsByTagName('FONT')).reverse();
 80 		for(var i = 0; i < fonts.length; i++) {
 81 			var font = fonts[i];
 82 			var color = font.getAttribute('color');
 83 			
 84 			if(color) {
 85 				var span = rdom.replaceTag("span", font);
 86 				span.removeAttribute('color');
 87 				span.style.color = color;
 88 			}
 89 		}
 90 	},
 91 	
 92 	addNbspToEmptyBlocks: function(content) {
 93 		var blocks = new xq.DomTree().getBlockTags().join("|");
 94 		var regex = new RegExp("<(" + blocks + ")>\\s*?</(" + blocks + ")>", "img");
 95 		return content.replace(regex, '<$1> </$2>');
 96 	},
 97 	
 98 	replaceNbspToBr: function(content) {
 99 		var blocks = new xq.DomTree().getBlockTags().join("|");
100 		var regex = new RegExp("<(" + blocks + ")>( )?</(" + blocks + ")>", "img");
101 		var rdom = xq.RichDom.createInstance();
102 		return content.replace(regex, '<$1>' + rdom.makePlaceHolderString() + '</$3>');
103 	}
104 });
105