/* ************************************************************
Created: 20060120
Author:  Steve Moitozo <god at zilla dot us>
Description: This is a quick and dirty password quality meter 
		 written in JavaScript so that the password does 
		 not pass over the network
Revision Author: Dick Ervasti (dick dot ervasti at quty dot com)
Revision Description: Exchanged text based prompts for a graphic thermometer
Revision Author: Deb Schwartz (dschwartz at 7sigma dot com)
Revision Description: Rewrote regex section, added username check,
         added unhide elements, added disable/enable submit, added baseScore for known requirements
		 matching, made configurable, rewrote message build

Password Strength Factors and Weightings

password length:
level 0 (3 point): less than 4 characters
level 1 (6 points): between 5 and 7 characters
level 2 (12 points): between 8 and 15 characters
level 3 (18 points): 16 or more characters

letters:
level 0 (0 points): no letters
level 1 (5 points): all letters are lower case
level 2 (7 points): letters are mixed case

numbers:
level 0 (0 points): no numbers exist
level 1 (5 points): one number exists
level 1 (7 points): 3 or more numbers exists

special characters:
level 0 (0 points): no special characters
level 1 (5 points): one special character exists
level 2 (10 points): more than one special character exists

combinatons:
level 0 (1 points): letters and numbers exist
level 1 (1 points): mixed case letters
level 1 (2 points): letters, numbers and special characters 
					exist
level 1 (2 points): mixed case letters, numbers and special 
					characters exist

************************************************************ */

var keyNum='';

document.onkeydown = keyCheck;
function keyCheck(event){
    if( window.event ){
		// i hate Internet Explorer
		keyNum = window.event.keyCode;
	}
	else{
		keyNum = (window.event) ? event.keyCode : event.keyCode;
	}
}

