/************************************************************************
** These functions ŠLogic Pilots, 2001.
** Comments to LogicPilots, logicpilot@logicpilots.com
************************************************************************/

/************************************************************************
** _showArray(a):
** 	Array a;
** 	Returns String;
************************************************************************/
function _showArray(a){
	var s="";
	for (var prop in a){
		s += "["+prop+"]\t=\t"+a[prop]+"\n<br>";
	}
	return s;
}

/************************************************************************
** _splitOn(s,sep):
** 	String s;
** 	String sep;
** 	Returns Array();
************************************************************************/
function _splitOn(s,sep){
	if (s == null || s == "") { return "";}
	if (sep == null || sep == ""){ sep = " ";}
	var ax=0;
	var bx=0;
	var ix=0;
	var temp = new Array();
	while ( (bx=s.indexOf(sep,ax)) != -1 ) {
		temp[ix++] = s.substring(ax,bx);
		ax = bx + 1;
	}
	temp[ix] = s.substring(ax);
	return temp;
}

/************************************************************************
** _iswhite(c):
** 	Char c;
** 	Returns Boolean;
************************************************************************/
function _iswhite(c){
	var firstchar=c.charAt(0);
	if (c =="\t" || c==" " || c=="\n") {
		return true;
	} else {
		return false;
	}
}

/************************************************************************
** _noWhite(s):
** 	String s;
** 	Returns String;
** 	Removes ALL whitespace form string;
************************************************************************/
function _noWhite(s){
	var newS="";
	if (s == null || s == "") { return "";}
	for (i=0; i<s.length; i++){
		newS += ( _iswhite(s.charAt(i)) )? "":s.charAt(i);
	}
	return newS;
}


/************************************************************************
** _trim(s):
** 	String s;
** 	Returns String;
************************************************************************/
function _trim(s){
	if (s == null || s == "") { return "";}
	var lastidx=0;
	var c="";
	var buf="";
	var trimmed="";
	while ( lastidx < s.length && _iswhite(c=s.charAt(lastidx++)) ){
		continue;
	}
	lastidx--;
	while (lastidx < s.length) {
		c = s.charAt(lastidx++);
		if ( _iswhite(c) ) {
			buf += c;
		} else {
			trimmed += buf + c;
			buf = "";
		}
	}
	return trimmed;					
}

/************************************************************************
** _cookies2Array():
** 	Returns Array;
************************************************************************/
function _cookies2Array(){
	var temparr = new Array();
	var assocArray = new Array();
	var names="";
	var values="";
	var cookieString = document.cookie;
	temparr = _splitOn(cookieString,";");
	for (var idx=0; idx < temparr.length; idx++) {
		names = temparr[idx].substring(0,(temparr[idx]+"=").indexOf("="));
		values = temparr[idx].substring((temparr[idx]+"=").indexOf("=")+1);
		assocArray[_trim(unescape(names))]=unescape(values);
	}
	return assocArray;
}

/************************************************************************
** _setCookie():
** 	Returns true;
************************************************************************/
function _setCookie(name, value, expire) {
	document.cookie = name + "=" + escape(value) + "; path=/"
	+ ((expire == null) ? "" : ("; expires=" + expire.toGMTString()));
	return true;
}

/************************************************************************
** _getCookie():
** 	Wrapper for _cookies2Array();
** 	Returns unescaped string.
************************************************************************/
function _getCookie(name) {
	var val = _cookies2Array()[name];
	return (val == null) ? "":val;
}


/************************************************************************
** MD5 Message Digest:
** 	The following are helper functions called by calcMD5().
** 	NOTE! These MD5 functions were NOT authored by Logic Pilots, Inc.
************************************************************************/
/* convert integer to hex string */
function hex(i){
	var sHex = "0123456789abcdef";
	h = "";
	for(j = 0; j <= 3; j++)
		h += sHex.charAt((i>>(j*8+4))&0x0F)+sHex.charAt((i>>(j*8))&0x0F);
	return h;
}

