/**
 * javaclient_login.js
 *
 *
 *
 */

function isValidEmail(emailStr){
    var emailPat=/^(.+)@(.+)$/
    var specialChars="\\(\\)<>@,;:\\\\\\\"\\.\\[\\]"
    var validChars="\[^\\s" + specialChars + "\]"
    var quotedUser="(\"[^\"]*\")"
    var ipDomainPat=/^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/
    var atom=validChars + '+'
    var word="(" + atom + "|" + quotedUser + ")"
    var userPat=new RegExp("^" + word + "(\\." + word + ")*$")
    var domainPat=new RegExp("^" + atom + "(\\." + atom +")*$")

    var matchArray=emailStr.match(emailPat)
    if (matchArray==null) {
   return false;
    }

    var user=matchArray[1]
    var domain=matchArray[2]

    if (user.match(userPat)==null) {
      return false;
    }

    var IPArray=domain.match(ipDomainPat)
    if (IPArray!=null) {
   for (var i=1;i<=4;i++) {
     if (IPArray[i]>255) {
       return false;
     }
      }
      return true;
    }

    var domainArray=domain.match(domainPat);
    if (domainArray==null) {
      return false;
    }

    var atomPat=new RegExp(atom,"g");
    var domArr=domain.match(atomPat);
    var len=domArr.length;

    if (domArr[domArr.length-1].length<2 || domArr[domArr.length-1].length>3) {
      return false;
    }

    if (len<2) {
      return false;
    }

    return true;
}

function isValidChikkaID(value){

	if(isNumeric(value) && (value.length>=8 &&  value.length<=15)){
		if(value.indexOf("00")==0){
			// a valid chikkaid
			//alert('a valid pc chikkaid');
			return true;
		}else{
			// expecting a mobile number
			// check if valid mobile number
			if(value.length<9){
			//alert('a not valid mobile chikkaid');
			return false;
			}else{
			//alert('valid mobile chikkaid');
			return true;
			}
		}
	}else{
		//alert('nat valid length');
		return true;
	}
}

function isValidPassword(value){
	if(value.length>=4 && value.length<=15){
		//alert('valid password.');
		return true;
	}else{
		//alert('not valid length');
		return false;
	}
}

function isNumeric(value){

	var ret_val = true;
	var temp;

	for (var i=0; i<value.length; i++) {
		temp = value.substring(i, i+1);
		if (isNaN(temp)){
			ret_val = false;
			break;
		}
	}

	return ret_val;
}

function submitLogin(){
	var msg;
	var error;
	var num = 1;
	msg = "Please enter  the following information before clicking submit.\n\n"
	var chikkaid;
	var password;
	var window_top = document.login_form.window_top.value;
	var window_left = document.login_form.window_left.value;
	var window_width = document.login_form.window_width.value;
	var window_height = document.login_form.window_height.value;

	client_post_url = document.login_form.client_url.value;
	chikkaid = document.login_form.username.value;
	password = document.login_form.password.value;


	if(chikkaid==""){
		msg = msg + num + '. Your Chikka ID or your email address\n';
		error = true;
		num= num + 1;
	}else{
		if(!isValidChikkaID(chikkaid)){
			// valid chikkaid
			msg = msg + num + '. Please enter a valid ChikkaID.\n    Your ChikkaID should is at least 8 characters\n    and not more than 15 characters.\n';
			num= num + 1;
			error = true;
		}else if(!isValidEmail(chikkaid) && !isValidChikkaID(chikkaid)){
			// invalid email
			msg = msg + num + '. Please enter a valid email address\n';
			num= num + 1;
			error = true;
		}else{
			// valid chikkaid
		}
	}

	if(password==""){
		msg = msg + num + '. Your password\n';
		error = true;
	}else{
		if(!isValidPassword(password)){
			msg = msg + num + '. Please enter a valid password\n    It must be at least 4 characters and at most 8 characters.';
			num= num + 1;
			error = true;
		}else{
			// valid password...
		}
	}

	if(error==true){

		alert(msg);

	}else{

		encoded_pwd = myUrlEncode(document.login_form.password.value);

		var url = client_post_url + '?'
		url += '&username=' + escape(document.login_form.username.value) + '&password=' + escape(encoded_pwd);
		var leftpos = screen.availWidth - window_width - 20;
		is_resizable = (navigator.appName=="Netscape") ? 0 : 0;
		var options = 'status=yes,location=no, menubar=no, left=' + leftpos + ', top=' + window_top + ', width=' + window_width + ', height=' + window_height + ', scrollbars=no, resizable=yes';

		window.open(url,'LOGIN_PAGE',options);
		window.login_form.reset();
	}

}

