(function(){
	var Hackvertor = function() {
		this.historyPos = null;
		this.apps = {};
		this.startTag = '<@';
		this.endTag = '>';
		this.tagNumber = 0;
		this.extendParser = function(parser, appID, code, optParams) {		
				parser.extendWindow("$clearTagLog$", function() { 
					return document.getElementById('tagLog').value = '';					
				});
				parser.extendWindow("$getTagLog$", function() { 
					return document.getElementById('tagLog').value+'';					
				});
				parser.extendWindow("$tagLog$", function(txt) { 
						if(txt.length > 1000) {
							txt = 'Maximum 1000 chars allowed in tagLog';
						}
						document.getElementById('tagLog').value = ''+txt;
						document.getElementById('tagLogLayer').style.display='block';
				});
				parser.extendWindow("$getJSProps$", function(start, end) {
					start = parseInt(start);
					end = parseInt(end);
					if(start > 0 && end > 0 && start < end && end - start > 1000) {
						throw new Error("Invalid range selected");
					}
					var variables = [];
				    for(var i=start;i<end;i++) {
				        try {
				            eval("01."+String.fromCharCode(i)+"");
				            variables.push(String.fromCharCode(i));
				        } catch(e){}
				    }
				    return variables.join(",");
				});
				parser.extendWindow("$getJSVariables$", function(start, end) {	
					
					function fixedFromCharCode (codePt) {
					    if (codePt > 0xFFFF) {
					        codePt -= 0x10000;
					        return String.fromCharCode(0xD800 + (codePt >> 10), 0xDC00 +
					(codePt & 0x3FF));
					    }
					    else {
					        return String.fromCharCode(codePt);
					    }
					}
					
					start = parseInt(start);
					end = parseInt(end);
					if(start > 0 && end > 0 && start < end && end - start > 1000) {
						throw new Error("Invalid range selected");
					}
					var validVariables = [];
						for(i=start;i<end;i++) {
							var variableTest = fixedFromCharCode(i);		
							try { 
								eval(variableTest); 
							} catch(e) {
								if((e+'').indexOf('is not defined') != -1) {
									validVariables.push(variableTest);
								}
								if(e.description && e.description.indexOf('is undefined') != -1) {
									validVariables.push(variableTest);
								}
								
							}
						}
						return validVariables.join(', ');	
				});
				parser.extendWindow("$runCommand$", (function(appID){ 
					var HV = window.Hackvertor;
					return function(command, values) {
						HV.applicationCommand(appID, command, values);
					}				
				})(appID));	
				parser.extendWindow("$sandbox$", function(code){	
					var js = JSReg.create(), result; 
					js.setDebugObjects({doNotFunctionEval:true,functionCode: function(code) {
						code = code.replace("J.F();var $arguments$=J.A(arguments);",'');
						result = code;						
					}});
					try {
						js.eval(code);
					} catch(e){
						return e;
					}
					return result;
				});
				parser.extendWindow("$crypto$", (function(c){														
					return {
						$AES$ : {
							$encrypt$: function(message, passphrase){						
								return c.AES.encrypt(message, passphrase);
							}, 
							$decrypt$: function(crypted, passphrase){
								return c.AES.decrypt(crypted, passphrase);
							}
						},
						$Rabbit$ : {
							$encrypt$: function(message, passphrase){
								return c.Rabbit.encrypt(message, passphrase);
							}, 
							$decrypt$: function(crypted, passphrase){
								return c.Rabbit.decrypt(crypted, passphrase);
							}
						},
						$MARC4$ : {
							$encrypt$: function(message, passphrase){
								return c.MARC4.encrypt(message, passphrase);
							}, 
							$decrypt$: function(crypted, passphrase){
								return c.MARC4.decrypt(crypted, passphrase);
							}
						},
						$PBKDF2$ : function(passphrase, bits, iterations) {
							var salt = c.charenc.Binary.bytesToString(Crypto.util.randomBytes(16));
							return c.PBKDF2(passphrase, salt, bits, { iterations: iterations });
						},
						$Base64$ : {
							$encode$: function(str){
								var strBytes = c.charenc.Binary.stringToBytes(str);
								return c.util.bytesToBase64(strBytes);
							}, 
							$decode$: function(str){
								return String.fromCharCode.apply(null, c.util.base64ToBytes(str));
							}
						}
					};
				})(window.Crypto));
				parser.extendWindow("$getUser$", function() {
						var req = window.Hackvertor.createXHR();
						if(location.host != 'hackvertor.co.uk') {
							req.open('GET', '/hackvertor.co.uk/getUser', false);
						} else {
							req.open('GET', 'https://hackvertor.co.uk/getUser', false);
						}
						req.send(null);
						if(req.status == 200) {							
							return req.responseText;
						} else {
							return 'Failed to get user details.';
						}
				});				
				parser.extendWindow("$getUserID$", function(id) {				
					var req = window.Hackvertor.createXHR();
					if(location.host != 'hackvertor.co.uk') {
						req.open('GET', '/hackvertor.co.uk/getUserID?id='+encodeURIComponent(id), false);
					} else {
						req.open('GET', 'https://hackvertor.co.uk/getUserID?id='+encodeURIComponent(id), false);
					}
					req.send(null);
					if(req.status == 200) {							
						return req.responseText;
					} else {
						return 'Failed to get user info.';
					}
				});			
				parser.extendWindow("$loadStorage$", function(appID, id) {				
					var req = window.Hackvertor.createXHR();
					if(location.host != 'hackvertor.co.uk') {
						req.open('GET', '/hackvertor.co.uk/loadStorage?appID='+encodeURIComponent(appID)+'&id='+encodeURIComponent(id), false);
					} else {
						req.open('GET', 'https://hackvertor.co.uk/loadStorage?appID='+encodeURIComponent(appID)+'&id='+encodeURIComponent(id), false);
					}
					req.send(null);
					if(req.status == 200) {							
						return req.responseText;
					} else {
						return 'Failed to get storage.';
					}
				});
				parser.extendWindow("$saveStorage$", function(appID, id, JSON, mode) {				
					var req = window.Hackvertor.createXHR();
					if(location.host != 'hackvertor.co.uk') {
						req.open('GET', '/hackvertor.co.uk/saveStorage?appID='+encodeURIComponent(appID)+'&id='+encodeURIComponent(id)+'&JSON='+encodeURIComponent(JSON)+'&mode='+encodeURIComponent(mode), false);
					} else {
						req.open('GET', 'https://hackvertor.co.uk/saveStorage?appID='+encodeURIComponent(appID)+'&id='+encodeURIComponent(id)+'&JSON='+encodeURIComponent(JSON)+'&mode='+encodeURIComponent(mode), false);				
					}
					req.send(null);
					if(req.status == 200) {							
						return req.responseText;
					} else {
						return 'Failed to get storage.';
					}
				});
				parser.extendWindow("$userConnected$", function(appID) {				
					var req = window.Hackvertor.createXHR();
					if(location.host != 'hackvertor.co.uk') {
						req.open('GET', '/hackvertor.co.uk/userConnected?appID='+encodeURIComponent(appID), false);
					} else {
						req.open('GET', 'https://hackvertor.co.uk/userConnected?appID='+encodeURIComponent(appID), false);				
					}
					req.send(null);
					if(req.status == 200) {							
						return req.responseText;
					} else {
						return 'Failed to connect.';
					}
				});
				parser.extendWindow("$getConnected$", function(appID) {				
					var req = window.Hackvertor.createXHR();
					if(location.host != 'hackvertor.co.uk') {
						req.open('GET', '/hackvertor.co.uk/getConnected?appID='+encodeURIComponent(appID), false);
					} else {
						req.open('GET', 'https://hackvertor.co.uk/getConnected?appID='+encodeURIComponent(appID), false);				
					}
					req.send(null);
					if(req.status == 200) {							
						return req.responseText;
					} else {
						return 'Failed to connect.';
					}
				});
				parser.extendWindow("$getPipe$", function(queryString) {
					var req = window.Hackvertor.createXHR();
					req.open('GET', 'https://hackvertor.co.uk/getPipe?queryString='+encodeURIComponent(queryString), false); 
					req.send(null);
					if(req.status == 200) {																		
						return decodeURIComponent(req.responseText);
					} else {
						return 'Failed to get pipe.';
					}
				});
				parser.extendWindow("$execLanguage$", function(code, input, language) {
					var req = window.Hackvertor.createXHR();
					req.open('GET', 'https://hackvertor.co.uk/execLanguage?code='+encodeURIComponent(code)+'&input='+encodeURIComponent(input)+'&language='+encodeURIComponent(language), false); 
					req.send(null);
					if(req.status == 200) {																		
						return decodeURIComponent(req.responseText);
					} else {
						return 'Failed to get pipe.';
					}
				});				
				if(code !== undefined) {
					parser.extendWindow('$code$',code);
					if(optParams) {					
						parser.extendWindow('$params$',optParams);
					} else {
						parser.extendWindow('$params$',window.Hackvertor.params);
					}				
				}
				parser.extendWindow('$outputHTML$',(function(HTMLReg, HV) {
					var htmlpreview = document.getElementById('htmlpreview');
					return function(html) {	
							if(htmlpreview.style.display == 'block') {
								return 'Already open';
							}							
							html = HTMLReg.parse(html);
							HV.testHTML(html);
							return html;
					}
				})(window.HTMLReg, window.Hackvertor));
				parser.extendWindow('$log$',(function(astalanumerator,JSON) {
					var result = document.getElementById('inspectionResult');
					return function(obj, compact) {	
							if(result.style.display == 'block') {
								return 'Already open';
							}
							try {
								var json_obj = JSON(obj);
							} catch(e) {
								return "Invalid JSON string.";
							}																				
							astalanumerator.init(true);
							if(compact) {
								astalanumerator.compact = true;
							}
							astalanumerator.currentObj = json_obj;
							astalanumerator.inspect(astalanumerator.currentObj, 'astalanumerator.currentObj', result);
							return '';
					}
				})(window.astalanumerator, json_parse));
				parser.extendObject('$HV$',(function(tags) { 
						return function(tagName, args) {							
							if(!tags.hasOwnProperty(tagName)) {
								return null;
							}	
							if(!args) {
								args = [];
							}														
							return tags[tagName].execTag(this+'',function(output){ return output; },args, true);							
						   }
					})(window.Hackvertor.tags)
				);												
			return parser;
		}
		this.createXHR = function() {
			if (typeof XMLHttpRequest == "undefined") {
			  var req = function () {
			    try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
			      catch (e1) {}
			    try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
			      catch (e2) {}
			    try { return new ActiveXObject("Msxml2.XMLHTTP"); }
			      catch (e3) {}						  
			    throw new Error("This browser does not support XMLHttpRequest.");
			  };
			} else {
				var req = new XMLHttpRequest();
			}
		  return req;	
		}
		this.checkBase64 = function() {
			if(document.getElementById('nosave').checked) {
				str = window.Hackvertor.settings.input.value+'';				
				var strBytes = Crypto.charenc.Binary.stringToBytes(str);				
				location.hash = Crypto.util.bytesToBase64(strBytes);
				this.hideHvurl();
				return false;
			} else {
				return true;
			}
		}
		this.hvurl = function() {
			if(!window.Hackvertor.settings.input||window.Hackvertor.settings.input.value == '') {
				alert('You need to enter something into Hackvertor first.');
				return false;
			}
			window.Hackvertor.settings.hvurlWindow.style.display = 'block';
			window.Hackvertor.settings.hvurlData.value = window.Hackvertor.settings.input.value;
		}
		this.hideHvurl = function() {
			window.Hackvertor.settings.hvurlWindow.style.display = 'none';
		}		
		this.applicationCommand = function(appID, command, values) {									
			if(typeof values != 'object') {
				values = [];
			}
			var obj = this.apps['$'+appID+'$'];
			obj['$'+command+'$'].apply(null, values);									
		}
		this.loadApplication = function(code, appID) {				
			DomAPI.setAppID(appID);
			CSSReg.setAppID(appID);
			HTMLReg.setAppID(appID);	
			var parser = DomAPI.createParser();	
			parser = window.Hackvertor.extendParser(parser, appID);	
			parser.extendWindow('$'+appID+'$', (function(appID){ 
				var HV = window.Hackvertor;
				return function(command, values) {
					HV.applicationCommand(appID, command, values);
				}				
			})(appID));
			var site = parser.eval(code);			
			var appHTML = '<html>';
			appHTML += '<head>';
			appHTML += '<base target="_top" />';
			appHTML += '<title>'+appID+'</title>';						
			appHTML += '<style type="text/css">' + CSSReg.parse(site.$styles$()) + '</style>';				
			appHTML += '</head>';
			appHTML += '<body id="'+appID+'">';														
			appHTML += HTMLReg.parse(site.$html$());		
			appHTML += '</body>';
			appHTML += '</html>';			
			var doc = document.getElementById('application').contentWindow.document;			
			doc.open();			
			doc.write(appHTML);
			doc.close();
			document.getElementById('application').contentWindow.site = site;
			DomAPI.setDocument(doc);
			this.apps['$'+appID+'$'] = site;
			this.applicationCommand(appID, 'home', []);
		}
		this.naturalLanguage = function() {
			var text = document.getElementById('naturalLanguage').value,
				commands = nlsm.parse(text),
				tags = [];
			
			if(!this.getSelectedText()) {
				this.selectInput();
			}
			
			for(var i=0;i<commands.length;i+=2) {
				var command = commands[i+1];
				if(commands[i] == 'encode') {
					for(var id in this.tagIDS) {
						if(this.tagIDS.hasOwnProperty(id)) {
							if(this.tagIDS[id] == command) {
								tags.push(id);
								break;
							}
						}
					}
				} else {
					var foundDecode = 0;
					for(var id in this.tagIDS) {
						if(this.tagIDS.hasOwnProperty(id)) {
							if(this.tagIDS[id] == 'd_'+command) {							
								tags.push(id);
								foundDecode = 1;
								break;
							}
						}
					}
					if(!foundDecode) {
						tags.push(71);
					}
				}								
				
			}
			this.selectTag(tags);			
		}
		this.clear = function() {
				this.settings.input.value='';
				this.settings.output.value='';
				this.settings.input.focus();
				this.showLengths();
		}
		this.clearTags = function() {
			var hv = window.Hackvertor;
			var input = hv.settings.input.value;
			var regexpString = hv.startTag+'([_0-9a-zA-Z]+)(\\(.*\\))?'+hv.endTag;
			input = input.replace(new RegExp(regexpString,'g'),'');
			var regexpString = hv.startTag+'\/([_0-9a-zA-Z]+)'+hv.endTag;
			input = input.replace(new RegExp(regexpString,'g'),'');	
			hv.settings.input.value = input;
			hv.settings.input.focus();
			hv.showLengths();
		}
		this.swapInput = function() {
			this.settings.input.value=this.settings.output.value;
			this.settings.output.value=''
			this.settings.input.focus();
			this.showLengths();			
		}
		this.selectInput = function() {		
			this.settings.input.focus();
			this.settings.input.select();			
		}
		this.selectOutput = function() {
			this.settings.output.focus();
			this.settings.output.select();			
		}
		this.convert = function() {			
			this.execute();				
			this.showLengths();
			this.selectOutput();
		}
		this.resetParams = function() {
			this.params = [];
		}
		this.formatParam = function(param) {
			if(!/[^\d.]/.test(param) && /[.]/.test(param) && /[\d]/.test(param)) {
				return parseFloat(param);
			} else if(!/[^\d]/.test(param) && /[\d]/.test(param)) {
				return parseInt(param);
			} else {
				return ''+param;
			}
		}
		this.setParams = function(params) {
			params = params.replace(/^\(|\)$/g,'');
			params = params.replace(/((['])([^']*|\\['])(['])|(["])([^"]*|\\["])(["]))/g, function($0, $1, $2, $3, $4, $5, $6) { 							
				return $5 == '"' ? escape($6) : escape($3); 
			});
			this.params = params.split(',');
			for(var i in this.params) {
				this.params[i] = this.formatParam(unescape(this.params[i]));
			}
		}
		this.addTag = function(obj) {					
			this.tagIDS[obj.id] = obj.name;
			if(typeof this.categories[obj.categoryID] == 'undefined') {
				this.categories[obj.categoryID] = [obj.id];
			} else {
				this.categories[obj.categoryID].push(obj.id);
			}
			this.tags[obj.name] = {code:obj.code, param1:obj.param1, param2:obj.param2, param3:obj.param3, userID: obj.userID, help:obj.help,						
			execTag:function(code, callback, optParams, createNew) {					
				if(createNew) {
					if(!window.APIParser) {
						window.APIParser = JSReg.create();
					}
					var parser = window.APIParser;
					parser.init();
				} else {								
					var parser = window.parser;					
				}
				parser.setDebugObjects({
					errorLog:function(msg) {
					callback(msg);
				},
				errorHandler:function(e) {
					if (e.description) {
							var msg = '';
							if (e.description) {
								msg += 'Description:' + e.description + '\n';
							}
							if(e.msg) {
								msg += 'Msg:'+e.msg+'\n';
							}
							if (e.line) {
								msg += 'Line:' + e.line+'\n';
							}					
												
							if (parser.debugObjects.parseTree) {
								parser.debugObjects.parseTree(e.parseTree);
							}					
							if (parser.debugObjects.errorLog) {
								parser.debugObjects.errorLog(msg);
							} else {
								alert(msg);
							}
						} else {
							if (parser.debugObjects.errorLog) {
								parser.debugObjects.errorLog(e);
							} else {
								alert(e);
							}
						}			
				},
				result:function(code){					
					callback(code);
				},
				onComplete:(function(parser){ return function(result) {				
					parser.init();										
				}
				})(parser)												
				});				
				parser = window.Hackvertor.extendParser(parser, obj.name, code, optParams);
				return parser.eval(obj.code);				
			}};
		};
		this.addAPIFunction = function(code) {
			codeEditor.replaceSelection(code);
		};
		this.addAPICall = function(tagID) {			
			var hv = window.Hackvertor;
			var tag = hv.tags[hv.tagIDS[tagID]];
			var name = hv.tagIDS[tagID];
			var txt = hv.getSelectedText();
			var data;
			var input = hv.settings.input;			
			var tagName = ".HV('" + name + "'";			
			if(tag.param1 != '') {
				tagName += ',[';
				tagName += formatVar(tag.param1);
				if(tag.param2 != '') {
					tagName += ','+formatVar(tag.param2);	
				}
				if (tag.param3 != '') {
					tagName += ','+formatVar(tag.param3);
				}	
				tagName += ']';
			}	
			tagName += ')';
			function formatVar(str) {
				if(/[^\d]/.test(str)) {
					return "'" + str.replace(/'/g,'\\\'') + "'";
				} else {
					return str;
				}
			}
			
			codeEditor.replaceSelection(tagName);
		};
		this.selectTag = function(tagID) {
			var hv = window.Hackvertor, 
				input = hv.settings.input;
			if(typeof tagID != 'object') {
				tagList = [tagID];
			} else {
				tagList = tagID;
			}
			var data = input.value,	
				txt = hv.getSelectedText(),				
				start = '',
				end = '',
				startTag = [],
				endTag = [];				
			if(!document.selection || navigator.userAgent.indexOf("Opera") > -1) {
				start = data.substr(0, input.selectionStart);
				end = data.substr(input.selectionEnd, data.length);
			} else {
				if(document.selection) {								
					var range = document.selection.createRange();
					var stored_range = range.duplicate();
					stored_range.moveToElementText(input);
					stored_range.setEndPoint( 'EndToEnd', range );
					input.selectionStart = stored_range.text.length - range.text.length;
					input.selectionEnd = input.selectionStart + range.text.length;					
					start = '' + data.substr(0, input.selectionStart);
					end = data.substr(input.selectionEnd, data.length);															
				} 
			}			
			for(var i=0;i<tagList.length;i++) {
				tagID = tagList[i];																	
				var tag = hv.tags[hv.tagIDS[tagID]];
				var name = hv.tagIDS[tagID];				
				var tagName = name + '_' + hv.tagNumber + '';
				var firstTagName = tagName;
				if(tag.param1 != '') {
					firstTagName += '(';
					firstTagName += tag.param1;
					if(tag.param2 != '') {
						firstTagName += ','+tag.param2;	
					}
					if (tag.param3 != '') {
						firstTagName += ','+tag.param3;
					}			
					firstTagName += ')';
				}		
				hv.tagNumber++;						
				if(!document.selection || navigator.userAgent.indexOf("Opera") > -1) {												
					startTag.push(hv.startTag + firstTagName + hv.endTag);
					endTag.push(''+ hv.startTag + '/' + tagName + hv.endTag);																										
				} else {					
					if(document.selection) {			
						var range = document.selection.createRange();
						var stored_range = range.duplicate();
						stored_range.moveToElementText(input);
						stored_range.setEndPoint( 'EndToEnd', range );
						input.selectionStart = stored_range.text.length - range.text.length;
						input.selectionEnd = input.selectionStart + range.text.length;					
						startTag.push(hv.startTag + firstTagName + hv.endTag);
						endTag.push('' + hv.startTag + '/' + tagName + hv.endTag);																								        
					} else {					
						startTag.push(hv.startTag + firstTagName + hv.endTag);
						endTag.push('' + hv.startTag + '/' + tagName + hv.endTag);					
					}															
				}				
			}			
			input.value=start+startTag.reverse().join('')+txt+endTag.join('')+end;
			hv.showLengths();				
			input.focus();
			this.convert();
		};
		this.getSelectedText = function() {    
			var txt = '';    
			if(window.getSelection) {
			   txt = window.getSelection();
			} else if (document.getSelection) {
				txt = document.getSelection();
			} else if (document.selection) {
				txt = document.selection.createRange().text;
			} else {
				return;      
			}
			
			var input = window.Hackvertor.settings.input;
			if(txt == '') {
			  txt = (input.value).substring(input.selectionStart,input.selectionEnd);      
			  return txt;
			} else { 
			  return txt;
			}
		}		
		this.escape = function(str) {
			str = str +'';
			str = str.replace(/./g,function(c){
				return '&#' + c.charCodeAt(0) + ';';
			});
			return str;
		};
		this.tagHTML = '';
		this.clearTagHTML = function() {
			window.Hackvertor.tagHTML = '';
		};
		this.showTag = function(tagID) {
			var tag = window.Hackvertor.tags[window.Hackvertor.tagIDS[tagID]];
			var name = window.Hackvertor.tagIDS[tagID];
			window.Hackvertor.tagHTML += '<span title="'+window.Hackvertor.escape(tag.help)+'" class="highlight" onmousedown="Hackvertor.selectTag('+tagID+')">'+window.Hackvertor.escape(name)+'</span>';
		};
		
		this.checkID = function(id, userID) {			
			if(typeof window.Hackvertor.categories[id] != 'undefined') {
				var tagList = window.Hackvertor.categories[id];
				for(var i = 0;i<tagList.length;i++) {
					var tagID = tagList[i];					
					if(window.Hackvertor.tags[window.Hackvertor.tagIDS[tagID]].userID != userID && userID != '') {
						continue;
					}
					window.Hackvertor.showTag(tagID);
				}
			}
		}
		this.hexView = function(text) {
			text = text+'';
			text = text.replace(/./mg, function(c) {
				return ' ' + '0x' + /..$/.exec('00'+ c.charCodeAt(0).toString(16));
			});
			window.Hackvertor.testHTML(text);
		}
		this.changeCategory = function(id) {
			if(!document.getElementById('usersTags')) {
				return false;
			}
			var userID = document.getElementById('usersTags').options[document.getElementById('usersTags').selectedIndex].value;
			window.Hackvertor.clearTagHTML();			
			window.Hackvertor.checkID(id, userID);			
			window.Hackvertor.settings['tagContainer'].innerHTML = window.Hackvertor.tagHTML;						
		};
		this.appendSelect = function(select, value, content) {
			var opt;
			opt = document.createElement("option");
			opt.value = value;
			opt.appendChild(document.createTextNode(content));
			select.appendChild(opt);
		}
		this.clearSelect = function(select) {			
				while (select.length > 1) {
					select.remove(select.length-1);
				}			
		}
		this.categories = {};				
		this.tags = {			
		};
		this.tagIDS = {};
		this.hvurls = [];
		this.run = function(code, type, callback) {						
			this.tags[type].execTag(code, callback);
		}
		this.execute = function() {
			var input = this.settings.input.value;		
			this.output = input;
			var regexpString;
			var tagOrder = [];
			var re = new RegExp(this.startTag+'[\\w\\d]+(\\([^)]*\\))?\\s\/'+this.endTag + '|' + this.startTag+'\/[\\w\\d]+'+'\\'+this.endTag,'g');
			var matchedTags = this.output.match(re);
			if(matchedTags != null) {
				for(var i=0;i<matchedTags.length;i++) {				
					matchedTags[i] = matchedTags[i].replace(/\(.+\)\s*/,'');
					tagOrder.push(matchedTags[i].replace(new RegExp('['+this.startTag+this.endTag+'\/]','g'), ''));
				}
				var tagPos = 0;					
				this.execTagOrder(0, tagOrder);
			}											
		}
		this.regexpTags = function() {
			var hv = window.Hackvertor;
			var input = hv.settings.input.value;
			if(input == '') {
				alert('Enter some text and tags');
				return false;
			}
			var converted = '';
			var regexpString = hv.startTag+'([_0-9a-zA-Z]+)(\\(.*?\\))?'+hv.endTag;
			var tags = [];
			input = input.replace(new RegExp(regexpString,'g'),function($0, name, params) {			
				tags.push({name:name.replace(/_\d+$/,''), params: params});							
				return '';
			});
			var regexpString = hv.startTag+'\/([_0-9a-zA-Z]+)'+hv.endTag;
			input = input.replace(new RegExp(regexpString,'g'),'');	
			var regexp = prompt('Enter your regexp to split the input and apply the tags to');
			regexp = new RegExp(regexp+'','g');
			var counter = 0;
			input.replace(regexp, function(txt) {
				var out = [];
				var out2 = [];
				for(var i=0;i<tags.length;i++) {
					var tag = tags[i];
					out.push(hv.startTag+tag.name+'_'+counter+tag.params+hv.endTag); 
					out2.push(hv.startTag+'/'+tag.name+'_'+counter+hv.endTag);
					counter++;
				}
				converted += out.join("")+txt+out2.reverse().join("");
			});
			hv.settings.input.value = converted;
		}
		this.execTagOrder = function(tagPos, tagOrder){			
			var that = this;
			regexpString = this.startTag + '(' + tagOrder[tagPos] + ')(\\(.*\\))?' + this.endTag + '(([\\S\\s])*?)' + this.startTag + '\/(' + tagOrder[tagPos] + ')' + this.endTag + '|' + this.startTag + '(' + tagOrder[tagPos] + ')(\\(.*\\))?' + '\\s*\\/' + this.endTag;
			var re = new RegExp(regexpString);
			var matches = '';
			var r = re.exec(this.output);
			if (r != null) {
				this.resetParams();
				r[1] = !r[1] ? r[6] : r[1];
				var type = r[1].replace(/_[\s\d]+$/, '');
				var actualTagName = r[1];
				var params = !r[2] ? r[7] : r[2];
				if (params != null) {
					this.setParams(params);
				}
				var code = r[3];
				try {
					if (code === undefined) {
						code = '';
					}					
					this.run(code, type, function(result) {							
						result = result + '';						
						result = result.replace(/\$/g, '$$$$');						
						regexpString = that.startTag + '(' + actualTagName + ')(\\(.*\\))?' + that.endTag + '(([\\S\\s]*))' + that.startTag + '\/(' + actualTagName + ')' + that.endTag + '|' + that.startTag + '(' + actualTagName + ')(\\(.*\\))?\\s*\/' + that.endTag;
						that.output = that.output.replace(new RegExp(regexpString), result);						
						if(++tagPos < tagOrder.length) {							
							that.execTagOrder(tagPos, tagOrder);							
						} else {							
							that.settings.output.value = that.output;
							if(that.settings.outputCallback) {
								that.settings.outputCallback(that.output);
							}
						}						
					});										
				} 
				catch (e) {
					alert('--Error Performing conversion--\n' + e);
					return 'Please check syntax.';
				}
			}
		}
		this.realLength = function(str) {
			var len = 0;			
			str.replace(/(?:[\f\n\u000b\u2028\u2029]|.)/gi,function(c) {												
				if(c.charCodeAt() <= 0x007F) {
					len++;
				} else if(c.charCodeAt() <= 0x07FF) {
					len+=2;
				} else if(c.charCodeAt() <= 0xFFFF) {
					len+=3;
				} else if(c.charCodeAt() <= 0x10FFFF) {
					len+=4;
				}												
			});			
			return len;
		}
		this.showLengths = function() {
			this.settings.inputCharLen.innerHTML=+this.settings.input.value.length;
			this.settings.outputCharLen.innerHTML=+this.settings.output.value.length;
			this.settings.inputUnicodeCharLen.innerHTML=+this.realLength(this.settings.input.value);
			this.settings.outputUnicodeCharLen.innerHTML=+this.realLength(this.settings.output.value);
		}		
		this.settings = function(settings) {
			this.settings = settings;
		}
		this.addSetting = function(name, value) {
			this.settings[name] = value;
		}
		this.encodeForPreview = function(str) {
			str = str.replace(/[^\w\n\r ]/gi,function(c) {
				return '&#' + c.charCodeAt() + ';';
			});
			str = str.replace(/[ ]/gi,'&nbsp;').replace(/[\t]/gi,'&nbsp;&nbsp;&nbsp;').replace(/[\r\n]/gi,'<br>');			
			return str;
		}
		this.funcInspect = function() {
			var obj = eval(this.settings.output.value);
			var jsBuiltInProps = ['enumerable','configurable','set','get','writable','$','$&','$\'','$*','$+','$1','$2','$3','$4','$5','$6','$7','$8','$9','$`','APPLICATION','ATOMICSELECTION','AddChannel','AddDesktopComponent','AddFavorite','Anchor','Applet','Area','Array','Attr','AutoCompleteSaveForm','AutoScan','BGCOLOR','BaseHref','BehaviorUrnsCollection','BookmarkCollection','Boolean','Button','CSSCurrentStyleDeclaration','CSSRuleList','CSSRuleStyleDeclaration','CSSStyleDeclaration','CSSStyleRule','CSSStyleSheet','Checkbox','ChooseColorDlg','CompatibleInfo','CompatibleInfoCollection','ControlRangeCollection','Count','DOMImplementation','DataTransfer','Date','Dialog','E','Element','Event','FieldDelim','FileUpload','Form','Frame','Function','GetObject','HTCElementBehaviorDefaults','HTMLAnchorElement','HTMLAreaElement','HTMLAreasCollection','HTMLBGSoundElement','HTMLBRElement','HTMLBaseElement','HTMLBaseFontElement','HTMLBlockElement','HTMLBodyElement','HTMLButtonElement','HTMLCollection','HTMLCommentElement','HTMLDDElement','HTMLDListElement','HTMLDTElement','HTMLDivElement','HTMLDocument','HTMLEmbedElement','HTMLFieldSetElement','HTMLFontElement','HTMLFormElement','HTMLFrameElement','HTMLFrameSetElement','HTMLGenericElement','HTMLHRElement','HTMLHeadElement','HTMLHeadingElement',1,'HTMLHtmlElement','HTMLIFrameElement','HTMLImageElement','HTMLInputElement','HTMLIsIndexElement','HTMLLIElement','HTMLLabelElement','HTMLLegendElement','HTMLLinkElement','HTMLMapElement','HTMLMarqueeElement','HTMLMetaElement','HTMLModelessDialog','HTMLNamespaceInfo','HTMLNamespaceInfoCollection','HTMLNextIdElement','HTMLNoShowElement','HTMLOListElement','HTMLObjectElement','HTMLOptionElement','HTMLParagraphElement','HTMLParamElement','HTMLPhraseElement','HTMLPluginsCollection','HTMLPopup','HTMLScriptElement','HTMLSelectElement','HTMLSpanElement','HTMLStyleElement','HTMLTableCaptionElement','HTMLTableCellElement','HTMLTableColElement','HTMLTableElement','HTMLTableRowElement','HTMLTableSectionElement','HTMLTextAreaElement','HTMLTextElement','HTMLTitleElement','HTMLUListElement','HTMLUnknownElement','Helper','Hidden','History','Image','ImportExportFavorites','Infinity','isArray','IsSubscribed','JSON','JavaArray','JavaClass','JavaObject','JavaPackage','LN10','LN2','LOG10E','LOG2E','Layer','Link','Location','MAX_VALUE','MIN_VALUE','Math','Methods','MimeType','NEGATIVE_INFINITY','NaN','NamedNodeMap','NavigateAndFind','Navigator','NodeList','Number','Object','Option','PI','POSITIVE_INFINITY','Packages','Password','Plugin','Radio','RegExp','Reset','SECURITY','SQRT1_2','SQRT2','STYLE','Screen','ScriptEngine','ScriptEngineBuildVersion','ScriptEngineMajorVersion','ScriptEngineMinorVersion','Select','Selection','ShowBrowserUI','StaticNodeList','Storage','String','Style','StyleSheetList','StyleSheetPage','StyleSheetPageList','Submit','Text','TextNode','TextRange','TextRangeCollection','TextRectangle','TextRectangleList','Textarea','UNSELECTABLE','URL','URLUnencoded','UTC','Window','XDomainRequest','XMLDocument','XMLHttpRequest','XMLNS','XSLDocument','__caller__','__count__','__defineGetter__','__defineSetter__','__iterator__','__lookupGetter__','__lookupSetter__','__noSuchMethod__','__parent__','__proto__','_content','aLink','aLinkcolor','abbr','abort','above','abs','accelerator','accept','acceptCharset','accessKey','acos','action','activeElement','add','addBehavior','addElement','addImport','addListener','addPageRule','addProperty','addReadRequest','addRule','addheader','additive','alert','align','alinkColor','all','allowDomain','allowTransparency','alt','altHTML','altKey','altLeft','anchor','anchors','and','appCodeName','appCore','appMinorVersion','appName','appVersion','appendChild','appendData','applets','applicationName','apply','applyElement','archive','areas','arguments','arguments.callee','arguments.caller','arguments.length','aria-activedescendant','aria-busy','aria-checked','aria-controls','aria-describedby','aria-disabled','aria-expanded','aria-flowto','aria-haspopup','aria-hidden','aria-invalid','aria-labelledby','aria-level','aria-live','aria-multiselectable','aria-owns','aria-posinset','aria-pressed','aria-readonly','aria-relevant','aria-required','aria-secret','aria-selected','aria-setsize','aria-valuemax','aria-valuemin','aria-valuenow','arity','asin','assign','atEnd','atan','atan2','atob','attachAudio','attachEvent','attachMovie','attachSound','attachVideo','attribute','attributes','autoSize','autocomplete','availHeight','availLeft','availTop','availWidth','axis','back','background','backgroundAttachment','backgroundColor','backgroundImage','backgroundPosition','backgroundPositionX','backgroundPositionY','backgroundRepeat','balance','banner','bannerAbstract','beginFill','beginGradientFill','behavior','behaviorUrns','below','bgColor','bgProperties','bind','big','blink','blockDirection','blockFormats','blockIndent','blur','body','bold','boolean','border','borderBottom','borderBottomColor','borderBottomStyle','borderBottomWidth','borderCollapse','borderColor','borderColorDark','borderColorLight','borderLeft','borderLeftColor','borderLeftStyle','borderLeftWidth','borderRight','borderRightColor','borderRightStyle','borderRightWidth','borderSpacing','borderStyle','borderTop','borderTopColor','borderTopStyle','borderTopWidth','borderWidth','borderWidths','bottom','bottomMargin','bottomScroll','boundElements','boundingHeight','boundingLeft','boundingTop','boundingWidth','boxSizing','break','broadcastMessage','browserLanguage','btoa','bufferDepth','bullet','button','byte','call','callee','caller','canHaveChildren','canHaveHTML','cancelBubble','capabilities','caption','captionSide','captureEvents','case','catch','ceil','cellIndex','cellPadding','cellSpacing','cells','ch','chOff','char','charAt','charCodeAt','characterSet','charset','checked','childNodes','children','chr','cite','class','className','classes','classid','clear','clearAttributes','clearData','clearInterval','clearRequest','clearTimeout','click','clientHeight','clientInformation','clientLeft','clientTop','clientWidth','clientX','clientY','clip','clipBottom','clipLeft','clipRight','clipTop','clipboardData','cloneNode','close','closed','code','codeBase','codeType','colSpan','collapse','color','colorDepth','cols','compact','compareEndPoints','compatMode','compatible','compile','complete','componentFromPoint','components','concat','condenseWhite','confirm','connect','const','constructor','contains','content','contentDocument','contentEditable','contentOverflow','contentType','contentWindow','contextual','continue','control','controlRange','controllers','cookie','cookieEnabled','coords','cos','counterIncrement','counterReset','cpuClass','create','createAttribute','createCaption','createComment','createControlRange','createDocumentFragment','createElement','createEmptyMovieClip','createEventObject','createPopup','createRange','createStyleSheet','createTFoot','createTHead','createTextField','createTextNode','createTextRange','crypto','cssText','ctrlKey','ctrlLeft','current','currentStyle','cursor','curveTo','data','dataFld','dataFormatAs','dataPageSize','dataSrc','dataTransfer','dateTime','debugger','declare','decode','decodeURI','decodeURIComponent','default','defaultCharset','defaultChecked','defaultSelected','defaultStatus','defaultValue','defaultView','defaults','defer','defineProperty','defineProperties','delete','deleteCaption','deleteCell','deleteData','deleteRow','deleteTFoot','deleteTHead','description','designMode','detachEvent','deviceXDPI','deviceYDPI','dialogArguments','dialogHeight','dialogLeft','dialogTop','dialogWidth','dimensions','dir','direction','directories','disableExternalCapture','disabled','display','do','doImport','doReadRequest','doScroll','docTypeDecl','doctype','document','documentElement','documentMode','domain','double','dragDrop','dragOut','dragOver','dropEffect','dump','duplicate','duplicateMovieClip','duration','dynsrc','effectAllowed','elementFromPoint','elements','else','embedFonts','embeds','empty','emptyCells','enableExternalCapture','enabled','enabledPlugin','encodeURI','encodeURIComponent','encoding','enctype','endFill','enterFrame','enum','eq','escape','eval','evaluate','event','every','exec','execCommand','execScript','exp','expando','export','extends','external','face','fgColor','fileCreatedDate','fileModifiedDate','fileName','fileSize','fileUpdatedDate','filename','filter','filters','final','finally','find','findText','fireEvent','firstChild','firstPage','fixed','float','floor','flush','focus','focusEnabled','font','fontColor','fontFamily','fontSize','fontSmoothingEnabled','fontStyle','fontVariant','fontWeight','fontcolor','fonts','fontsize','for','forEach','form','formName','forms','forward','frame','frameBorder','frameElement','frameSpacing','frames','fromCharCode','fromElement','freeze','frozen','fscommand','function','galleryImg','ge','get','getAdjacentText','getAllResponseHeaders','getAscii','getAttention','getAttribute','getAttributeNode','getBeginIndex','getBookmark','getBounds','getBytesLoaded','getBytesTotal','getCaretIndex','getCharset','getClientRects','getCode','getCookie','getData','getDate','getDay','getDepth','getDuration','getElementById','getElementsByName','getElementsByTagName','getEndIndex','getExpression','getFocus','getFontList','getFullYear','getHours','getItem','getMilliseconds','getMinutes','getMonth','getNamedItem','getNewTextFormat','getOwnPropertyDescriptor','getOwnPropertyNames','getPan','getPosition','getProperty','getPrototypeOf','getRGB','getResponseHeader','getSeconds','getSelection','getSize','getTextExtent','getTextFormat','getTime','getTimer','getTimezoneOffset','getTransform','getURL','getUTCDate','getUTCDay','getUTCFullYear','getUTCHours','getUTCMilliseconds','getUTCMinutes','getUTCMonth','getUTCSeconds','getUTCYear','getVarDate','getVersion','getVolume','getYear','global','globalToLocal','go','goto','gotoAndPlay','gotoAndStop','gt','handleEvent','hasAccessibility','hasAudio','hasAudioEncoder','hasChildNodes','hasFeature','hasFocus','hasLayout','hasMP3','hasOwnProperty','hasVideoEncoder','hash','headers','height','hidden','hide','hideFocus','history','hitArea','hitTest','home','host','hostname','href','hreflang','hscroll','hspace','html','htmlFor','htmlText','httpEquiv','id','ids','if','ifFrameLoaded','ignoreCase','ignoreWhite','images','imeMode','implementation','implements','import','imports','in','inRange','include','indent','indeterminate','index','indexOf','innerHTML','innerHeight','innerText','innerWidth','input','insertAdjacentElement','insertAdjacentText','insertBefore','insertCell','insertData','insertRow','install','instanceof','int','interface','isActive','isAlternate','isContentEditable','isDebugger','isDisabled','isDown','isEqual','isFinite','isMap','isMultiLine','isNaN','isOpen','isPrefAlternate','isPropertyEnumerable','isPrototypeOf','isTextEdit','isToggled','italic','italics','item','java','javaEnabled','join','keys','keyCode','keyDown','keyPress','keyUp','label','lang','language','lastChild','lastIndex','lastIndexOf','lastMatch','lastModified','lastPage','lastParen','layerX','layers','layoutFlow','layoutGrid','layoutGridChar','layoutGridLine','layoutGridMode','layoutGridType','lbound','le','leading','left','leftContext','leftMargin','length','letterSpacing','lineBreak','lineHeight','lineNumber','lineStyle','lineTo','link','linkColor','links','list','listStyle','listStyleImage','listStylePosition','listStyleType','load','loadMovie','loadMovieNum','loadSound','loadVariables','loadVariablesNum','loaded','localName','localStorage','localToGlobal','localeCompare','location','locationbar','log','logicalXDPI','logicalYDPI','long','longDesc','loop','lowsrc','lt','manufacturer','map','margin','marginBottom','marginHeight','marginLeft','marginRight','marginTop','marginWidth','margins','match','max','maxChars','maxConnectionsPerServer','maxHeight','maxLength','maxWidth','maxhscroll','maxscroll','mbchr','mblength','mbord','mbsubstring','media','menuArguments','menubar','mergeAttributes','message','metaInfo','meth','method','mimeType','mimeTypes','min','minHeight','minWidth','mouseDown','mouseMove','mouseUp','move','moveAbove','moveBelow','moveBy','moveEnd','moveFirst','moveNext','moveRow','moveStart','moveTo','moveToAbsolute','moveToBookmark','moveToElementText','moveToPoint','msBlockProgression','msInterpolationMode','multiline','multiple','name','nameProp','namedItem','namedRecordset','namespace','namespaceURI','namespaces','native','navigate','navigator','ne','netscape','new','newline','next','nextFrame','nextPage','nextScene','nextSibling','noHref','noResize','noShade','now','noWrap','nodeName','nodeType','nodeValue','normalize','not','null','number','object','offscreenBuffering','offsetHeight','offsetLeft','offsetParent','offsetTop','offsetWidth','offsetX','offsetY','on','onAbort','onActivate','onAfterprint','onAfterupdate','onBeforeactivate','onBeforecut','onBeforedeactivate','onBeforeeditfocus','onBeforepaste','onBeforeprint','onBeforeunload','onBeforeupdate','onBlur','onCellchange','onChange','onChanged','onClick','onClipEvent','onClose','onConnect','onContextmenu','onControlselect','onCut','onData','onDataavailable','onDatasetchanged','onDatasetcomplete','onDblclick','onDeactivate','onDrag','onDragOut','onDragOver','onDragdrop','onDragend','onDragenter','onDragleave','onDragover','onDragstart','onDrop','onEnterFrame','onError','onErrorupdate','onFocus','onHelp','onKeyDown','onKeyUp','onKeydown','onKeypress','onKeyup','onKillFocus','onLine','onLoad','onMouseDown','onMouseMove','onMouseUp','onMousedown','onMousemove','onMouseout','onMouseover','onMouseup','onPaste','onPress','onPropertychange','onReadystatechange','onRelease','onReleaseOutside','onReset','onResize','onResizeend','onResizestart','onRollOut','onRollOver','onRowenter','onRowexit','onRowsdelete','onRowsinserted','onScroll','onScroller','onSelect','onSelectionchange','onSelectstart','onSetFocus','onSoundComplete','onStop','onSubmit','onUnload','onXML','onpropertychange','onreadystatechange','onvisibilitychange','open','opener','opsProfile','options','or','ord','origin','orphans','os','oscpu','outerHTML','outerHeight','outerText','outerWidth','outline','outlineColor','outlineStyle','outlineWidth','overflow','overflowX','overflowY','ownerDocument','ownerElement','owningElement','package','padding','paddingBottom','paddingLeft','paddingRight','paddingTop','paddings','page','pageBreakAfter','pageBreakBefore','pageBreakInside','pageX','pageXOffset','pageY','pageYOffset','pages','palette','parent','parentElement','parentLayer','parentNode','parentStyleSheet','parentTextEdit','parentWindow','parse','parseFloat','parseInt','parseXML','password','pasteHTML','pathname','pause','personalbar','pixelAspectRatio','pixelBottom','pixelDepth','pixelHeight','pixelLeft','pixelRight','pixelTop','pixelWidth','pkcs11','platform','play','plugin','plugins','plugins.refresh','pluginspage','pop','popup','port','posBottom','posHeight','posLeft','posRight','posTop','posWidth','position','pow','preference','prefix','press','prevFrame','prevScene','previous','previousPage','previousSibling','print','printAsBitmap','printAsBitmapNum','printNum','private','product','productSub','profile','prompt','prompter','propertyIsEnumerable','propertyName','protected','protocol','prototype','pseudoClass','public','publish','push','qualifier','queryCommandEnabled','queryCommandIndeterm','queryCommandState','queryCommandValue','quote','quotes','random','readOnly','readyState','reason','recalc','receiveAudio','receiveVideo','recordNumber','recordset','reduce','reduceRight','referrer','refresh','registerClass','rel','release','releaseCapture','releaseEvents','releaseOutside','reload','remainingSpace','remove','removeAttribute','removeAttributeNode','removeBehavior','removeChild','removeExpression','removeListener','removeMovieClip','removeNamedItem','removeNode','removeRule','removeTextField','repeat','replace','replaceChild','replaceData','replaceNode','replaceSel','reset','resizeBy','resizeTo','responseBody','responseText','responseXML','restrict','return','returnValue','rev','reverse','right','rightContext','rightMargin','role','rollOut','rollOver','round','routeEvents','rowIndex','rowSpan','rows','rubyAlign','rubyOverhang','rubyPosition','rule','rules','runtimeStyle','seal','savePreferences','saveType','scaleMode','scheme','scope','scopeName','screen','screenColor','screenDPI','screenLeft','screenResolutionX','screenResolutionY','screenTop','screenX','screenY','scripts','scroll','scrollAmount','scrollBy','scrollByLines','scrollByPages','scrollDelay','scrollHeight','scrollIntoView','scrollLeft','scrollString','scrollTo','scrollTop','scrollWidth','scrollX','scrollY','scrollbar','scrollbar3dLightColor','scrollbarArrowColor','scrollbarBaseColor','scrollbarDarkShadowColor','scrollbarFaceColor','scrollbarHighlightColor','scrollbarShadowColor','scrollbarTrackColor','scrollbars','scrolling','search','sectionRowIndex','security','securityPolicy','seek','select','selectable','selectableContent','selected','selectedIndex','selection','selector','selectorText','self','send','sendAndLoad','serverString','sessionStorage','set','setActive','setAttribute','setAttributeNode','setBufferTime','setCapture','setCookie','setCursor','setDate','setDuration','setExpression','setFocus','setFps','setFullYear','setGain','setHotKeys','setHours','setInterval','setKeyFrameInterval','setLoopback','setMask','setMilliseconds','setMinutes','setMode','setMonth','setMotionLevel','setNamedItem','setNewTextFormat','setPan','setPosition','setProperty','setQuality','setRGB','setRate','setRequestHeader','setResizable','setSeconds','setSelection','setSilenceLevel','setTextFormat','setTime','setTimeout','setTransform','setUTCDate','setUTCFullYear','setUTCHours','setUTCMilliseconds','setUTCMinutes','setUTCMonth','setUTCSeconds','setUseEchoSuppression','setVolume','setYear','setZOptions','shape','shift','shiftKey','shiftLeft','short','show','showHelp','showMenu','showModalDialog','showModelessDialog','siblingAbove','siblingBelow','sidebar','signText','sin','size','sizeToContent','slice','small','some','sort','sortOn','source','sourceIndex','span','specified','splice','split','splitText','sqrt','src','srcElement','srcFilter','srcUrn','stack','standby','start','startDrag','static','status','statusText','statusbar','stop','stopAllSounds','stopDrag','strike','stringify','style','styleFloat','styleSheet','styleSheets','sub','submit','substr','substring','substringData','suffixes','summary','sun','sup','super','swapDepths','swapNode','switch','synchronized','systemLanguage','systemXDPI','systemYDPI','tBodies','tFoot','tHead','tabChildren','tabEnabled','tabIndex','tabStop','tabStops','table','tableLayout','tagName','tagUrn','tags','taint','taintEnabled','tan','target','targetPath','tellTarget','test','text','textAlign','textAlignLast','textAutospace','textColor','textDecoration','textDecorationBlink','textDecorationLineThrough','textDecorationNone','textDecorationOverline','textDecorationUnderline','textHeight','textIndent','textJustify','textKashidaSpace','textOverflow','textTransform','textUnderlinePosition','textWidth','textarea','this','throw','throws','timeout','title','toArray','toISOString','toDateString','toElement','toExponential','toFixed','toGMTString','toJSON','toLocaleDateString','toLocaleLowerCase','toLocaleString','toLocaleTimeString','toLocaleUpperCase','toLowerCase','toPrecision','toSource','toString','toTimeString','toUTCString','toUpperCase','toggleHighQuality','toolbar','top','topMargin','trace','trackAsMenu','transient','trim','trimLeft','trimRight','trueSpeed','try','type','typeDetail','typeof','ubound','undefined','underline','unescape','unicodeBidi','uninstall','uniqueID','units','unload','unloadMovie','unloadMovieNum','unshift','untaint','unwatch','updateAfterEvent','updateCommands','updateInterval','url','urn','urns','useHandCursor','useMap','userAgent','userLanguage','userProfile','vAlign','vLink','vLinkcolor','value','valueOf','valueType','var','variable','vcard_name','vendor','vendorSub','version','verticalAlign','viewInheritStyle','viewLink','viewLinkContent','viewMasterTab','visibility','vlinkColor','void','volatile','volume','vrml','vspace','watch','wheelDelta','while','whiteSpace','widows','width','window','with','wordBreak','wordSpacing','wordWrap','wrap','write','writeln','writingMode','x','xmlDecl','y','zIndex','zoom'];
			var props = [];
			for(var i=0;i<jsBuiltInProps.length;i++) {
				try {
					eval("if(obj.function::[jsBuiltInProps[i]]) {props.push(jsBuiltInProps[i]);}");
				} catch(e){}
			}
			this.settings.output.value = props;
		}
		this.testHTML = function(optContent, innerHTML) {
		   this.settings.preview.style.display = 'block';
		   this.settings.source.style.display = 'block';
		   var ifrm = this.settings.iframe.contentWindow.document;			   			  
		   ifrm.open();
		    if(optContent == null) {
		    	var code = this.settings.output.value;
		    	if(window.localStorage) {
					var history = localStorage.getItem("codeHistory");
					if(history === null) {
						localStorage.setItem("codeHistory", encodeURIComponent(code).replace(/'/g,'%27'));
					} else {
						history = history+','+encodeURIComponent(code).replace(/'/g,'%27');
						localStorage.setItem("codeHistory", history);
					}
				}
		    	if(!innerHTML) {
		    		ifrm.writeln('' + code);
		    		this.settings.sourceCode.innerHTML = this.encodeForPreview(code);
		    	}
		    } else {
				if(!innerHTML) {
					ifrm.writeln('' + optContent);
					this.settings.sourceCode.innerHTML = this.encodeForPreview(optContent);
				}
			}
			ifrm.close();
			if(innerHTML) {
				ifrm.body.innerHTML = optContent;
				this.settings.sourceCode.innerHTML = this.encodeForPreview(optContent);
			}
		}
		this.closePreview = function() {
			this.settings.preview.style.display = 'none';
			this.settings.source.style.display = 'none';
			clearInterval(window.toStaticTimer);
		}
		this.closeSource = function() {
			this.settings.source.style.display = 'none';
			this.settings.preview.style.display = 'none';
			clearInterval(window.toStaticTimer);
		}
		this.saveStorage = function(code) {			
			if(window.localStorage) {
				var history = localStorage.getItem("codeHistory");
				if(history === null) {
					localStorage.setItem("codeHistory", encodeURIComponent(code).replace(/'/g,'%27'));
				} else {										
					history = history+','+encodeURIComponent(code).replace(/'/g,'%27');
					localStorage.setItem("codeHistory", history);
				}
			}
		}
		this.testString = function(fresh,alertOutput) {
			var code = this.settings.output.value;
			this.clearErrors();
			if(code == '') {
				return false;
			}
			
			this.saveStorage(code);
			
			if(fresh) {
				this.testHTML("<script>function run() { var code=top.Hackvertor.settings.output.value; try {try { throw new Error() } catch(ex) { relativeLineNumber = ex.lineNumber }	evalResult = eval(code);return evalResult;	} catch(ex) {error = ex.message+' (line '+(ex.lineNumber - relativeLineNumber)+')';top.Hackvertor.sendError(error);} }run();<\/script>");
				return null;
			}
			
			try {
				try { throw new Error() } catch(ex) { relativeLineNumber = ex.lineNumber }				
					evalResult = eval(code);					
					if(alertOutput) {					
						alert('Result:\n'+evalResult + '\nType:\n' + typeof evalResult);
					}
					return evalResult;				
			} catch(ex) {
				error = ex.message+' (line '+(ex.lineNumber - relativeLineNumber)+')';
				this.sendError(error);
			}	
		}
		this.sendError = function(error) {
			var errorConsole = this.settings.errorConsole;
			errorConsole.style.display = 'block';
			errorConsole.innerHTML = error;
		}
		this.clearErrors = function() {
			var errorConsole = this.settings.errorConsole;
			errorConsole.innerHTML = '';
			errorConsole.style.display = 'none';
		}
		this.addHVURL = function(obj) {
			if(typeof this.hvurls[obj.userID] == 'undefined') {
				this.hvurls[obj.userID] = [];
			} 			
			this.hvurls[obj.userID].push({hvurlID:obj.hvurlID,description:obj.description});			
		}
		this.domScratch = function() {
			this.settings.preview.style.display = 'block';
			this.settings.preview.style.width = '95%';
			this.settings.preview.style.height = '95%';
			this.settings.preview.style.left = '0';
			this.settings.preview.style.top = '0';
			var ifrm = this.settings.iframe.contentWindow.document;			   			  
			ifrm.open();
			ifrm.write('<!doctype html><html><head><meta http-equiv="Content-Type" content="text/xhtml;charset=utf-8" /><style>#canvas, #canvas2, #html, #log {width:100%;height:190px;overflow-y:scroll}</style></head><body><textarea id="html"></textarea><hr /><div id="canvas"></div><hr /><textarea id="log"></textarea><hr /><div id="canvas2"></div><script>var html = document.getElementById(\'html\');var log = document.getElementById(\'log\');var canvas = document.getElementById(\'canvas\');var canvas2 = document.getElementById(\'canvas2\');var updateCanvas = function(){canvas.innerHTML=html.value;log.value=canvas.innerHTML;canvas2.innerHTML=canvas.innerHTML;};html.onblur=function(){ top.Hackvertor.saveStorage(html.value); };html.onkeyup = updateCanvas;window.onload = updateCanvas;<\/script></body></html>');
			ifrm.close();						
		}
		this.inspectHTML = function() {
			if(document.getElementById('output').value) {
				this.saveStorage(document.getElementById('output').value);
			}
			DOM.innerHTML = '';
			DOM.innerHTML = document.getElementById('output').value;		
			astalanumerator.run('document.getElementById(\'DOM\').firstChild');
		}
		this.loadHvurls = function(userID) {
			this.clearSelect(document.getElementById('savedHvurls'));
			var urls = this.hvurls[userID];
			if(typeof urls != 'undefined') {
				for(var i=0;i<urls.length;i++) {
					var obj = urls[i];			
					this.appendSelect(document.getElementById('savedHvurls'), obj.hvurlID, obj.description);				
				}
			}
		}
		this.hackvertlet = function() {
			var input = this.settings.input;
			if(input.value == '') {
				input.value = 'Hackvertlet';
				this.selectInput();
			} else {
				var hackvertletName = prompt('Please enter a name for your Hackvertlet');
				if(hackvertletName == null) {
					return false;
				}
				self.location = 'data:text/html,<p>Drag the link below to your bookmarks</p><a href="javascript:txt=document.getSelection();self.location=\'https://hackvertor.co.uk/home#\'+encodeURIComponent(btoa(atob(\''+btoa(input.value)+'\').replace(/Hackvertlet/g,txt)));">'+hackvertletName.replace(/[^!. a-zA-Z0-9_\-]/g,'')+'</a>';
			}
		}
		this.checkHistory = function() {			
			if(window.localStorage) {
				this.history = localStorage.getItem("codeHistory").split(",");									
			}			
			if(this.historyPos === null && this.history.length) {	
				this.historyPos = this.history.length;
			} 										
		}
		this.historyClear = function() {
			if(window.localStorage) {
				localStorage.clear();
			}
		}
		this.historyStart = function() {
			this.checkHistory();									
			this.settings.output.value = decodeURIComponent(this.history[0]);
			this.historyPos = 0;
		}
		this.historyEnd = function() {			
			this.checkHistory();											
			this.settings.output.value = decodeURIComponent(this.history[this.history.length-1]);
			this.historyPos = this.history.length-1;
		}
		this.historyBack = function() {			
			this.checkHistory();					
			if(this.historyPos !== null && this.historyPos > 0) {				
				this.settings.output.value = decodeURIComponent(this.history[--this.historyPos]);				
			}
		}
		this.historyForward = function() {			
			this.checkHistory();
			if(this.historyPos !== null && this.historyPos + 1 < this.history.length) {									
				this.settings.output.value = decodeURIComponent(this.history[++this.historyPos]);				
			}
		}
		this.scanTags = function() {
			var tagsList = ['video','time','source','section','rule','progress','output','nest','nav','meter','m','header','footer','figure','event-source','datatemplate','datalist','datagrid','command','colgroup','canvas','audio','aside','article','embed','a','abbr','acronym','address','applet','area','b','base','bdo','big','body','br','button','caption','center','cite','code','col','dd','del','dfn','dir','div','dl','dt','em','font','form','frame','h1','h2','h3','h4','h5','h6','head','hr','html','i','iframe','img','input','ins','isindex','kbd','label','legend','li','link','map','menu','meta','object','ol','option','p','param','pre','q','s','samp','script','select','small','span','strike','strong','style','sub','sup','table','tbody','td','tfoot','th','thead','title','tr','tt','u','ul','var','blink','marquee','!doctype','basefont','bgsound','blockquote','fieldset','frameset','ilayer','image','keygen','listing','multicol','nobr','noembed','noframes','noscript','nolayer','optgroup','rb','rbc','rp','rtc','rt','ruby','spacer','textarea','wbr','xml','xmp'].sort(),
				val = this.settings.output.value, i, tag, found = [];			
			for(i=0;i<tagsList.length;i++) {
				tag = tagsList[i];
				try {
					if(document.createElement(tag)[val] !== undefined) {
						found.push(tag);
					}
				} catch(e){}
			}
			this.settings.output.value = found;
		}
		this.propertyFuzzer = function() {
			var html = '<!doctype html><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><\/head><body>';
			html += '<script>self.results=[];<\/script>';
			html += '<script>window.onload=function(){if(self.results.length) {top.document.getElementById("output").value = self.results.join(",");} else {top.document.getElementById("output").value = "No results found.";}}<\/script>';
			for(var i=1;i<0xffff;i++) {								
				html += '<script>if(typeof self["alert'+String.fromCharCode(i)+'"]=="function"){results.push('+i+')}<\/script>';				
			}	
			html += '<script>if(typeof self["alert'+String.fromCharCode(0)+'"]=="function"){results.push('+0+')}<\/script><\/body><\/html>';
			var ifrm = this.settings.iframe.contentWindow.document;			   			  
			ifrm.open();
			ifrm.write(html);
			ifrm.close();
		}
		this.tagFuzzer = function() {
			var tagsList = ['video','time','source','section','rule','progress','output','nest','nav','meter','m','header','footer','figure','event-source','datatemplate','datalist','datagrid','command','colgroup','canvas','audio','aside','article','embed','a','abbr','acronym','address','applet','area','b','base','bdo','big','body','br','button','caption','center','cite','code','col','dd','del','dfn','dir','div','dl','dt','em','font','form','frame','h1','h2','h3','h4','h5','h6','head','hr','html','i','iframe','img','input','ins','isindex','kbd','label','legend','li','link','map','menu','meta','object','ol','option','p','param','pre','q','s','samp','script','select','small','span','strike','strong','style','sub','sup','table','tbody','td','tfoot','th','thead','title','tr','tt','u','ul','var','blink','marquee','!doctype','basefont','bgsound','blockquote','fieldset','frameset','ilayer','image','keygen','listing','multicol','nobr','noembed','noframes','noscript','nolayer','optgroup','rb','rbc','rp','rtc','rt','ruby','spacer','textarea','wbr','xml','xmp'].sort(),
				attributes = ['onfocus','onstart','poster','onload','onerror','onreadystatechange','data','href','src','background','DYNSRC','LOWSRC'], html = '', tag, i, j,
				ifrm = this.settings.iframe.contentWindow.document;	
			html = '<script>logged = {};results = [];function logResults(tag, attribute){ if(logged[tag+""+attribute]){return false;};results.push({tag:tag,attribute:attribute});logged[tag+""+attribute]=1; }<\/script>';					
			html += '<div id="container"></div>';
			html += '<div style="position:absolute;left:-5000px;">';
			for(i=0;i<tagsList.length;i++) {
				tag = tagsList[i];
				html += '\'"><'+tag + ' type="text/javascript"';
				for(j=0;j<attributes.length;j++) {
					if(attributes[j] === 'src' && tag === 'iframe') {
						html += ' ' + attributes[j] + '="javascript:parent.logResults('+i+','+j+')"';
					} else {
						html += ' ' + attributes[j] + '="javascript:logResults('+i+','+j+')"';
					}
				}
				html += '>test'+'</'+tag+'>';
				/*
				html += '\'"><'+tag + ' type="text/html"';
				for(j=0;j<attributes.length;j++) {
					if(/^on/.test(attributes[j])) {
						continue;
					}
					html += ' ' + attributes[j] + '="data:text/html,<script>parent.logResults('+i+','+j+')<\/script>"';					
				}
				html += '>test'+'</'+tag+'>';
				*/
			}			
			html += '</div>';
			html += "<script>window.onload=function(){ var html = '', tagsList = '"+tagsList.join(',')+"'.split(','),attributes = '"+attributes.join(',')+"'.split(',');html += '<style>*{font-size:12px;font-family: \"Lucida Grande\", verdana, arial, helvetica, sans-serif;}table {width:100%;}td{border:1px solid #ccc;}th{text-align:left;background-color:#}tr.row1{background-color:#EDF6F7;}tr.row2{background-color:#EDF1F7;}</style>';html += '<table><tr class=\"row1\"><th>Tag</th><th>Attribute</th></tr>';for(var i=0;i<results.length;i++){ html+='<tr class=\"row2\"><td>'+tagsList[results[i].tag]+'</td><td>'+attributes[results[i].attribute]+'</td></tr>'; };html+='</table>';setTimeout(function(html) { return function(){ document.getElementById('container').innerHTML=html; } }(html), 500); }<\/script>";					   			  		
			ifrm.write(html);
			ifrm.close();					
			this.settings.preview.style.width = '80%';
			this.settings.preview.style.height = '80%';
			this.settings.preview.style.display = 'block';
			
		}
		this.urlFuzzer = function() {
			var a = document.createElement('a'), html = '', i,
				beforeSlashes = [], middleSlashes = [], afterSlashes = [], 
				middleHttp = [], oneSlash = [], noSlashes = [], beforeHttp = [], afterHttp = [], 
				beforeColon = [], middleJavascript = [], startJavascript = [],
				beforeFile = [], repeatedFile = [], beforeColonFile = [], beforeSemi = [], beforeEntColon = [];
			html += '<style>textarea{width:350px;height:100px;}*{font-size:12px;font-family: "Lucida Grande", verdana, arial, helvetica, sans-serif;}table {width:100%;}td{border:1px solid #ccc;}th{text-align:left;background-color:#}tr.row1{background-color:#EDF6F7;}tr.row2{background-color:#EDF1F7;}</style>';
			html += '<table>';
			html += '<tr class="row1">';			
			html += '<th>Type</th>';
			html += '<th>Position</th>';
			html += '<th>Sample</th>';
			html += '<th>Chars</th>';
			html += '</tr>';
			for(i=0;i<0xffff;i++) {	
				try {
					a.href=String.fromCharCode(i)+'//x';
					if(a.host === 'x') {
						beforeSlashes.push(i);
					}
					a.href='/'+String.fromCharCode(i)+'/x';
					if(a.host === 'x') {
						middleSlashes.push(i);
					}
					a.href='//'+String.fromCharCode(i)+'x';
					if(a.host === 'x') {
						afterSlashes.push(i);
					}
					a.href='http:/'+String.fromCharCode(i)+'x';
					if(a.host === 'x') {
						oneSlash.push(i);
					}
					a.href='http:'+String.fromCharCode(i)+'x';
					if(a.host === 'x') {
						noSlashes.push(i);
					}
					a.href=''+String.fromCharCode(i)+'http://x';
					if(a.host === 'x') {
						beforeHttp.push(i);
					}
					a.href='http://'+String.fromCharCode(i)+'x';
					if(a.host === 'x') {
						afterHttp.push(i);
					}
					a.href='http:/'+String.fromCharCode(i)+'/x';
					if(a.host === 'x') {
						middleHttp.push(i);
					}									
					a.href=''+String.fromCharCode(i)+'file://x';
					if(a.protocol === 'file:') {
						beforeFile.push(i);
					}
					a.href=''+String.fromCharCode(i)+'://x';
					if(a.protocol === 'file:') {
						beforeColonFile.push(i);
					}
					a.href = String.fromCharCode(i)+String.fromCharCode(i)+'/x';
					if(a.protocol === 'file:') {
						repeatedFile.push(i);
					}
					
					a.href='javascript'+String.fromCharCode(i)+':';
					if(a.protocol === 'javascript:') {
						beforeColon.push(i);
					}
					a.href='javas'+String.fromCharCode(i)+'cript:';
					if(a.protocol === 'javascript:') {
						middleJavascript.push(i);
					}
					a.href=''+String.fromCharCode(i)+'javascript:';
					if(a.protocol === 'javascript:') {
						startJavascript.push(i);
					}
					try {						
						var span=document.createElement('span');
						span.innerHTML='<a href="javascript&colon'+String.fromCharCode(i)+';">test</a>';						
						if(span.firstChild.protocol === 'javascript:') {
							beforeSemi.push(i);
						}
						span.innerHTML='<a href="javascript&'+String.fromCharCode(i)+'colon;">test</a>';						
						if(span.firstChild.protocol === 'javascript:') {
							beforeEntColon.push(i);
						}
					} catch(e){};					
					
				} catch(e) {}
			}
			html += '<tr class="row2">';
			html += '<td>//</td>';
			html += '<td>Before slashes</td>';
			html += '<td>CHAR//</td>';
			html += '<td><textarea>'+beforeSlashes.join(',')+'</textarea></td>';
			html += '</tr>';
			html += '<tr class="row2">';
			html += '<td>//</td>';
			html += '<td>Middle of slashes</td>';
			html += '<td>/CHAR/</td>';
			html += '<td><textarea>'+middleSlashes.join(',')+'</textarea></td>';
			html += '</tr>';
			html += '<tr class="row2">';
			html += '<td>//</td>';
			html += '<td>After slashes</td>';
			html += '<td>//CHAR</td>';
			html += '<td><textarea>'+afterSlashes.join(',')+'</textarea></td>';
			html += '</tr>';
			html += '<tr class="row2">';
			html += '<td>http:</td>';
			html += '<td>One slash</td>';
			html += '<td>http:/CHAR</td>';
			html += '<td><textarea>'+oneSlash.join(',')+'</textarea></td>';
			html += '</tr>';
			html += '<tr class="row2">';
			html += '<td>http:</td>';
			html += '<td>No slashes</td>';
			html += '<td>http:CHAR</td>';
			html += '<td><textarea>'+noSlashes.join(',')+'</textarea></td>';
			html += '</tr>';
			html += '<tr class="row2">';
			html += '<td>http:</td>';
			html += '<td>Before http</td>';
			html += '<td>CHARhttp://</td>';
			html += '<td><textarea>'+beforeHttp.join(',')+'</textarea></td>';
			html += '</tr>';
			html += '<tr class="row2">';
			html += '<td>http:</td>';
			html += '<td>After http</td>';
			html += '<td>http://CHAR</td>';
			html += '<td><textarea>'+afterHttp.join(',')+'</textarea></td>';
			html += '</tr>';
			html += '<tr class="row2">';
			html += '<td>http:</td>';
			html += '<td>Middle http slashes</td>';
			html += '<td>http:/CHAR/</td>';
			html += '<td><textarea>'+middleHttp.join(',')+'</textarea></td>';
			html += '</tr>';
								
			html += '<tr class="row2">';
			html += '<td>file:</td>';
			html += '<td>Before colon:</td>';
			html += '<td>CHAR:</td>';
			html += '<td><textarea>'+beforeColonFile.join(',')+'</textarea></td>';
			html += '</tr>';
			html += '<tr class="row2">';
			html += '<td>file:</td>';
			html += '<td>Before file:</td>';
			html += '<td>CHARfile://</td>';
			html += '<td><textarea>'+beforeFile.join(',')+'</textarea></td>';
			html += '</tr>';		
			html += '<tr class="row2">';
			html += '<td>file:</td>';
			html += '<td>Two characters</td>';
			html += '<td>CHARCHAR/</td>';
			html += '<td><textarea>'+repeatedFile.join(',')+'</textarea></td>';
			html += '</tr>';
			
			html += '<tr class="row2">';
			html += '<td>javascript:</td>';
			html += '<td>Before Colon</td>';
			html += '<td>javascriptCHAR:</td>';
			html += '<td><textarea>'+beforeColon.join(',')+'</textarea></td>';
			html += '</tr>';
			html += '<tr class="row2">';
			html += '<td>javascript:</td>';
			html += '<td>Middle of javascript</td>';
			html += '<td>javasCHARcript:</td>';
			html += '<td><textarea>'+middleJavascript.join(',')+'</textarea></td>';
			html += '</tr>';
			html += '<tr class="row2">';
			html += '<td>javascript:</td>';
			html += '<td>Start of javascript</td>';
			html += '<td>CHARjavascript:</td>';
			html += '<td><textarea>'+startJavascript.join(',')+'</textarea></td>';			
			html += '</tr>';
			html += '<tr class="row1">';
			html += '<td>javascript&amp;colon;</td>';
			html += '<td>Before semi-colon of &amp;colon;</td>';
			html += '<td>javascript&amp;colonCHAR;</td>';
			html += '<td><textarea>'+beforeSemi.join(',')+'</textarea></td>';			
			html += '</tr>';
			html += '<tr class="row2">';
			html += '<td>javascript&amp;colon;</td>';
			html += '<td>Before c of &amp;colon;</td>';
			html += '<td>javascript&amp;CHARcolon;</td>';
			html += '<td><textarea>'+beforeEntColon.join(',')+'</textarea></td>';			
			html += '</tr>';
			html += '</table>';
			var ifrm = this.settings.iframe.contentWindow.document;			   			  
			ifrm.open();
			ifrm.writeln(html);
			ifrm.close();			
			this.settings.preview.style.width = '80%';
			this.settings.preview.style.height = '80%';
			this.settings.preview.style.display = 'block';			
		}
		this.jsCheck = function() {
			var response = '';	
			response += '---RegEx flags---\n';
			for(var i=0;i<0xffff;i++) {
				try {
					eval("new RegExp('a','"+String.fromCharCode(i)+"');");
					response += String.fromCharCode(i)+'\n';
				} catch(e){}
			}
			response += '---Use strict---\n';
			(function(){				
				"use strict";
				try {
					eval("with({}){}");
					response += 'with:' + true+'\n';
				} catch(e){
					response += 'with:' + false+'\n';
				}
				try {
					eval("x=1");
					response += 'eval can assign:' + true+'\n';
				} catch(e){
					response += 'eval can assign:' + false+'\n';
				}
				
				response += 'this is:' + (function(){ "use strict";return this; })()+'\n';
				response += 'this call is:' + (function(){ "use strict";return this; }).call()+'\n';
				response += 'this apply is:' + (function(){ "use strict";return this; }).apply()+'\n';
				try {
					eval("({a:1,a:1})");
					response += 'duplicate object props:' + true+'\n';
				} catch(e){
					response += 'duplicate object props:' + false+'\n';
				}
				try {
					eval('(function(){ "use strict";arguments.callee; })();');
					response += 'arguments.callee:' + true+'\n';
				} catch(e){
					response += 'arguments.callee:' + false+'\n';
				}
				try {
					eval('(function(){ "use strict";arguments.caller; })();');
					response += 'arguments.caller:' + true+'\n';
				} catch(e){
					response += 'arguments.caller:' + false+'\n';
				}
				try {
					response += 'octals:' + eval('(function(){ "use strict";return 010!==10; })()')+'\n';
				} catch(e) {
					response += 'octals:false';
				}
				
				try {
					response += eval('(function(){ "use strict";function x(){};delete x;})()')+'\n';										
					response += 'delete on variables/func:' + true+'\n';
				} catch(e){
					response += 'delete on variables/func:' + false+'\n';
				}
				
			})();
			response += '---E4X---\n';
			response += 'Variables:';
			try {
				eval('x=<test></test>');
				response += 'true';
			} catch(e) {
				response += 'false';
			}
			response +='\n';
			response += 'Inline:';
			try {
				eval('<test></test>');
				response += 'true';
			} catch(e) {
				response += 'false';
			}
			response +='\n';				
			response += '---Variables---\n';	
			response += 'constants:';
			try {
				eval("const XXYYZZ=1;");
				response += 'true';
			} catch(e) {
				response += 'false';
			}
			response += '\n';
			response += '---Objects---\n';		
			response += '.create:' + (Object.create?true:false)+'\n';
			response += '.preventExtensions:' + (Object.preventExtensions?true:false)+'\n';
			response += '.seal:' + (Object.seal?true:false)+'\n';
			response += '.isSealed:' + (Object.isSealed?true:false)+'\n';
			response += '.freeze:' + (Object.freeze?true:false)+'\n';
			response += '.isFrozen:' + (Object.isFrozen?true:false)+'\n';
			response += '.isExtensible:' + (Object.isExtensible?true:false)+'\n';
			response += '.getOwnPropertyDescriptor:' + (Object.getOwnPropertyDescriptor?true:false)+'\n';
			response += '.keys:' + (Object.keys?true:false)+'\n';
			response += '.valueOf:' + (({}).valueOf?true:false)+'\n';
			response += '.toSource:' + (({}).toSource?true:false)+'\n';
			response += '.toString:' + (({}).toString?true:false)+'\n';								
			response += '---Functions---\n';
			response += '.name:' + ((function x(){}).name?true:false)+'\n';
			response += '.callee:' + ((function(){ try {return arguments.callee ? true : false;}catch(e){return false;} })())+'\n';				
			response += '.caller:' + ((function(){ try {return arguments.callee.caller ? true : false;}catch(e){return false;} })())+'\n';
			response += 'unicode encoding:';
			try {
				eval("function x(){};\\u0078()");
				response += 'true';
			} catch(e) {
				response += 'false';
			}							
			response += '\n';
			response += 'unicode encode parenthesis?:';
			try {
				eval("function x(){};\\u0078\\u0028\\u0029");
				response += 'true';
			} catch(e) {
				response += 'false';
			}							
			response += '\n';
			response += 'setter function x(){}:';
			try {
				eval("setter function x(){}");
				response += 'true';					
			} catch(e) {
				response += 'false';
			}
			response += '\n';
			response += 'getter function x(){}:';
			try {
				eval("getter function x(){}");
				response += 'true';					
			} catch(e) {
				response += 'false';
			}
			response += '\n';
			response += 'function get x(){}:';
			try {
				eval("function get x(){}");
				response += 'true';					
			} catch(e) {
				response += 'false';
			}
			response += '\n';				
			response += 'function set x(){}:';
			try {
				eval("function set x(){}");
				response += 'true';					
			} catch(e) {
				response += 'false';
			}
			response += '\n';																														
			response += '---Arrays---\n';				
			response += 'indexOf():' + ([].indexOf?true:false)+'\n';
			response += 'lastIndexOf():' + ([].lastIndexOf?true:false)+'\n';				
			response += 'every():' + ([].every?true:false)+'\n';
			response += 'filter():' + ([].filter?true:false)+'\n';
			response += 'forEach():' + ([].forEach?true:false)+'\n';								
			response += 'map():' + ([].map?true:false)+'\n';
			response += 'some():' + ([].some?true:false)+'\n';
			response += 'reduce():' + ([].reduce?true:false)+'\n';
			response += 'reduceRight():' + ([].reduceRight?true:false)+'\n';				
			
			response += '---Strings---\n';
			response += 'String Indexes:' + ('test'[0]=='t')+'\n';
			response += '---Getters/Setters---\n';
			response += '__defineGetter__:' + (window.__defineGetter__?true:false)+'\n';
			response += '__defineSetter__:' + (window.__defineSetter__?true:false)+'\n';				
			response += '__lookupGetter__:' + (window.__lookupGetter__?true:false)+'\n';								
			response += '__lookupSetter__:' + (window.__lookupSetter__?true:false)+'\n';
			response += 'Object.defineProperty:' + (Object.defineProperty?true:false)+'\n';
			response += 'Object.defineProperties:' + (Object.defineProperties?true:false)+'\n';
			response += '---IE specific---\n';				
			response += 'toStaticHTML():' + (window.toStaticHTML?true:false)+'\n';																
			response += '---Destructuring assignments---\n';
			response += 'Arrays:';
			try {
				eval('var a = 1;var b = 2;[a, b]=[b, a];');
				response += 'true';					
			} catch(e) {
				response += 'false';
			}
			response +='\n';		
			response += 'Assignment correct?:';									
			try {
				response += a == 2 && b == 1 ? true : false;
			} catch(e) { response += 'false'; }
			response +='\n';		
			response += '---Expression closures---\n';
			response += 'Variable:';
			try {
				eval('var x=function(x) x * x;');
				response += 'true';					
			} catch(e) {
				response += 'false';
			}	
			response +='\n';		
			response += 'Inline:';
			try {
				eval('function(x) x * x;');
				response += 'true';					
			} catch(e) {
				response += 'false';
			}						
			response +='\n';	
			response += '---DOM prototypes overwrites __syntax___---\n';
			response += 'location:';
			try {
				eval("window.__defineGetter__('location',function() { return 'Overwrite' });overwrite=location=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';

			response += 'location.hash:';
			try {
				eval("location.__defineGetter__('hash',function() { return 'Overwrite' });overwrite=location.hash=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';
			response += 'location.host:';
			try {
				eval("location.__defineGetter__('host',function() { return 'Overwrite' });overwrite=location.host=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';
			response += 'location.hostname:';
			try {
				eval("location.__defineGetter__('hostname',function() { return 'Overwrite'});overwrite=location.hostname=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';
			response += 'location.href:';
			try {
				eval("location.__defineGetter__('href',function() { return 'Overwrite' });overwrite=location.href=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';
			response += 'location.search:';
			try {
				eval("location.__defineGetter__('search',function() { return 'Overwrite' });overwrite=location.search=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';

			response += 'document.domain:';
			try {
				eval("document.__defineGetter__('domain',function() { return 'Overwrite' });overwrite=document.domain=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';

			response += 'document.referrer:';
			try {
				eval("document.__defineGetter__('referrer',function() { return 'Overwrite' });overwrite=document.referrer=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';


			response += 'document.URL:';
			try {
				eval("document.__defineGetter__('URL',function() { return 'Overwrite' });overwrite=document.URL=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';

			response += 'navigator.userAgent:';
			try {
				eval("navigator.__defineGetter__('userAgent',function() { return 'Overwrite' });overwrite=navigator.userAgent=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';

			response += '---DOM prototypes overwrites defineProperty---\n';
			response += 'location:';																								
			try {
				eval("Object.defineProperty(window,'location',{get:function(){ return 'Overwrite';}});overwrite=location=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';

			response += 'location.hash:';																								
			try {
				eval("Object.defineProperty(location,'hash',{get:function(){ return 'Overwrite';}});overwrite=location.hash=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';
			response += 'location.host:';
			try {
				eval("Object.defineProperty(location,'host',{get:function(){ return 'Overwrite';}});overwrite=location.host=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';
			response += 'location.hostname:';
			try {
				eval("Object.defineProperty(location,'hostname',{get:function(){ return 'Overwrite';}});overwrite=location.hostname=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';
			response += 'location.href:';
			try {
				eval("Object.defineProperty(location,'href',{get:function(){ return 'Overwrite';}});overwrite=location.href=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';
			response += 'location.search:';
			try {
				eval("Object.defineProperty(location,'search',{get:function(){ return 'Overwrite';}});overwrite=location.search=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';

			response += 'document.domain:';
			try {
				eval("Object.defineProperty(document,'domain',{get:function(){ return 'Overwrite';}});overwrite=document.domain=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';

			response += 'document.referrer:';
			try {
				eval("Object.defineProperty(document,'referrer',{get:function(){ return 'Overwrite';}});overwrite=document.referrer=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';


			response += 'document.URL:';
			try {
				eval("Object.defineProperty(document,'URL',{get:function(){ return 'Overwrite';}});overwrite=document.URL=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';

			response += 'navigator.userAgent:';
			try {
				eval("Object.defineProperty(navigator,'userAgent',{get:function(){ return 'Overwrite';}});overwrite=navigator.userAgent=='Overwrite'?true:false;");
			} catch(e) { overwrite = false; };
			response += ''+overwrite+'\n';
			
			window.Hackvertor.settings.output.value=response;
		}
	}			
	window.Hackvertor = new Hackvertor;	
})();