/* add, handling overflows correctly */
function add(x, y){
	return ((x&0x7FFFFFFF) + (y&0x7FFFFFFF)) ^ (x&0x80000000) ^ (y&0x80000000);
}

/* MD5 rounds functions */
function R1(A, B, C, D, X, S, T){
	q = add(add(A, (B & C) | ((~B) & D)), add(X, T));
	return add((q << S) | (q >>> (32 - S)), B);
}
function R2(A, B, C, D, X, S, T){
	q = add(add(A, (B & D) | (C & (~D))), add(X, T));
	return add((q << S) | (q >>> (32 - S)), B);
}
function R3(A, B, C, D, X, S, T){
	q = add(add(A, B ^ C ^ D), add(X, T));
	return add((q << S) | (q >>> (32 - S)), B);
}
function R4(A, B, C, D, X, S, T){
	q = add(add(A, C ^ (B | (~D))), add(X, T));
	return add((q << S) | (q >>> (32 - S)), B);
}

/************************************************************************
** MD5 Message Digest, main function, calcMD5()
************************************************************************/
function calcMD5(sInp) {
	/* Calculate length in machine words, including padding */
	wLen = (((sInp.length + 8) >> 6) + 1) << 4;
	var X = new Array(wLen);
	/* Convert string to array of words */
	j = 4;
	for (i = 0; (i * 4) < sInp.length; i++) {
		X[i] = 0;
		for (j = 0; (j < 4) && ((j + i * 4) < sInp.length); j++) {
			X[i] += sInp.charCodeAt(j + i * 4) << (j * 8);
		}
	}
	
	/* Append padding bits and length */
	if (j == 4) X[i++] = 0x80;
	else X[i - 1] += 0x80 << (j * 8);
	for(; i < wLen; i++) { X[i] = 0; }
	X[wLen - 2] = sInp.length * 8;
	
	/* hard coded initial values */
	a = 0x67452301; b = 0xefcdab89; c = 0x98badcfe; d = 0x10325476;
	
	/* Process each 16 word block in turn */
	for (i=0; i<wLen; i+=16) {
	aO=a; bO=b; cO=c; dO=d;
	
	a=R1(a,b,c,d,X[i+ 0],7 ,0xd76aa478);
	d=R1(d,a,b,c,X[i+ 1],12,0xe8c7b756);
	c=R1(c,d,a,b,X[i+ 2],17,0x242070db);
	b=R1(b,c,d,a,X[i+ 3],22,0xc1bdceee);
	a=R1(a,b,c,d,X[i+ 4],7 ,0xf57c0faf);
	d=R1(d,a,b,c,X[i+ 5],12,0x4787c62a);
	c=R1(c,d,a,b,X[i+ 6],17,0xa8304613);
	b=R1(b,c,d,a,X[i+ 7],22,0xfd469501);
	a=R1(a,b,c,d,X[i+ 8],7 ,0x698098d8);
	d=R1(d,a,b,c,X[i+ 9],12,0x8b44f7af);
	c=R1(c,d,a,b,X[i+10],17,0xffff5bb1);
	b=R1(b,c,d,a,X[i+11],22,0x895cd7be);
	a=R1(a,b,c,d,X[i+12],7 ,0x6b901122);
	d=R1(d,a,b,c,X[i+13],12,0xfd987193);
	c=R1(c,d,a,b,X[i+14],17,0xa679438e);
	b=R1(b,c,d,a,X[i+15],22,0x49b40821);
	
	a=R2(a,b,c,d,X[i+ 1],5 ,0xf61e2562);
	d=R2(d,a,b,c,X[i+ 6],9 ,0xc040b340);
	c=R2(c,d,a,b,X[i+11],14,0x265e5a51);
	b=R2(b,c,d,a,X[i+ 0],20,0xe9b6c7aa);
	a=R2(a,b,c,d,X[i+ 5],5 ,0xd62f105d);
	d=R2(d,a,b,c,X[i+10],9 , 0x2441453);
	c=R2(c,d,a,b,X[i+15],14,0xd8a1e681);
	b=R2(b,c,d,a,X[i+ 4],20,0xe7d3fbc8);
	a=R2(a,b,c,d,X[i+ 9],5 ,0x21e1cde6);
	d=R2(d,a,b,c,X[i+14],9 ,0xc33707d6);
	c=R2(c,d,a,b,X[i+ 3],14,0xf4d50d87);
	b=R2(b,c,d,a,X[i+ 8],20,0x455a14ed);
	a=R2(a,b,c,d,X[i+13],5 ,0xa9e3e905);
	d=R2(d,a,b,c,X[i+ 2],9 ,0xfcefa3f8);
	c=R2(c,d,a,b,X[i+ 7],14,0x676f02d9);
	b=R2(b,c,d,a,X[i+12],20,0x8d2a4c8a);
	
	a=R3(a,b,c,d,X[i+ 5],4 ,0xfffa3942);
	d=R3(d,a,b,c,X[i+ 8],11,0x8771f681);
	c=R3(c,d,a,b,X[i+11],16,0x6d9d6122);
	b=R3(b,c,d,a,X[i+14],23,0xfde5380c);
	a=R3(a,b,c,d,X[i+ 1],4 ,0xa4beea44);
	d=R3(d,a,b,c,X[i+ 4],11,0x4bdecfa9);
	c=R3(c,d,a,b,X[i+ 7],16,0xf6bb4b60);
	b=R3(b,c,d,a,X[i+10],23,0xbebfbc70);
	a=R3(a,b,c,d,X[i+13],4 ,0x289b7ec6);
	d=R3(d,a,b,c,X[i+ 0],11,0xeaa127fa);
	c=R3(c,d,a,b,X[i+ 3],16,0xd4ef3085);
	b=R3(b,c,d,a,X[i+ 6],23, 0x4881d05);
	a=R3(a,b,c,d,X[i+ 9],4 ,0xd9d4d039);
	d=R3(d,a,b,c,X[i+12],11,0xe6db99e5);
	c=R3(c,d,a,b,X[i+15],16,0x1fa27cf8);
	b=R3(b,c,d,a,X[i+ 2],23,0xc4ac5665);
	
	a=R4(a,b,c,d,X[i+ 0],6 ,0xf4292244);
	d=R4(d,a,b,c,X[i+ 7],10,0x432aff97);
	c=R4(c,d,a,b,X[i+14],15,0xab9423a7);
	b=R4(b,c,d,a,X[i+ 5],21,0xfc93a039);
	a=R4(a,b,c,d,X[i+12],6 ,0x655b59c3);
	d=R4(d,a,b,c,X[i+ 3],10,0x8f0ccc92);
	c=R4(c,d,a,b,X[i+10],15,0xffeff47d);
	b=R4(b,c,d,a,X[i+ 1],21,0x85845dd1);
	a=R4(a,b,c,d,X[i+ 8],6 ,0x6fa87e4f);
	d=R4(d,a,b,c,X[i+15],10,0xfe2ce6e0);
	c=R4(c,d,a,b,X[i+ 6],15,0xa3014314);
	b=R4(b,c,d,a,X[i+13],21,0x4e0811a1);
	a=R4(a,b,c,d,X[i+ 4],6 ,0xf7537e82);
	d=R4(d,a,b,c,X[i+11],10,0xbd3af235);
	c=R4(c,d,a,b,X[i+ 2],15,0x2ad7d2bb);
	b=R4(b,c,d,a,X[i+ 9],21,0xeb86d391);
	
	a=add(a,aO); b=add(b,bO); c=add(c,cO); d=add(d,dO);
	}
	return hex(a)+hex(b)+hex(c)+hex(d);
}

function testMD5(){ // from RFC 1321
	if (calcMD5("") != "d41d8cd98f00b204e9800998ecf8427e"
	 || calcMD5("a") != "0cc175b9c0f1b6a831c399e269772661"
	 || calcMD5("abc") != "900150983cd24fb0d6963f7d28e17f72"
	 || calcMD5("message digest") != "f96b697d7cb7938d525a2f31aaf161d0")
	alert("MD5 failed consistency check!");
}