function retrievePassword(){

	forgot_url = document.login_form.forgot_url.value;

	if(forgot_url==''){
		forgot_url = 'http://java.chikka.com/forgotpassword.php';
	}

	window.open(forgot_url,'FORGOTPASSWORD_PAGE','toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=no,width=450,height=350');
}

function checkEnter(event)
{
	var code = 0;

	if (navigator.appName == 'Netscape')
		code = event.which;
	else
		code = event.keyCode;

	if ( code == 13 ) submitLogin();
}




/* Copyright (c) 2000 by Robert Graham (RobertGraham.com) */

/*
This code contains your standard Base64 encode/decode
routines.
*/

/**
*/
function base64ToAscii(c)
{
	var theChar = 0;

	if (0 <= c && c <= 25)
	{
		theChar = String.fromCharCode(c + 65);
	}
	else if (26 <= c && c <= 51)
	{
		theChar = String.fromCharCode(c - 26 + 97);
	}
	else if (52 <= c && c <= 61)
	{
		theChar = String.fromCharCode(c - 52 + 48);
	}
	else if (c == 62)
	{
		theChar = '+';
	}
	else if( c == 63 )
	{
		theChar = '/';
	}
	else
	{
		theChar = String.fromCharCode(0xFF);
	}

	return theChar;
}


/**
 * Encodes a string according to "URL encoding" rules whereby every
 * character is converted to the %xx equivelent. This is similar
 * the JavaScript 'escape()' function, except that it encodes all
 * the characters, not just the special ones like "-/?&...". For example,
 * the string "foo@example.com" will be encoded into
 * "%66%6F%6F%40%65%78%61%6D%70%6C%65%2E%63%6F%6D".
 *@see myUrlDecode
 */
function myUrlEncode(str) {
	var result = "";
	var i = 0;
	var sextet = 0;
	var leftovers = 0;
	var octet = 0;

	for (i=0; i < str.length; i++) {
		octet = str.charCodeAt(i);
		switch( i % 3 )
		{
			case 0:
			{
				sextet = ( octet & 0xFC ) >> 2 ;
				leftovers = octet & 0x03 ;

				// sextet contains first character in quadruple
				break;
			}

			case 1:
			{
				sextet = ( leftovers << 4 ) | ( ( octet & 0xF0 ) >> 4 );
				leftovers = octet & 0x0F ;

				// sextet contains 2nd character in quadruple
				break;
			}

			case 2:
			{
				sextet = ( leftovers << 2 ) | ( ( octet & 0xC0 ) >> 6 ) ;
				leftovers = ( octet & 0x3F ) ;

				// sextet contains third character in quadruple
				// leftovers contains fourth character in quadruple
				break;
			}
		}

		result = result + base64ToAscii(sextet);

		// don't forget about the fourth character if it is there
		if( (i % 3) == 2 )
		{
			result = result + base64ToAscii(leftovers);
		}

	}

	// figure out what to do with leftovers and padding
	switch( str.length % 3 )
	{
		case 0:
		{
			// an even multiple of 3, nothing left to do
			break ;
		}
		case 1:
		{
			// one 6-bit chars plus 2 leftover bits
			leftovers =  leftovers << 4 ;
			result = result + base64ToAscii(leftovers);
			result = result + "==";
			break ;
		}
		case 2:
		{
			// two 6-bit chars plus 4 leftover bits
			leftovers = leftovers << 2 ;
			result = result + base64ToAscii(leftovers);
			result = result + "=";
			break ;
		}
	}

	return result;
}


