var storelist = "";
var logform = "";
var fallback = "0";
var slidetime = 5000; // length of time per pic
var storedtime;
var myMsg;
var myBar;
var myGall;
var frontpass;

window.addEvent('domready', function() {
	myMsg = new Fx.Tween('msgbar', { property: 'opacity', link: 'chain' });
	myBar = new Fx.Tween('topbar', { property: 'opacity', link: 'chain' });
	if($('htmlcontrols')) var myMove = new Drag.Move('htmlcontrols', {
		handle: $('controlshead')
	});
	getpics();
	
});

function doajax(url, data) {
	storedtime = new Date().getTime();
	var req = new Request({
		url: url,
		method: 'post', 
		onRequest: $('fl_loading').style.display = 'block',
		onSuccess: function(response) { doresponse(url, response); }
		});
	req.send(data);
}

function upload(type) {
	if($('userid')) var extrabit = "&userid=" + $('userid').innerHTML;
	else var extrabit = "";
	if(type == "av") var dir = "cmsplus/";
	else var dir = "";
	window.open(dir + 'upload.php?type=' + type + extrabit,'','status=no,width=300,height=150,left=20,top=20,scrollbars=yes');
}
function upgall(gall) {
	var base = document.getElementsByTagName('base')[0].href;
	window.open(base + '/cmsplus/gallupload.php?gallid=' + gall,'','status=no,width=300,height=150,left=20,top=20,scrollbars=yes');
}

function showmsg(text) {
	if(typeof myMsg == "object") {
		myMsg.clearChain();
		myMsg.cancel();
		$('msgbar').innerHTML = text;
		showbar();
	}
	else setTimeout("showmsg('" + text + "')", 100);	
}

function showbar() {
	var input = $('msgbar').innerHTML;
	var classtype = "generic";
	var divided = input.split("&lt;&gt;&lt;&gt;&lt;&gt;");
	if(divided[1]) {
		$('msgbar').innerHTML = divided[1];
		classtype = divided[0];
	}
	else {
		var divided = input.split('&lt;>&lt;>&lt;>');
		if(divided[1]) {
			$('msgbar').innerHTML = divided[1];
			classtype = divided[0];
		}
	}

	$('msgbar').className = "flmsg_" + classtype;
	$('msgbar').style.display = "block";
	myMsg.set(0).start(0.9).wait(5000).start(0).chain(function() { $('msgbar').style.display = "none"; });
}
function showtopbar() {
	$('topbar').style.display = "block";
	myBar.set(0).start(0.9);
}
function hidebar() {
	myMsg.start(0).chain(function() {
		$('msgbar').style.display = "none";
		myMsg.cancel();
		myMsg.clearChain();
	});
}
function hidetopbar() {
	myBar.start(0).chain(function() {
		$('topbar').style.display = "none";
	});
}

function votechosen(radioid) {
	$('chosen').value = $(radioid).value;
}