function testPassword(passwd,userchk,reqlength,lower,upper,number,special){
	if(keyNum == 9){ return; }  // skip out for the tab key

	// requirements configuration
	var usernameCheck=userchk;
	var requiredLength=reqlength;

	var requiredChars=new Object;
		requiredChars.lowercase=lower;
		requiredChars.capital=upper;
		requiredChars.number=number;
		requiredChars.special=special;

	// bar configuration
	barlength=150;

	var colors=new Array();
	colors[0]='tan';
	colors[1]='#ff0000';
	colors[2]='#990000';
	colors[3]='#990099';
	colors[4]='#000099';
	colors[5]='#0000ff';

	var texts=new Array();
	texts[0]='';
	texts[1]='Very Weak';
	texts[2]='Weak';
	texts[3]='Ok';
	texts[4]='Strong';
	texts[5]='Very Strong';

	// get save button for enable/disable
	var saveButton=document.getElementById('chpass');

	// display requested elements
	var strengthRow=document.getElementById('passMeterRow');
	strengthRow.style.display='';

	var	totalRequired=0;
	for(prop in requiredChars){
		totalRequired=totalRequired+requiredChars[prop];
	}

	// begin calculating scores
	var intScore = 0;
	var baseScore = 0;
	var strVerdict = '';
	var level=0;
	var passed=new Object;
		passed.user=true;
		passed.length=false;
		passed.lowercase=false;
		passed.capital=false;
		passed.number=false;
		passed.special=false;

	// PASSWORD LENGTH
	if (!passwd.length || passwd.length==0){
		intScore = -1;
	}
	else if (passwd.length >= requiredLength){
		baseScore=1;
		passed.length=true;
	}
	if(intScore >=0){
		if (passwd.length <4){   // length between 1 and 3
			intScore = (intScore+3)
		}
		else if (passwd.length <=7){   // length between 4 and 7
			intScore = (intScore+6)
		}
		else if (passwd.length <=15){   // length between 8 and 15
			intScore = (intScore+12)
		}
		else if (passwd.length >15){   // length 16 or more
			intScore = (intScore+18)
		}
	}
	
	var lowercasearray=passwd.match(/[a-z]/g);
	var uppercasearray=passwd.match(/[A-Z]/g);
	var letterarray=passwd.match(/\D/g);
	var specialarray=passwd.match(/[!()+-.<=>@#$%^&*?_~;]/g);
	var numberarray=passwd.match(/\d/g);

	// LETTERS
	if (lowercasearray){   // at least one lower case letter
		intScore = (intScore+1);
		if(lowercasearray.length >= requiredChars.lowercase){
			baseScore++;
			passed.lowercase=true;
		}
	}
	else if(requiredChars.lowercase<1){
			baseScore++;
	}

	if (uppercasearray){   // at least one upper case letter
		intScore = (intScore+5)
		if(uppercasearray.length >= requiredChars.capital){
			baseScore++;
			passed.capital=true;
		}
	}
	else if(requiredChars.capital<1){
			baseScore++;
	}
	
	// NUMBERS
	if (numberarray){   // at least one number
		intScore = (intScore+5);
		if(numberarray.length >= 3){   // at least three numbers
			intScore = (intScore+5)
		}
		if(numberarray.length >= requiredChars.number){
			baseScore++;
			passed.number=true;
		}
	}
	else if(requiredChars.number<1){
			baseScore++;
	}
	
	// SPECIAL CHAR
	if(specialarray){   // at least one special character
		intScore = (intScore+5);
		if(specialarray.length >= 2){   // at least two special characters
			intScore = (intScore+5)
		}
		if(specialarray.length >= requiredChars.special){
			baseScore++;
			passed.special=true;
		}
	}
	else if(requiredChars.special<1){
			baseScore++;
	}

	// COMBOS
	// both upper and lower case
	if (lowercasearray && uppercasearray){
		intScore = (intScore+1)
	}
	// both letters and numbers	
	if (numberarray && letterarray){ 
		intScore = (intScore+1)
	}
	// Letters, numbers, and special characters
	if (numberarray && letterarray && specialarray){ 
		intScore = (intScore+2)
	}
	// Upper Letters, Lower Letters, numbers and special characters
	if (lowercasearray && uppercasearray && numberarray && specialarray){
		intScore = (intScore+2);
	}

	// username or part of username
	if(usernameCheck!=='off'){
		var usernameField=document.getElementById('userName');
		if(usernameField.value){
			var user=usernameField.value;
		}
		else{
			var user=usernameField.innerHTML;
		}
		var isEmail=user.indexOf('@');
		if(isEmail != -1){
			var username=user.substring(0,isEmail);
		}
		else{
			var username=user;
		}
		if(username.length < 2){alert('Please enter your email address first');}
		if(usernameCheck=='half'){
			var namehalf=(username.length / 2)|0;
			//if(namehalf < 1){alert('Please enter your email address first');}
			for(i=0;i <= namehalf;i++){
				var endstr=namehalf + i;
				var namepart=username.substring(i,endstr);
				if(passwd.indexOf(namepart) != -1){
					intScore = (intScore-10)
					baseScore--;
					passed.user=false;
				}
			}
		}
		else if(usernameCheck=='all'){
			if(passwd.indexOf(username) != -1){
				intScore = (intScore-10)
				baseScore--;
				passed.user=false;
			}
		}
		else if(usernameCheck=='equal'){
			if(passwd == username){
				intScore = (intScore-10)
				baseScore--;
				passed.user=false;
			}
		}
	}

	// check score
	if (passwd.length==0 || !passwd.length){ //empty
		level=0;
	}
	else if(intScore < 16){	//very weak
		level=1;
	}
	//else if (intScore < 25 || baseScore < 5){  //weak
	else if (intScore < 25){  //weak
		//if(baseScore==5){
		//	level=3;
		//}
		//else{
			level=2;
		//}
	}
	else if (intScore < 35){  //ok
		level=3;
	}
	else if (intScore < 45){  //strong
		level=4;
	}
	else if (intScore >=45){
		level=5;
	}

	// enable/disable save button if requirements were met
	if(baseScore < 5){
		saveButton.disabled=true;
	}
	else{
		saveButton.disabled=false;
	}

	// set bar lengths
	barsection=(barlength/5)|0;
	var cellbars=new Array();
	cellbars[0]=new Array(0,barsection*5);
	cellbars[1]=new Array(barsection,barsection*4);
	cellbars[2]=new Array(barsection*2,barsection*3);
	cellbars[3]=new Array(barsection*3,barsection*2);
	cellbars[4]=new Array(barsection*4,barsection);
	cellbars[5]=new Array(barsection*5,0);

	// build verdict
	strVerdict='<table><tr><td><table cellpadding=0 cellspacing=2><tr>';
	if(cellbars[level][0] > 0){
		strVerdict+='<td height=4 width='+cellbars[level][0]+' bgcolor='+colors[level]+'></td>';
	}
	if(cellbars[level][1] > 0){
		strVerdict+='<td height=4 width='+cellbars[level][1]+' bgcolor='+colors[0]+'></td>';
	}
	strVerdict+='</tr></table></td><td style="font-size:.8em;"> &nbsp;&nbsp;<b>'+texts[level]+'</b></td></tr></table>';
	//document.write(strVerdict);
	document.getElementById("passMeter").innerHTML= (strVerdict);

	if(requiredLength > 0 || usernameCheck ==true || totalRequired > 0){
		var requiredRow=document.getElementById('passRequireRow');
		requiredRow.style.display='';

		// build requirements statement
		var requireStr='';
		var passedTag="<span class='passed'>";
		var warningTag="<span class='warning'>";
		if(requiredLength > 0){
			if(passed.length==true){
				var lengthClass=passedTag;
			}
			else{
				var lengthClass=warningTag;
			}
			requireStr+= lengthClass+requiredLength+' characters</span>';
		}
		if(totalRequired > 0){
			if(requiredLength > 0){
				requireStr+= ', with a';
			}
			else{
				requireStr+= 'A';
			}
			requireStr+='t least ';
			charStrings=new Array();
			for(prop in requiredChars){
				if(requiredChars[prop]>0){
					if( (prop=='number' && passed.number==true) ||
						(prop=='lowercase' && passed.lowercase==true) ||
						(prop=='capital' && passed.capital==true) ||
						(prop=='special' && passed.special==true) ){
						charStr=passedTag;
					}
					else{
						charStr=warningTag;
					}
					charStr+=requiredChars[prop]+' '+prop;
					if(prop=='lowercase' || prop=='capital'){
						charStr+=' letter';
					}
					else if(prop=='special'){
						charStr+=' character';
					}
					if(requiredChars[prop]>1){
						charStr+='s';
					}
					charStr+='</span>';
					charStrings.push(charStr);
				}
			}
			var curlen=charStrings.length;
			for(var i=0; i < curlen; i++){
				requireStr+=charStrings.shift();
				if(charStrings.length > 1){
					requireStr+=', ';
				}
				else if(charStrings.length == 1){
					requireStr+=' and ';
				}
			}
		}
		requireStr+='.';
		if(usernameCheck !== 'off'){
			if(passed.user==true){
				var userClass=passedTag;
			}
			else{
				var userClass=warningTag;
			}
			if(usernameCheck == 'half'){
				requireStr+='<br>'+userClass+'Also may not contain half or more of your username.</span>';
			}
			else if(usernameCheck == 'all'){
				requireStr+='<br>'+userClass+'Also may not contain your username.</span>';
			}
			if(usernameCheck == 'equal'){
				requireStr+='<br>'+userClass+'Also may not be the same as your username.</span>';
			}
		}
		//document.write(requireStr);
		document.getElementById("passMeterRequired").innerHTML= requireStr;
	}



}