/**
 * A helper function for converting a hex digit into the corresponding
 * integer value. I really don't know much about JavaScript, so the
 * the conversion is a little laborious. There probably is an easier
 * way (including a built-in function), but I don't know it.
 */
function hexval(c) {
	if (String('0').charCodeAt(0) <= c && c <= String('9').charCodeAt(0))
		return c - String('0').charCodeAt(0);
	if (String('A').charCodeAt(0) <= c && c <= String('F').charCodeAt(0))
		return c - String('A').charCodeAt(0) + 10;
	if (String('a').charCodeAt(0) <= c && c <= String('f').charCodeAt(0))
		return c - String('a').charCodeAt(0) + 10;
	return 0;
}

/**
 * Decodes a string that has been previously encoded according to the
 * myUrlDecode() function.
 *@see myUrlEncode
 */
function myBase64Decode(str, is_binary) {
	var result = "";
	var i = 0;
	var x;
	var shiftreg = 0;
	var count = -1;


	for (i=0; i < str.length; i++) {
		c = str.charAt(i);
		if ('A' <= c && c <= 'Z')
			x = str.charCodeAt(i) - 65;
		else if ('a' <= c && c <= 'z')
			x = str.charCodeAt(i) - 97 + 26;
		else if ('0' <= c && c <= '9')
			x = str.charCodeAt(i) - 48 + 52;
		else if (c == '+')
			x = 62;
		else if (c == '/')
			x = 63;
		else
			continue;

		count++;

		switch (count % 4)
		{
		case 0:
			shiftreg = x;
			continue;
		case 1:
			v = (shiftreg<<2) | (x >> 4);
			shiftreg = x & 0x0F;
			break;
		case 2:
			v = (shiftreg<<4) | (x >> 2);
			shiftreg = x & 0x03;
			break;
		case 3:
			v = (shiftreg<<6) | (x >> 0);
			shiftreg = x & 0x00;
			break;
		}

		if (!is_binary && (v < 32 || v > 126) && (v != 0x0d) && (v != 0x0a))
		{
			result = result + "<";
			result = result + "0123456789ABCDEF".charAt((v/16)&0x0F);
			result = result + "0123456789ABCDEF".charAt((v/1)&0x0F);
			result = result + ">";
		}
		else
			result = result + String.fromCharCode(v);

	}
	return result.toString();
}

/**
 *
 */
function myNbtDecode(str) {
	var result = "";
	var i = 0;
	var x;
	var shiftreg = 0;
	var count = -1;


	for (i=0; i < str.length; i++) {
		c = str.charAt(i);
		if ('A' <= c && c <= 'Z')
			x = str.charCodeAt(i) - 65;
		else if ('a' <= c && c <= 'z')
			x = str.charCodeAt(i) - 97;
		else
			continue;

		count++;

		switch (count % 2)
		{
		case 0:
			shiftreg = x;
			continue;
		case 1:
			v = (shiftreg<<2) | (x);
			shiftreg = 0;
			break;
		}

		result = result + String.fromCharCode(v);

	}
	return result.toString();
}

function myUrlDecode(str) {
	return myBase64Decode(str, false);
}


var PacketTags = new Array(
		"Reserved - a packet tag must not have this value",
		"Public-Key Encrypted Session Key Packet",
		"Signature Packet",
		"Symmetric-Key Encrypted Session Key Packet",
		"One-Pass Signature Packet",
		"Secret Key Packet",
		"Public Key Packet",
		"Secret Subkey Packet",
		"Compressed Data Packet",
		"Symmetrically Encrypted Data Packet",
		"Marker Packet",
		"Literal Data Packet",
		"Trust Packet",
		"User ID Packet",
		"Public Subkey Packet",
		"Private or Experimental Values"
	);

var HashAlgorithm = new Array(
	"UNKNOWN",
	"MD5",
    "SHA1",
    "RIPEMD160",
    "double-width SHA",
    "MD2",
    "TIGER192",
    "HAVAL-5-160"
);

var CompressionAlgorithm = new Array(
	"Uncompressed",
	"ZIP (RFC 1951)",
    "ZLIB (RFC 1950)"
);

