/*
 * Javascript Password Stregth
 *
 * Copyright (c) 2008, Felix Bruns <felixbruns@web.de>
 * 
 */

(function($) {
	$.extend($.fn, {
		passwordStrength: function(settings){
			var settings = $.extend({
				minlength : 6,
				ratings   : [0, 10, 15, 30, 40, 100],
				widths    : ['10%', '25%', '50%', '75%', '100%'],
				colors    : ['#f00', '#c06', '#f60', '#3c0', '#3f0'],
				verdicts  : ['Very weak', 'Weak', 'Medium', 'Strong', 'Very strong'],
				common    : ['password', '123', '123456', 'qwerty', 'qwertz']
			}, settings);
			
			return this.each(function(){
				var id = $(this).attr('id');
				
				/* Append info divs */
				if(settings.minlength > 0){
					$(this).after(
						"<div class=\"password-strength-minlength\" id=\"" + id +
						"-minlength\">Minimum number of characters is " +
						settings.minlength + "</div>"
					);
				}
				$(this).after(
					"<div class=\"password-strength-info\" id=\"" + id + "-text\"></div>"
				);
				$(this).after(
					"<div class=\"password-strength-bar\" id=\"" + id + "-bar\" ></div>"
				);
				
				/* Show password strength */
				$.fn.showPasswordStrength($(this).val(), id, settings);
				
				/* Recalculate every keypress */
				$(this).keyup(function() {
					$.fn.showPasswordStrength($(this).val(), id, settings);
				});
			})
		},
		
		showPasswordStrength: function(password, id, settings){
			var color, verdict, width;
			
			/* Get password rating */
			var rating = $.fn.ratePassword(password, settings);
			
			/* Check for special ratings */
			if(rating == -300){
				color   = '#000';
				verdict = 'No protection';
				width   = '5%';
			}
			else if(rating == -200){
				color   = '#f00';
				verdict = 'Unsafe password!';
				width   = '5%';
			}
			else if(rating < 0 && rating > -199){
				color = '#f00';
				verdict  = 'Too short';
				width    = '5%';
			}
			
			/* Check for defined ratings */
			for(var i = 0; i < settings.ratings.length; i++){
				if(rating >= settings.ratings[i] && rating < settings.ratings[i + 1]){
					color   = settings.colors[i];
					verdict = settings.verdicts[i];
					width   = settings.widths[i];
					
					break;
				}
			}
			
			/* Change color and verdict */
			$('#' + id + '-bar').css({
				backgroundColor : color,
				border          : '1px solid ' + color,
				width           : width
			});
			$('#' + id + '-text').html("<span style='color: " + color + ";'>" + verdict + "</span>");
		},
		
		ratePassword: function(password, settings){
			var rating = 0;
			
			/* Check if password is empty */
			if(password.length == 0 && settings.minlength == 0){
				return -300;
			}
			
			/* Check for common words */
			for(var i = 0; i < settings.common.length; i++){
				if(password.toLowerCase() == settings.common[i]){
					return -200;
				}
			}
			
			/* Check password length */
			if(password.length < settings.minlength){
				rating -= 100;
			}
			else if(password.length >= settings.minlength && password.length <= (settings.minlength + 2)){
				rating += 6;
			}
			else if(password.length >= (settings.minlength + 3) && password.length <= (settings.minlength + 4)){
				rating += 12;
			}
			else if(password.length >= (settings.minlength + 5)){
				rating += 18;
			}
			
			/* Check for characters */
			if(password.match(/[a-z]/)){
				rating += 1;
			}
			if(password.match(/[A-Z]/)) {
				rating += 5;
			}
			if(password.match(/\d+/)) {
				rating += 5;
			}
			if(password.match(/(.*[0-9].*[0-9].*[0-9])/)) {
				rating += 7;
			}
			if(password.match(/.[!,@,#,$,%,^,&,*,?,_,~]/)) {
				rating += 5;
			}
			if(password.match(/(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])/)) {
				rating += 7;
			}
			if(password.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/)) {
				rating += 2;
			}
			if(password.match(/([a-zA-Z])/) && password.match(/([0-9])/)) {
				rating += 3;
			}
			if(password.match(/([a-zA-Z0-9].*[!,@,#,$,%,^,&,*,?,_,~])|([!,@,#,$,%,^,&,*,?,_,~].*[a-zA-Z0-9])/)) {
				rating += 3;
			}
			
			return rating;
		}
	})
})(jQuery);