function prepel(el) {
	el = encodeURI(el);
	el = el.replace(/&/g, "%26");
	el = el.replace(/\+/g, "%2B");
	el = el.replace(/#/g, "%23");
	return el;
}

function emailsub() {
	var name = $('mailname').value;
	var email = $('mailemail').value;
	var subject = $('mailsubject').value;
	var message = $('mailmessage').value;
	if($('mailspamcode'))	var spamcode = $('mailspamcode').value;
	else var spamcode = "";
	if($('mailto'))	var mailto = $('mailto').value;
	else var mailto = "";
	if($('tel'))	var tel = $('tel').value;
	else var tel = "";
	if(name != "" && email != "" && message != "") {
		name = prepel(name);
		email = prepel(email);
		subject = prepel(subject);
		message = prepel(message);
		mailto = prepel(mailto);
		tel = prepel(tel);
		var poststr = "name=" + name + "&email=" + email + "&subject=" + subject + "&message=" + message + "&antispam=" + spamcode + "&mailto=" + mailto + "&tel=" + tel;
		doajax('cmsplus/sendmail.php', poststr);

	}
	else {
		showmsg('alert<><><>You must enter your name, e-mail address and a message.');
	}
}

function togglelist(list) {
	storelist = list;
	var poststr = "sellist=" + encodeURI(list);
	doajax('cmsplus/listtoggle.php', poststr);
}
function pollsub() {
	var poststr = "chosen=" + encodeURI($('chosen').value);
	doajax('cmsplus/pollvote.php', poststr);
}
function reloadpoll() {
	doajax('cmsplus/pollload.php', '');
}
function reloadlist() {
	doajax('cmsplus/listload.php', 'list=' + storelist);
}

function sharelink() {
	$('topbar').style.display = "none";
	$('topcont').innerHTML = "<form method=\"post\" action=\"#\" onsubmit=\"sharinglink(); return false;\"><table align=\"center\"><tr><td>Your name:<\/td><td><input type=\"text\" class=\"fl_signinform\" name=\"yourname\" id=\"yourname\"\/><\/td><td>Your e-mail:<\/td><td><input type=\"text\" class=\"fl_signinform\" name=\"youremail\" id=\"youremail\"\/><\/td><td>Friend's e-mail:<\/td><td><input type=\"text\" class=\"fl_signinform\" name=\"theiremail\" id=\"theiremail\"\/><\/td><td><input type=\"submit\" class=\"fl_signinsub\" value=\"Send link\"\/><\/td><\/tr><\/table><\/form>";
	showtopbar();
}
function sharinglink() {
	hidetopbar();
	var poststr = "yourname=" + encodeURI($('yourname').value) + "&youremail=" + encodeURI($('youremail').value) + "&theiremail=" + encodeURI($('theiremail').value);
	doajax('cmsplus/sharelink.php', poststr);
}
function register(whatfor) {
	logform = whatfor;
	$('topbar').style.display = "none";
	$('topcont').innerHTML = "<form method=\"post\" action=\"#\" onsubmit=\"registering(); return false;\"><table align=\"center\"><tr><td>Username:<\/td><td><input type=\"text\" class=\"fl_regform\" name=\"registeruser\" id=\"registeruser\"\/><\/td><td>E-mail:<\/td><td><input type=\"text\" class=\"fl_regform\" name=\"registeremail\" id=\"registeremail\"\/><\/td><td>Password:<\/td><td><input type=\"password\" class=\"fl_regform\" name=\"registerpass\" id=\"registerpass\"\/><\/td><td>Again:<\/td><td><input type=\"password\" class=\"fl_regform\" name=\"registerpass2\" id=\"registerpass2\"\/><\/td><td><input type=\"submit\" class=\"fl_regsub\" value=\"Register\"\/><\/td><\/tr><\/table><\/form>";
	showtopbar();
}
function signin(whatfor, pass) {
	logform = whatfor;
	if(whatfor == "mailing") storelist = pass;
	$('topbar').style.display = "none";
	$('topcont').innerHTML = "<form method=\"post\" action=\"#\" onsubmit=\"encryptpass('signinpass'); loggingin(); return false;\"><table align=\"center\"><tr><td>Username:<\/td><td><input type=\"text\" class=\"fl_signinform\" name=\"signinuser\" id=\"signinuser\"\/><\/td><td>Password:<\/td><td><input type=\"password\" class=\"fl_signinform\" name=\"signinpass\" id=\"signinpass\"\/><\/td><td><input type=\"submit\" class=\"fl_signinsub\" value=\"Log in\"\/><\/td><\/tr><\/table><\/form>";
	showtopbar();
}
function signout(whatfor, pass) {
	logform = whatfor;
	if(whatfor == "mailing") storelist = pass;
	doajax('functions.php', 'logout=1');
}
function loggingin() {
	hidetopbar();
	var poststr = "mustlog=1&loginuser=" + encodeURI($('signinuser').value) + "&loginpass=" + encodeURI($('signinpass').value);

	doajax('functions.php', poststr);
}
function registering() {
	hidetopbar();
	var poststr = "registeruser=" + encodeURI($('registeruser').value) + "&registerpass=" + encodeURI($('registerpass').value) + "&registerpass2=" + encodeURI($('registerpass2').value) + "&registeremail=" + encodeURI($('registeremail').value);

	doajax('cmsplus/signup.php', poststr);
}
function reloadform() {
	if(logform == "mailing") doajax('cmsplus/listload.php', 'list=' + storelist);
	else {
		var pageid = encodeURI($('pageid').innerHTML);
		var pagetype = encodeURI($('pagetype').innerHTML);
		var poststr = "pageid=" + pageid + "&pagetype=" + pagetype;
		doajax('cmsplus/commsload.php', poststr);
	}
}
function showform() {
	if($('fl_commsform')) $('fl_commsform').style.display = "block";
	else if($('fl_guestform')) $('fl_guestform').style.display = "block";
}
function commsub(div) {
	logform = div;
	if($('commname')) var commname = encodeURI($('commname').value);
	else var commname = "";
	if($('commemail')) var commemail = encodeURI($('commemail').value);
	else var commemail = "";
	if($('commweb')) var commweb = encodeURI($('commweb').value);
	else var commweb = "";
	if($('commmessage')) var commmessage = encodeURI($('commmessage').value);
	else var commmessage = "";
	if($('commspamcode')) var commspamcode = encodeURI($('commspamcode').value);
	else var commspamcode = "";
	var pageid = encodeURI($('pageid').innerHTML);
	var pagetype = encodeURI($('pagetype').innerHTML);
	
	var poststr = "commname=" + commname + "&commemail=" + commemail + "&commweb=" + commweb + "&commmessage=" + commmessage + "&commspamcode=" + commspamcode + "&pageid=" + pageid + "&pagetype=" + pagetype;
	doajax('cmsplus/addcomment.php', poststr);

}
function reloadcomms() {
	var pageid = encodeURI($('pageid').innerHTML);
	var pagetype = encodeURI($('pagetype').innerHTML);
	var poststr = "pageid=" + pageid + "&pagetype=" + pagetype + "&reload=1"; 	doajax('cmsplus/commsload.php', poststr);
}

function forgotpass(isfront) {
	$('topbar').style.display = "none";
	$('topcont').innerHTML = "<form method=\"post\" action=\"#\" onsubmit=\"passforgot('" + isfront + "'); return false;\"><table align=\"center\"><tr><td>Username:<\/td><td><input type=\"text\" name=\"forgotuser\" class=\"fl_signinform\" id=\"forgotuser\"\/><\/td><td><b>or</b> e-mail address:<\/td><td><input type=\"text\" class=\"fl_signinform\" name=\"forgotemail\" id=\"forgotemail\"\/><\/td><td><input type=\"submit\" class=\"fl_signinsub\" value=\"Send reminder\"\/><\/td><\/tr><\/table><\/form>";
	showtopbar();
}
function changepass(isfront) {
	$('topbar').style.display = "none";
	$('topcont').innerHTML = "<form method=\"post\" action=\"#\" onsubmit=\"passchange(); return false;\"><table align=\"center\"><tr><td>Current password:<\/td><td><input type=\"password\" name=\"curpass\" class=\"fl_signinform\" id=\"curpass\"\/><\/td><td>New password:<\/td><td><input type=\"password\" class=\"fl_signinform\" name=\"newpass1\" id=\"newpass1\"\/><\/td><td>New password again:<\/td><td><input type=\"password\" name=\"newpass2\" class=\"fl_signinform\" id=\"newpass2\"\/><\/td><td><input type=\"submit\" class=\"fl_signinsub\" value=\"Save\"\/><\/td><\/tr><\/table><\/form>";
	frontpass = isfront;
	showtopbar();
}
function passchange() {
	hidetopbar();
	var curpass = prep($('curpass').value);
	var newpass1 = prep($('newpass1').value);
	var newpass2 = prep($('newpass2').value);
	var poststr = "curpass=" + curpass + "&newpass1=" + newpass1 + "&newpass2=" + newpass2;
	if(frontpass == "1") doajax("cmsplus/changepass.php", poststr);
	else doajax("changepass.php", poststr);
}
function passforgot(isfront) {
	hidetopbar();
	var forgotuser = prep($('forgotuser').value);
	var forgotemail = prep($('forgotemail').value);
	var poststr = "forgotuser=" + forgotuser + "&forgotemail=" + forgotemail;
	if(isfront == "1") doajax("cmsplus/forgotpass.php", poststr);
	else doajax("forgotpass.php", poststr);
}
function saverating(div, ratingid) {
	var rating = prep($(div).value);
	$(div).style.display = "none";
	doajax("cmsplus/rating.php", "ratingid=" + ratingid + "&rating=" + rating + "&ratingrnd=" + div);
}

function prep(text) {
	text = encodeURI(text);
	text = text.replace(/&/g, "%26");
	text = text.replace(/\+/g, "%2B");
	text = text.replace(/#/g, "%23");
	return text;
}


function doresponse(url, response) {
	$('fl_loading').style.display = "none";
	if(url == "cmsplus/pollvote.php") pollvoted(response);
	else if(url == "cmsplus/rating.php") ratingsaved(response);
	else if(url == "tags.php") tags(response);
	else if(url == "saveblog.php") blogsaved(response);
	else if(url == "saveuser.php") usersaved(response);
	else if(url == "cmsplus/pollload.php") pollloaded(response);
	else if(url == "cmsplus/listtoggle.php") listtoggle(response);
	else if(url == "cmsplus/listload.php") listloaded(response);
	else if(url == "functions.php") loginresponse(response);
	else if(url == "cmsplus/addcomment.php") commentdone(response);
	else if(url == "cmsplus/commsload.php") commentsloaded(response);
	else if(url == "store-newimage.php") imageloaded(response);
	else showmessage(response);
}

function showmessage(response) {
	if($('userconflink')) {
		if(response.indexOf("success") != -1) $('userconflink').style.display = "none";
	}
	if($('mailname')) {
		if(response.indexOf("success") != -1) {
			$('mailname').value = "";
			$('mailemail').value = "";
			$('mailsubject').value = "";
			$('mailmessage').value = "";
			if($('mailspamcode')) $('mailspamcode').value = "";
		}
	}
	showmsg(response);
}
function pollvoted(response) {
	showmsg(response);
	reloadpoll();
}

function ratingsaved(response) {
	var resp = response.split("????");
	if(resp[0]) {
		$("rating_" + resp[0]).innerHTML = resp[1];
		showmsg(resp[2]);
	}
	else showmsg(response);
}
function commentdone(response) {
	var resp = response.split("????");
	if(resp[0] == "3") {
		if($('commname')) $('commname').value = "";
		if($('commmessage')) $('commmessage').value = "";
		if($('commspamcode')) $('commspamcode').value = "";
		reloadcomms();
		showmsg(resp[1]);
	}
	else showmsg(resp[1]);
}
function listtoggle(response) {
	showmsg(response);
	reloadlist();
}
function loginresponse(response) {
	showmsg(response);
	reloadform();
}
function replaceform(response) {
	$(logform).innerHTML = response;
}
function pollloaded(response) {
	$('fl_pollbox').innerHTML = response;
}
function listloaded(response) {
	$('fl_mailing').innerHTML = response;
}
function commentsloaded(response) {
	var resp = response.split("????");
	$(resp[0]).innerHTML = resp[1];
}

// Gallery slideshow stuff

var gall = new Array();
var thumbs = new Array();
var slideon = 0;
var forceslide = 0;
var slideshow;
var picid = 0;

function getpics() {
	gall = document.images;
	var curid;
	for(var i = 0; i < gall.length; i++) {
		if(gall[i].getAttribute('rel')) {
			if(gall[i].getAttribute('rel') == "fl_gall") {
				thumbs[thumbs.length] = gall[i];
				if(!gall[i].parentNode.id) gall[i].parentNode.id = "flpic_" + picid;
				curid = gall[i].parentNode.id;
				picid++;
				$(curid).addEvent('click', function(event) {
					event.preventDefault? event.preventDefault() : event.returnValue = false;
					attachimage(this);
				});
			}
		}
	}
	if(thumbs.length > 0) {
		var gallery = document.createElement('div');
		gallery.id = "fl_gallwrap";
		gallery.innerHTML = "<div id=\"fl_gallcover\"><\/div><div id=\"fl_gallbox\"><img src=\"gfx/lightbox/loading.gif\" id=\"fl_gallpic\" alt=\"*\"\/><a href=\"#\" id=\"fl_gallprev\" title=\"Previous (P, Left arrow)\"><img src=\"gfx/lightbox/prevlabel.gif\" alt=\"Prev\"\/><\/a> <a href=\"#\" id=\"fl_gallnext\" title=\"Next (N, Right arrow)\"><img src=\"gfx/lightbox/nextlabel.gif\" alt=\"Next\"\/><\/a><div id=\"fl_gallbelowpic\"><a href=\"#\" id=\"fl_gallclose\" title=\"Close (X, Esc)\"><img src=\"gfx/lightbox/closelabel.gif\" alt=\"Close\"\/><\/a><div id=\"fl_gallcaption\"><\/div> <a href=\"#\" id=\"fl_gallslide\" title=\"Toggle slideshow (S)\">Start slideshow<\/a><div style=\"clear: both;\"><\/div><\/div><\/div>";
		document.body.appendChild(gallery);
		myGall = new Fx.Tween('fl_gallwrap', { 
			property: 'opacity',
			duration: 300,
			link: 'cancel'
		});
		
		$('fl_gallcover').addEvent('click', hidebox);
		$('fl_gallclose').addEvent('click', hidebox);
		$('fl_gallprev').addEvent('click', loadprev);
		$('fl_gallnext').addEvent('click', loadnext);
		$('fl_gallslide').addEvent('click', doslideshow);
		window.addEvent('keydown', function(event) {
			if(event.key == "c" || event.key == "x" || event.key == "esc") hidebox(event);
			else if(event.key == "p" || event.key == "left") moveimg('p');
			else if(event.key == "n" || event.key == "right") moveimg('n');
			else if(event.key == "s") doslideshow(event);
		});
	
	}
	
}
function attachimage(el) {
	var thumb = el.firstChild.src;
	loadbox(thumb);
}
function loadprev(e) { 
	e=e||event; 
	e.preventDefault? e.preventDefault() : e.returnValue = false;
	moveimg("p");
}
function loadnext(e) { 
	e=e||event; 
	e.preventDefault? e.preventDefault() : e.returnValue = false;
	moveimg("n");
}
function moveimg(mode) {
	if($('fl_gallwrap').style.display == "block") {

		var img = $('fl_gallpic').src.replace(/\/pictures\//, "\/thumbnails\/");
		img = img.replace(/.jpg/g, ".png");
		for(var i = 0; i < thumbs.length; i++) {
			if(thumbs[i].src == img) var curpos = i;
		}
		if(mode == "p") {
			if(curpos != 0) loadbox(thumbs[curpos - 1].src);
		}
		if(mode == "n") {
			if(curpos != thumbs.length - 1) loadbox(thumbs[curpos + 1].src);
			else clearInterval(slideshow);
		}
	
	}

}

function doslideshow(e) {
	e=e||event; 
	e.preventDefault? e.preventDefault() : e.returnValue = false;
	if($('fl_gallwrap').style.display == "block") {
		if(slideon == 0) {
			if($('fl_gallnext').style.display == "none") {
				loadbox(thumbs[0].src);
				forceslide = 1;
			}
			else {
				slideon = 1;
				slideshow = setInterval("moveimg('n')", slidetime);
				$('fl_gallslide').innerHTML = "Stop slideshow";
			}
		}
		else {
			clearInterval(slideshow);
			$('fl_gallslide').innerHTML = "Start slideshow";
		}
	}
}

function loadbox(thumb) {
	if($('fl_gallwrap').style.display != "block") {
		$('fl_gallwrap').style.display = "block";
		myGall.set(0).start(1);
	}

	var prevok = 0;
	var nextok = 0;
	for(var i = 0; i < thumbs.length; i++) {
		if(thumbs[i].src == thumb) {
			var caption = thumbs[i].alt;
			var showcaption = thumbs[i].parentNode.title;
			var useimg = i;
			if(i != 0) prevok = 1;
			if(i != thumbs.length - 1) nextok = 1;
			else {
				$('fl_gallslide').innerHTML = "Start slideshow";
				clearInterval(slideshow);
			}

		}
	}
	var myCaption = new Fx.Slide('fl_gallbelowpic');
	myCaption.slideOut('vertical').chain(function() {
	$('fl_gallprev').style.display = "none";
	$('fl_gallnext').style.display = "none";
	
		var img = thumb.replace(/\/thumbnails\//, "\/pictures\/");
		img = img.replace(/.png/g, ".jpg");
		var newimage = new Image();
		newimage.onload = function() {
			var loaded = newimage;
			dobox(loaded, caption, showcaption, prevok, nextok);
			
			if(nextok == 1) {
				var nextimg = thumbs[useimg + 1].src.replace(/\/thumbnails\//, "\/pictures\/");
				nextimg = nextimg.replace(/.png/g, ".jpg");
				var preload2 = new Image();
				preload2.src = nextimg;
			}
			if(prevok == 1) {
				var previmg = thumbs[useimg - 1].src.replace(/\/thumbnails\//, "\/pictures\/");
				previmg = previmg.replace(/.png/g, ".jpg");
				var preload1 = new Image();
				preload1.src = previmg;
			}
		}
		newimage.src = img;
	});
}

function dobox(loaded, caption, showcaption, prevok, nextok) {

	var curimg = new Image();
	curimg.src = $('fl_gallpic').src;
	var curwidth = curimg.width;
	var curheight = curimg.height;
	
	$('fl_gallpic').src = "gfx/lightbox/loading.gif";
	$('fl_gallpic').style.top = "35%";
	
	var myPic = new Fx.Morph('fl_gallbox', {
		onComplete: function() {
			$('fl_gallpic').style.top = "0";
			$('fl_gallpic').src = loaded.src;
			var myPicFade = new Fx.Tween('fl_gallpic', {
				property: 'opacity',
				duration: 300
			});
			myPicFade.set(0).start(1);

			if(prevok == 0) $('fl_gallprev').style.display = "none";
			else {
				$('fl_gallprev').style.display = "block";
				$('fl_gallprev').style.height = loaded.height + "px";
				$('fl_gallprev').style.width = loaded.width / 2 + "px";
				$('fl_gallprev').style.marginTop = loaded.height * -1 + "px";
			}
			if(nextok == 0) $('fl_gallnext').style.display = "none";
			else {
				$('fl_gallnext').style.display = "block";
				$('fl_gallnext').style.height = loaded.height + "px";
				$('fl_gallnext').style.width = loaded.width / 2 + "px";
				$('fl_gallnext').style.marginLeft = loaded.width / 2 + "px";
				$('fl_gallnext').style.marginTop = loaded.height * -1 + "px";
			}
			if(prevok == 0 && nextok == 0) $('fl_gallslide').style.display = "none";
			else $('fl_gallslide').style.display = "inline";
			$('fl_gallpic').src = loaded.src;
			
			$('fl_gallpic').alt = showcaption;
			$('fl_gallcaption').innerHTML = caption;

			$('fl_gallbelowpic').style.width = loaded.width + "px";
			$('fl_gallbelowpic').style.display = "block";
			var myCaption = new Fx.Slide('fl_gallbelowpic');
			myCaption.slideIn('vertical');

			if(forceslide == 1) {
				forceslide = 0;
				doslideshow(this);
			}
		}
	});
	
	if(curimg.width < 100) curimg.width = 100;
	if(curimg.height < 100) curimg.height = 100;
	myPic.set({
		'height': curimg.height, 
		'width': curimg.width
		}).start({
		'height': [curimg.height,loaded.height],
		'width': [curimg.width,loaded.width]
	});

}
function hidebox(e) {
	e=e||event; 
	e.preventDefault? e.preventDefault() : e.returnValue = false;

	myGall.start(0).chain(
		function() {
			$('fl_gallpic').src = "gfx/lightbox/loading.gif";
			$('fl_gallpic').style.top = "50%";
			$('fl_gallbox').style.width = "100px";
			$('fl_gallbox').style.height = "100px";
			$('fl_gallwrap').style.display = "none";
			$('fl_gallbelowpic').style.display = "none";
			$('fl_gallslide').innerHTML = "Start slideshow";
			slideon = 0;
		}
	);
}

// The code to MD5 up passwords

var x = "";
var a = "";
var b = "";
var c = "";
var d = "";
var i = "";
var olda = "";
var oldb = "";
var oldc = "";
var oldd = "";

function encryptpass(element) {
	if($('fl_loading')) $('fl_loading').style.display = 'block';
	var enteredpass = $(element).value;
	if(enteredpass != "" && (enteredpass.length != "32" || element == "loginpass")) {
		var submitpass = calcMD5(enteredpass);
		$(element).value = submitpass;
		return enteredpass;
	}
	else return false;
}

/*
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * Digest Algorithm, as defined in RFC 1321.
 * Copyright (C) Paul Johnston 1999 - 2000.
 * Updated by Greg Holt 2000 - 2001.
 * See http://pajhome.org.uk/site/legal.html for details.
 */

/*
 * Convert a 32-bit number to a hex string with ls-byte first
 */
var hex_chr = "0123456789abcdef";
function rhex(num)
{
  var str = "";
  var j = "";
  for(j = 0; j <= 3; j++)
    str += hex_chr.charAt((num >> (j * 8 + 4)) & 0x0F) +
           hex_chr.charAt((num >> (j * 8)) & 0x0F);
  return str;
}

/*
 * Convert a string to a sequence of 16-word blocks, stored as an array.
 * Append padding bits and the length, as described in the MD5 standard.
 */
function str2blks_MD5(str)
{
  var nblk = ((str.length + 8) >> 6) + 1;
  var blks = new Array(nblk * 16);
  var i = "";
  for(i = 0; i < nblk * 16; i++) blks[i] = 0;
  for(i = 0; i < str.length; i++)
    blks[i >> 2] |= str.charCodeAt(i) << ((i % 4) * 8);
  blks[i >> 2] |= 0x80 << ((i % 4) * 8);
  blks[nblk * 16 - 2] = str.length * 8;
  return blks;
}

/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally 
 * to work around bugs in some JS interpreters.
 */
function add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}

/*
 * Bitwise rotate a 32-bit number to the left
 */
function rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

/*
 * These functions implement the basic operation for each round of the
 * algorithm.
 */
function cmn(q, a, b, x, s, t)
{
  return add(rol(add(add(a, q), add(x, t)), s), b);
}
function ff(a, b, c, d, x, s, t)
{
  return cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function gg(a, b, c, d, x, s, t)
{
  return cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function hh(a, b, c, d, x, s, t)
{
  return cmn(b ^ c ^ d, a, b, x, s, t);
}
function ii(a, b, c, d, x, s, t)
{
  return cmn(c ^ (b | (~d)), a, b, x, s, t);
}

/*
 * Take a string and return the hex representation of its MD5.
 */
function calcMD5(str)
{
  x = str2blks_MD5(str);
  a =  1732584193;
  b = -271733879;
  c = -1732584194;
  d =  271733878;

  for(i = 0; i < x.length; i += 16)
  {
    olda = a;
    oldb = b;
    oldc = c;
    oldd = d;

    a = ff(a, b, c, d, x[i+ 0], 7 , -680876936);
    d = ff(d, a, b, c, x[i+ 1], 12, -389564586);
    c = ff(c, d, a, b, x[i+ 2], 17,  606105819);
    b = ff(b, c, d, a, x[i+ 3], 22, -1044525330);
    a = ff(a, b, c, d, x[i+ 4], 7 , -176418897);
    d = ff(d, a, b, c, x[i+ 5], 12,  1200080426);
    c = ff(c, d, a, b, x[i+ 6], 17, -1473231341);
    b = ff(b, c, d, a, x[i+ 7], 22, -45705983);
    a = ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
    d = ff(d, a, b, c, x[i+ 9], 12, -1958414417);
    c = ff(c, d, a, b, x[i+10], 17, -42063);
    b = ff(b, c, d, a, x[i+11], 22, -1990404162);
    a = ff(a, b, c, d, x[i+12], 7 ,  1804603682);
    d = ff(d, a, b, c, x[i+13], 12, -40341101);
    c = ff(c, d, a, b, x[i+14], 17, -1502002290);
    b = ff(b, c, d, a, x[i+15], 22,  1236535329);    

    a = gg(a, b, c, d, x[i+ 1], 5 , -165796510);
    d = gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
    c = gg(c, d, a, b, x[i+11], 14,  643717713);
    b = gg(b, c, d, a, x[i+ 0], 20, -373897302);
    a = gg(a, b, c, d, x[i+ 5], 5 , -701558691);
    d = gg(d, a, b, c, x[i+10], 9 ,  38016083);
    c = gg(c, d, a, b, x[i+15], 14, -660478335);
    b = gg(b, c, d, a, x[i+ 4], 20, -405537848);
    a = gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
    d = gg(d, a, b, c, x[i+14], 9 , -1019803690);
    c = gg(c, d, a, b, x[i+ 3], 14, -187363961);
    b = gg(b, c, d, a, x[i+ 8], 20,  1163531501);
    a = gg(a, b, c, d, x[i+13], 5 , -1444681467);
    d = gg(d, a, b, c, x[i+ 2], 9 , -51403784);
    c = gg(c, d, a, b, x[i+ 7], 14,  1735328473);
    b = gg(b, c, d, a, x[i+12], 20, -1926607734);
    
    a = hh(a, b, c, d, x[i+ 5], 4 , -378558);
    d = hh(d, a, b, c, x[i+ 8], 11, -2022574463);
    c = hh(c, d, a, b, x[i+11], 16,  1839030562);
    b = hh(b, c, d, a, x[i+14], 23, -35309556);
    a = hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
    d = hh(d, a, b, c, x[i+ 4], 11,  1272893353);
    c = hh(c, d, a, b, x[i+ 7], 16, -155497632);
    b = hh(b, c, d, a, x[i+10], 23, -1094730640);
    a = hh(a, b, c, d, x[i+13], 4 ,  681279174);
    d = hh(d, a, b, c, x[i+ 0], 11, -358537222);
    c = hh(c, d, a, b, x[i+ 3], 16, -722521979);
    b = hh(b, c, d, a, x[i+ 6], 23,  76029189);
    a = hh(a, b, c, d, x[i+ 9], 4 , -640364487);
    d = hh(d, a, b, c, x[i+12], 11, -421815835);
    c = hh(c, d, a, b, x[i+15], 16,  530742520);
    b = hh(b, c, d, a, x[i+ 2], 23, -995338651);

    a = ii(a, b, c, d, x[i+ 0], 6 , -198630844);
    d = ii(d, a, b, c, x[i+ 7], 10,  1126891415);
    c = ii(c, d, a, b, x[i+14], 15, -1416354905);
    b = ii(b, c, d, a, x[i+ 5], 21, -57434055);
    a = ii(a, b, c, d, x[i+12], 6 ,  1700485571);
    d = ii(d, a, b, c, x[i+ 3], 10, -1894986606);
    c = ii(c, d, a, b, x[i+10], 15, -1051523);
    b = ii(b, c, d, a, x[i+ 1], 21, -2054922799);
    a = ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
    d = ii(d, a, b, c, x[i+15], 10, -30611744);
    c = ii(c, d, a, b, x[i+ 6], 15, -1560198380);
    b = ii(b, c, d, a, x[i+13], 21,  1309151649);
    a = ii(a, b, c, d, x[i+ 4], 6 , -145523070);
    d = ii(d, a, b, c, x[i+11], 10, -1120210379);
    c = ii(c, d, a, b, x[i+ 2], 15,  718787259);
    b = ii(b, c, d, a, x[i+ 9], 21, -343485551);

    a = add(a, olda);
    b = add(b, oldb);
    c = add(c, oldc);
    d = add(d, oldd);
  }
  return rhex(a) + rhex(b) + rhex(c) + rhex(d);
}