function hexcode(x) {
	var result = "";
	result = result + "0123456789ABCDEF".charAt((x/16)&0x0F);
	result = result + "0123456789ABCDEF".charAt((x/1)&0x0F);
	return result;
}

function hexdump(str,i) {
	var result = "";
	var start = i;
	var ascii_dump = "";

	while (i < str.length) {
		var c = str.charCodeAt(i);
		result = result + hexcode(c);
		if (c > 32 && c < 127)
			ascii_dump = ascii_dump + str.charAt(i);
		else
			ascii_dump = ascii_dump + '.';
		if (((i-start) % 8) == 7)
			result = result + " ";
		if (((i-start) % 16) == 15) {
			result = result + " " + ascii_dump + "\n";
			ascii_dump = "";
		}
		i++;
	}

	while (((i-start) % 16) != 15) {
		result = result + "  ";
		if (((i-start) % 8) == 7)
			result = result + " ";
		ascii_dump = ascii_dump + " ";
		i++;
	}
	result = result + "    " + ascii_dump + "\n";
	return result;
}

function publicKeyAlgorithm(x) {
	var result = "";

	switch (x)
	{
	case  1: result = result + "RSA Encrypt or Sign"; break;
	case  2: result = result + "RSA Encrypt-Only"; break;
	case  3: result = result + "RSA Sign-Only"; break;
	case 16: result = result + "Elgamal Encrypt-Only"; break;
	case 17: result = result + "DSA"; break;
	case 18: result = result + "Elliptic Curve"; break;
	case 19: result = result + "ECDSA"; break;
	case 20: result = result + "Elgamal Encrypt or Sign"; break;
	case 21: result = result + "Diffie-Hellman (X9.42) for IETF-S/MIME"; break;
    default: result = result + "UNKNOWN"; break;
	}

	return result;
}

function myPGPdecodeKey(str, i) {
	var x = 0;
	var result = "";

	//- A one-octet version number (3).
	var sig_version = str.charCodeAt(i++);
	result = result + "Sig-Version = " + sig_version + "\n";

	//- A four-octet number denoting the time that the key was created.
	x = str.charCodeAt(i)<<24 | str.charCodeAt(i+1)<<16 | str.charCodeAt(i+2)<<8 | str.charCodeAt(i+3);
	var creation_time = new Date();
	creation_time.setTime(x * 1000);
	result = result + "Creation-Time = " + creation_time + "\n";
	i = i + 4;

	//- A two-octet number denoting the time in days that this key is
    //   valid. If this number is zero, then it does not expire.
	x = str.charCodeAt(i)<<16 | str.charCodeAt(i+1);
	if (x == 0)
		result = result + "Expiration = never\n";
	else
		result = result + "Expiration = " + x + " days\n";
	i = i + 2;

	//- A one-octet number denoting the public key algorithm of this key
	x = str.charCodeAt(i++);
	result = result + "Public-Key-Algorithm = " + x + " (" + publicKeyAlgorithm(x) + ")\n";

	result = result + "Public-Key Data:\n";
	result = result + hexdump(str,i);


	return result;
}

function decode_compressed_packet(str,i,len) {
	var result = "";
	var x = 0;

	//- One octet that gives the algorithm used to compress the packet.
	x = str.charCodeAt(i++);
	result = result + "Compression-Algorithm = " + x + " (" + CompressionAlgorithm[x] + ")\n";
	result = result + "---- Compressed Data ----\n";
	result = result + hexdump(str,i);

	return result;
}

function decode_new_pgp(str,i,content_tag,len) {
	var result = "";

	switch (content_tag) {
	case 8:
		result = result + decode_compressed_packet(str,i,len);
		break;
	default:
		result = result + "---- UNKNOWN DECODE ----\n";
		result = result + hexdump(str,i);
	}

	return result;
}


