﻿/*
	executeEmbeddedScripts
	
	Based on the script from the article: Javascript script execution in innerHTML: the revenge by kratorius
	
	Extended by Jeremy Bell to support document.write
	jeremy@blackoutwebdesign.com
	Blackout Entertainment Limited, New Zealand
*/

function executeEmbeddedScripts(node){
  var bSaf = (navigator.userAgent.indexOf('Safari') != -1);
  var bOpera = (navigator.userAgent.indexOf('Opera') != -1);
  var bMoz = (navigator.appName == 'Netscape');

  if (!node) return;

  /* IE wants it uppercase */
  var st = node.getElementsByTagName('SCRIPT');
  var strExec;
	var scripts = st.length;
	
	i=0;
	for(j=0;j<scripts;j++){
		
		var scriptsAtStart = st.length;
		
		if (bSaf) {
      strExec = st[i].innerHTML;
      st[i].innerHTML = "";
    } else if (bOpera) {
      strExec = st[i].text;
      st[i].text = "";
    } else if (bMoz) {
      strExec = st[i].textContent;
      st[i].textContent = "";
    } else {
      strExec = st[i].text;
      st[i].text = "";
    }
		
		// Create attribute to hold document write output
		document.getElementsByTagName('body')[0].setAttribute("docWriteOutput","");
		
		// Fix document.write statements
		strExec = fixDocWrite(strExec);
		
    try {
      eval(strExec);
// Next fails on Safari
//      var x = document.createElement("script");
//      x.type = "text/javascript";
			
      /* In IE we must use .text! */
//      if ((bSaf) || (bOpera) || (bMoz))
//        x.innerHTML = strExec;
//      else x.text = strExec;
			
//      document.getElementsByTagName("head")[0].appendChild(x);
			
			// Get position just after script
			var html = node.innerHTML;
			var pos = html.indexOf('</script>',html.indexOf(strExec))>=0
				? html.indexOf('</script>',html.indexOf(strExec))
				: html.indexOf('</SCRIPT>',html.indexOf(strExec));
			pos += String('</script>').length;
			
			// Insert document.write output
			var s = document.getElementsByTagName('body')[0].getAttribute("docWriteOutput");
			if ((s != null) && (s != '')) {
				html = html.substr(0,pos) + document.getElementsByTagName('body')[0].getAttribute("docWriteOutput") + html.substr(pos);
				node.innerHTML = html;
			}
			
			// Is the script still there or has it been replaced with other HTML
			if(scriptsAtStart==st.length){
				// Script has not been replaced
				i++;
			}
    } catch(e) {
      //alert("Script execution error: "+e);
    }
  }
}

function fixDocWrite(str){
	var replacee = 'document.write(';
	var replacer = 'document.getElementsByTagName("body")[0].setAttribute("docWriteOutput",document.getElementsByTagName("body")[0].getAttribute("docWriteOutput")+';
	while(str.indexOf(replacee)>=0){
		// Get left side
		var left = str.substr(0,str.indexOf(replacee));
		// Get position of closing bracket
		var pos = getNextScriptChar(str,(str.indexOf(replacee)+replacee.length),')');
		// Get length of middle
		var middleLength = pos - (str.indexOf(replacee)+replacee.length);
		// Get middle
		var middle = str.substr(str.indexOf(replacee)+replacee.length,middleLength);
		// Get right
		var right = str.substr(pos);
		// Rebuild string
		str = left+replacer+middle+right;
	}
	return str;
}

function getNextScriptChar(str,startingpos,char){
	var insideDoubleQuote = false;
	var insideSingleQuote = false;
	var escaped = false;
	for(j=startingpos;j<str.length;j++){
		
		if(str.charAt(j)==char&&!insideDoubleQuote&&!insideSingleQuote){ // Look for the char
			return j;
		}
		
		if(str.charAt(j)=="'"&&!escaped&&insideSingleQuote){ // Look for closing single quote
			insideSingleQuote = false;
		} else if(str.charAt(j)=="'"&&!escaped&&!insideDoubleQuote){ // Look for opening single quotes
			insideSingleQuote = true;
		}
		
		if(str.charAt(j)=='"'&&!escaped&&insideDoubleQuote){ // Look for closing double quote
			insideDoubleQuote = false;
		} else if(str.charAt(j)=='"'&&!escaped&&!insideSingleQuote){ // Look for opening double quotes
			insideDoubleQuote = true;
		}
		
		if(str.charAt(j)=='\\'&&!escaped){ // Look for escape
			escaped = true;
		} else {
			escaped = false;
		}
		
	}
	return -1;
}