function myPGPdecode(strx) {


	var result = "";
	var str = "xxx";
	var i = 0;

	str = myBase64Decode(strx, true);
	str.toString();

	if (str.length < 10)
		return "sig too small " + str;

	var tag = str.charCodeAt(i);
	i++;

	var content_tag = 0;
	var length_type = -1;
	var len = 0;
	if (tag & 0x80 != 0x80)
		return "Invalid tag\n";
	if ((tag & 0xC0) == 0xC0)
	{
		result = result + "Format = new 5.x OpenPGP format\n";
		content_tag = tag & 0x3F;
		result = result + "Content-Tag = " + content_tag + " ";
		if (content_tag < 14)
			result = result + "(" + PacketTags[content_tag] + ")";
		result = result + "\n";
		len = str.charCodeAt(i++);
		if (len == 255)
		{
			len = str.charCodeAt(i)<<24 | str.charCodeAt(i+1)<<16 | str.charCodeAt(i+2)<<8 | str.charCodeAt(i+3);
		}
		else if (len > 191)
		{
			len = (len - 192) << 8 + str.charCodeAt(i++) + 192;
		}
		result = result + "Length = " + len + " bytes\n";

		result = result + decode_new_pgp(str,i,content_tag,len);
		return result;
	}
	else
	{
		result = result + "Format = old 2.x format\n";
		content_tag = (tag >> 2) & 0x0F;
		length_type = tag & 0x03;
		result = result + "Content-Tag = " + content_tag + " ";
		if (content_tag < 14)
			result = result + "(" + PacketTags[content_tag] + ")";
		result = result + "\n";
		//result = result + "Length-Type = " + length_type + "\n";
		if (length_type == 0)
		{
			len = str.charCodeAt(i);
			i = i + 1;
		}
		else if (length_type == 1)
		{
			len = str.charCodeAt(i) << 8 | str.charCodeAt(i+1);
			i = i + 2;
		}
		result = result + "Length = " + len + " bytes\n";
	}

	/*if (len > str.length)
		return "missing data, len=" + len + ", str.length = " + str.length + ", c=" + str.charAt(i) + "\n";*/
	//result = result + "Length = " + len + "\n";

	if (content_tag == 2)
	{
		//result = result + "---- SIGNATURE ----\n";
		var sig_version = str.charCodeAt(i++);
		var x = 0;
		switch (sig_version)
		{
		case 1:
		case 3:
			result = result + "Sig-Version = " + sig_version + "\n";
			x = str.charCodeAt(i++);
			if (x != 5)
			{
				result = result + "Expected val=5, found " + x + "\n";
				return result;
			}
			x = str.charCodeAt(i++);
			result = result + "Sig-Type = " + x ;
			switch (x)
			{
		    case 0x00: result = result + " (Signature of a binary document.)\n"; break;
		    case 0x01: result = result + " (Signature of a canonical text document.)\n"; break;
		    case 0x02: result = result + " (Standalone signature.)\n"; break;
		    case 0x10: result = result + " (Generic certification of a User ID and Public Key packet.)\n"; break;
		    case 0x11: result = result + " (Persona certification of a User ID and Public Key packet.)\n"; break;
		    case 0x12: result = result + " (Casual certification of a User ID and Public Key packet.)\n"; break;
		    case 0x13: result = result + " (Positive certification of a User ID and Public Key packet.)\n"; break;
		    case 0x18: result = result + " (Subkey Binding Signature)\n"; break;
		    case 0x1F: result = result + " (Signature directly on a key)\n"; break;
		    case 0x20: result = result + " (Key revocation signature)\n"; break;
		    case 0x28: result = result + " (Subkey revocation signature)\n"; break;
		    case 0x30: result = result + " (Certification revocation signature)\n"; break;
		    case 0x40: result = result + " (Timestamp signature.)\n"; break;
			default: result = result + "(unknown)\n"; break;
			}
			x = str.charCodeAt(i)<<24 | str.charCodeAt(i+1)<<16 | str.charCodeAt(i+2)<<8 | str.charCodeAt(i+3);
			var creation_time = new Date();
			creation_time.setTime(x * 1000);
			result = result + "Creation-Time = " + creation_time + "\n";
			i = i + 4;

			//- Eight-octet key ID of signer.
			result = result + "KeyID = 0x";
			for (j=0; j<8; j++) {
				x = str.charCodeAt(i++);
				result = result + hexcode(x);
			}
			result = result + "\n";


			//- One-octet public key algorithm.
			x = str.charCodeAt(i++);
			result = result + "Public-Key-Algorithm = " + x + " (" + publicKeyAlgorithm(x) + ")\n";


			//- One-octet hash algorithm.
			x = str.charCodeAt(i++);
			result = result + "Hash-Algorithm = " + x + " (" + HashAlgorithm[x] +")\n";


			//- Two-octet field holding left 16 bits of signed hash value.
			x = str.charCodeAt(i++);
			result = result + "Q-hash = 0x" + hexcode(x);
			x = str.charCodeAt(i++);
			result = result + hexcode(x) + "\n";

			// Binary data
			result = result + "Signature data:\n";
			result = result + hexdump(str,i);


			break;
		default:
			result = result + "Sig-Version = " + sig_version + "(UNKNOWN)\n";
		}
	}
	else if (content_tag == 6)
	{
		result = result + "---- KEY ----\n";
		result = result + myPGPdecodeKey(str,i);
	}
	else
	{
		result = result + "---- UNDECODED CONTENTS ----\n";
	}


	return result;

}

function myUrlBinaryDecode(strx) {
	var str = myBase64Decode(strx,true);
	return hexdump(str,0);
}



function myMsgIdDecode(str) {
	var result = "";
	var x = 0;
	var i = 0;

	x = str.charCodeAt(i)<<24 | str.charCodeAt(i+1)<<16 | str.charCodeAt(i+2)<<8 | str.charCodeAt(i+3);
	var creation_time = new Date();
	creation_time.setTime(x * 1000);
	result = result + "Creation-Time = " + creation_time + "\n";
	i = i + 4;

	return result + hexdump(str,i);
}

//aHR0cDovL0xFU0xFWS01MDA6ODA4Mjo=


/***************************************************************/

/*
 * 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)
{
  str = "";
  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)
{
  nblk = ((str.length + 8) >> 6) + 1;
  blks = new Array(nblk * 16);
  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 MD5(str)
{
  x = str2blks_MD5(str);
  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;

  for(i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var 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);
}

function hash(form,login_url) {
    // this is Javascript enabled browser
    // document.login_form[".js"].value=1;
    // rudimentary check for a 4.x brower. should catch IE4+ and NS4.*

    var url;

    if (arguments.length > 1 && login_url != "") { // in case login_url is not passed in
      url = login_url;
    } else {
      //url = "${.l_url}";
      //if (url == "") {
        url = "http://login.yahoo.com/config/login";
      //}
    }
    url += "?";

    if (navigator.userAgent.indexOf("Mozilla/4")==0) {
      var passwd = form.passwd.value;
      var hash1 = MD5(form.passwd.value);
      var challenge = form[".challenge"].value;
      var hash2 = MD5(form.passwd.value) + challenge;
      var hash;

      if(form.passwd.value){
        hash=MD5(hash2);
      } else {
        hash="";
      }
      var js = 0;

      for(i=0; i<form.elements.length; i++){
        if(form.elements[i].name.length <=0) {
          continue;
        }
        if(i > 0){
          url += "&";
        }
        url += form.elements[i].name;
        url += "=";

        if(form.elements[i].name == "passwd"){
          url += hash;
        } else if (form.elements[i].type == "checkbox" && !form.elements[i].checked) {
          url += "";
        } else if (form.elements[i].name == ".save"){
          url += "1"; // "Sign in" causes problem with the space
        } else if (form.elements[i].name == ".js"){
          js = 1;
          url += "1";
        } else {
          url += escape(form.elements[i].value);
        }
      }

      // indicate the password is hashed.
      url += "&.hash=1";

      if(js == 0){
        url += "&.js=1";
      }
      url += "&.md5=1";
      //alert("url=" + url);
      location.href=url;
      // prevent from running this again. Allow the server response to submit the form directly
      form.onsubmit=null;

      // abort normal form submission
      return false;
    }
    // allow normal form submission
    return true;
}

