/********************************************************************************/
/*										*/
/*  Copyright (c) GENIESYS, Inc. All rights reserved				*/
/*  										*/
/*  Site	:	http://www.geniesys.net					*/
/*										*/
/*  Feedback	:	support@geniesys.net					*/
/*										*/
/*  File	:	validation_rules.js					*/
/*  Version	:	2.0							*/
/*  Purpose	:	library of general-purpose validation, verificaton	*/
/*			and formating functions					*/
/*										*/
/*  Notes	:	Distributed as part of software developed by		*/
/*			GENIESYS Inc. Permission given to use this script in	*/
/*			ANY kind of applications if header lines are left	*/
/*			unchanged.						*/
/*										*/
/*  Maintenance History:							*/
/*  00/00/2001	Alex Dudnik	Original Implementation				*/
/*  04/26/2001	Alex Dudnik	Removed/disabled unused code			*/
/*  05/04/2001	Alex Dudnik	Modified browser detection code for Netscape6	*/
/*  07/17/2003  Alex Dudnik	Removed browser detection code (redefined in	*/
/*				browser_version.js)				*/
/********************************************************************************/
/*

	*** LIST OF FUNCTIONS ***

FUNCTION					ARGUMENT				RETURN
----------------------------			-----------------			-------------------
isInt( Object | String [, verbose] )		form object or string		true if value can be interpreted as integer	

_isInt( int | float | NaN )			numeric				true if value is integer

isFloat( Object | String [, verbose])		form object or string		true if value can be interpreted as float	

_isFloat( int | float | NaN )			numeric				true if value is float

_isHex( string )				string of HEX characters	true if no symbols other than 0123456789AaBbCcDdEeFf

isNumber( Object | String  )			String of decimals		true if no symbols other than 0123456789

isIPaddress( Object | String [, verbose])	form object or string		true if value can be interpreted as an IP address

isSSN( Object | String [, verbose] )		form object or string		true if value can be interpreted as Social Security Number

isZip( Object|String, verbose )			form object or string		true if value can be interpreted as US Zip code 5[+4]

isEmailAddress( Object | String [, verbose])	form object or string		true if value can be interpreted as full email address

isURL( Object | String )			form object or string		true if value can be interpreted as URL (http, ftp, mailto) 

isMD5Encrypted( Object | String )		form object or string		true if value such as a password has been encrypted by MD5(). i.e. = 32 hex characters

Trim( Object | String [, verbose] )		form object or string		removes spaces at the beginning and at the end of a string

removeSpaces( Object )				form object			removes all spaces in the field

getDaysPerMonth( month, year )			int, int			returns number of days in a month with correction for leap year

Note:	Applies to all functions where optional "verbose" argument is accepted.
		Argument "verbose" is optional and assumed FALSE if not specified.
		When it is FALSE then error/warning messages are NOT displayed.
*/

function isInt( myObject, verbose ) {
	// --- Uses low level function _isInt() ---;
	switch ( typeof(myObject) ) {
	case "object"    :  var result = _isInt(myObject.value); break;
	case "string"    :  var result = _isInt(myObject);       break;
	case "number"    :  var result = _isInt(myObject);       break;
	case "undefined" :  alert("Invalid usage of isInt( Object | String )\nOne parameter is required."); return;
	default          :  alert("Invalid usage of isInt( Object | String )\nParameter type is unknown."); return;
	}

	if( result ) return true;	// End function & return TRUE;

	// NOT a number OR NOT Integer;
	if( verbose ) alert('Integer value only!');
	if (typeof(myObject)=="object") { myObject.value=myObject.defaultValue; myObject.focus(); }
	return false;
}

function _isInt( par1 ) {
	if( par1 && (isNaN(par1) || (parseFloat(par1) !== parseInt(par1,10))) ) {return false;}
	return true;
}

function isFloat( myObject, verbose ) {
	// --- Uses low level function _isFloat() ---;
	switch ( typeof(myObject) ) {
	case "object"    :  var result = _isFloat(myObject.value); break;
	case "string"    :  var result = _isFloat(myObject);       break;
	case "number"    :  var result = _isFloat(myObject);       break;
	case "undefined" :  alert("Invalid usage of isFloat( Object | String )\nOne parameter is required."); return;
	default          :  alert("Invalid usage of isFloat( Object | String )\nParameter type is unknown."); return;
	}

	if( result ) return true;	// End function & return TRUE;

	// NOT a number ( Integers are permitted to pass );
	if( verbose ) alert('Integer or Decimal value only!');
	if (typeof(myObject)=="object") { myObject.value=myObject.defaultValue; myObject.focus(); }
	return false;
}

function _isFloat( par1 ) {
	if( par1 && (isNaN(par1)) ) return false;
	return true;
}


function _isHex( par1 ) {
	if( par1 ) {
		var result = true;
		for ( var i=0; i<par1.length; i++ ) {
			if(isNaN(parseInt(par1.charAt(i),16))){ if( i !== 1 || par1.charAt(i) !== "x" ){ return false; }}
		}
	}
	return true;
}


function isIPaddress( myObject, verbose ) {
	var myRe = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;

	switch ( typeof(myObject) ) {
	case "object"    :  Trim(myObject); var myArray = myRe.exec(myObject.value); break;
	case "string"    :                  var myArray = myRe.exec(Trim(myObject)); break;
	case "undefined" :  alert("Invalid usage of isIPaddress( Object | String )\nOne parameter is required."); return;
	default          :  alert("Invalid usage of isIPaddress( Object | String )\nParameter type is unknown."); return;
	}

	if ( myArray ) {
		var result = true;
		for ( var i=1; i<5; i++ ) {
			if ( myArray[i] < 0 || myArray[i] > 255 ) { result = false; break; }
		}
		if( result ) return true;	// End function & return TRUE;
	}

	// INVALID FORMAT;
	if( verbose ) alert('Invalid IP address format!\nExpecting ###.###.###.###\nwhere each group of ### is a number between 0 and 255');
	if (typeof(myObject)=="object") { myObject.value=myObject.defaultValue; myObject.focus(); }
	return false;
}

function isSSN( myObject, verbose ) {
	var myRe = /^(\d{3})[-|\s](\d{2})[-|\s](\d{4})$/;

	switch ( typeof(myObject) ) {
	case "object"    :  Trim(myObject); var myArray = myRe.exec(myObject.value); break;
	case "string"    :                  var myArray = myRe.exec(Trim(myObject)); break;
	case "undefined" :  alert("Invalid usage of isSSN( Object | String )\nOne parameter is required."); return;
	default          :  alert("Invalid usage of isSSN( Object | String )\nParameter type is unknown."); return;
	}

	if ( myArray ) {
		if (typeof(myObject)=="object") { myObject.value = myArray[1] + "-" + myArray[2] + "-" + myArray[3]; }
		return true;	// End function & return TRUE;
	}

	// INVALID FORMAT;
	if( verbose ) alert('Invalid SSN format!\nExpecting ###-##-####');
	if (typeof(myObject)=="object") { myObject.value=myObject.defaultValue; myObject.focus(); }
	return false;
}

function isZip( myObject, verbose ) {
	var myRe = /^(\d{5})$|^(\d{5})[-|\s](\d{4})$/;

	switch ( typeof(myObject) ) {
	case "object"    :  Trim(myObject); var myArray = myRe.exec(myObject.value); break;
	case "string"    :                  var myArray = myRe.exec(Trim(myObject)); break;
	case "undefined" :  alert("Invalid usage of isZip( Object | String )\nOne parameter is required."); return;
	default          :  alert("Invalid usage of isZip( Object | String )\nParameter type is unknown."); return;
	}

	if( myArray ) return true;	// End function & return TRUE;

	// INVALID FORMAT;
	if( verbose ) alert('Invalid Zip code.\nExpecting #####[-####]');
	if (typeof(myObject)=="object") { myObject.value=myObject.defaultValue; myObject.focus(); }
	return false;
}

function isEmailAddress( myObject, verbose ) {

	var myRe = /([\w\.\-]+)\@([\w\-]+)\.(\w+[\.\w+]*)$/i;

	switch ( typeof(myObject) ) {
	case "object"    :  Trim(myObject); var myArray = myRe.exec(myObject.value); break;
	case "string"    :                  var myArray = myRe.exec(Trim(myObject)); break;
	case "undefined" :  alert("Invalid usage of isEmailAddress( Object | String )\nOne parameter is required."); return;
	default          :  alert("Invalid usage of isEmailAddress( Object | String )\nParameter type is unknown."); return;
	}

	//alert("$0=" + RegExp.$0 + "\n$1=" + RegExp.$1 + "\n$2=" + RegExp.$2 + "\n$3=" + RegExp.$3 + "\n$4=" + RegExp.$4 + "\n$5=" + RegExp.$5 + "\t")
	//alert( myArray );

	if ( myArray ) return true;	// End function & return TRUE;

	// No match, invalid email format
	if( verbose ) alert('Invalid email address.\nExpecting user@domain.com[.country_code]');
	if (typeof(myObject)=="object") {
		// Restore original value, but if original is nothing do not erase user's typing
		if(myObject.defaultValue != "") { myObject.value=myObject.defaultValue; }
		myObject.focus();
	}
	return false;
}

function isURL( myObject ) {

	switch ( typeof(myObject) ) {
	case "object"    :  Trim(myObject); var str = myObject.value; break;
	case "string"    :                  var str = Trim(myObject); break;
	case "undefined" :  alert("Invalid usage of isEmailAddress( Object | String )\nOne parameter is required."); return;
	default          :  alert("Invalid usage of isEmailAddress( Object | String )\nParameter type is unknown."); return;
	}

	// when URLs start with the following text then assume that complete URL is already specified
	// and don't try to fix anything.

	if(str.indexOf('http://')    ==0)	return true;
	if(str.indexOf('https://')   ==0)	return true;
	if(str.indexOf('ftp://')     ==0)	return true;
	if(str.indexOf('about:')     ==0)	return true;
	if(str.indexOf('mailto:')    ==0)	return true;
	if(str.indexOf('javascript:')==0)	return true;

	if( str=="" ) {
		return true;				// URL string is empty;
	} else {
		if( typeof(myObject) == "object" ) {
			if(str.indexOf('@') > 0) {
			  myObject.value = "mailto:" + str;
			} else {
			  myObject.value = "http://" + str;
			}
		}
		return true;
	}
}


function isMD5Encrypted( myObject ) {

	switch ( typeof(myObject) ) {
	case "object"    :  Trim(myObject); var str = myObject.value; break;
	case "string"    :                  var str = Trim(myObject); break;
	case "undefined" :  alert("Invalid usage of isMD5Encrypted( Object | String )\nOne parameter is required."); return;
	default          :  alert("Invalid usage of isMD5Encrypted( Object | String )\nParameter type is unknown."); return;
	}


	if( str=="" ) {
		return false;				// MD5("") will return a 32 Hex string;
	} else {
		if( _isHex(str) && str.length == 32) {
			return true;
		} else {
			return false;
		}
	}
}


function IsNumber( myObject ) {
	
	switch ( typeof(myObject) ) {
	case "object"    :  var str = myObject.value; break;
	case "string"    :  var str = myObject;       break;
	case "undefined" :  alert("Invalid usage of IsNumber( Object | String )\nOne parameter is required."); return;
	default          :  alert("Invalid usage of IsNumber( Object | String )\nParameter type is unknown."); return;
	}

	if(str.length == 0) return false;

	for(var j = 0; j < str.length; j++) {
		if((str.substring(j,j+1) > '9') || (str.substring(j,j+1) < '0')) return false;
	}

	return true;
}


function Trim(myObject, verbose ) {

	var myRe1 = /^\s*(\S*.*)/i;	// leading spaces
	var myRe2 = /^(.*\S)\s+$/i;	// trailing spaces

	var str, lines, eol, i;
	switch ( typeof(myObject) ) {
	case "object"	:
		if(typeof(myObject.value) == "string") {
			if(myObject.value.length == 0) return;
			if(myObject.value.indexOf("\r\n") > -1) {
				eol = "\r\n";
			} else if(myObject.value.indexOf("\r") > -1) {
				eol = "\r";
			} else {
				eol = "\n";
			}
			lines = myObject.value.split(eol);
			for(i=0; i<lines.length; i++) {
				var myArray = myRe1.exec(lines[i]);
				if ( myArray ) lines[i] = myArray[1];
				var myArray = myRe2.exec(lines[i]);
				if ( myArray ) lines[i] = myArray[1];
			}
			// Remove empty elements from the head and tail of the array (Trim array)
			for(i=0; i<lines.length; i++)    if(lines[i] == "") {lines.shift(); i--;} else break;
			for(i=lines.length-1; i>=0; i--) if(lines[i] == "")  lines.pop();         else break;
			myObject.value = lines.join(eol);
		} else {
			switch ( typeof(myObject.value) ) {
			case "object":
				//alert("Object in object found.\nType=" + myObject.type)
				break;
			default:
				//alert("Type=" + myObject.type)
				break;
			}
		}
		return;
		break;

	case "string"	:
		str = myObject;
		if(str.length == 0) return "";
		if(str.indexOf("\r\n") > -1) {
			eol = "\r\n";
		} else if(str.indexOf("\r") > -1) {
			eol = "\r";
		} else {
			eol = "\n";
		}
		lines = str.split(eol);
		for(i=0; i<lines.length; i++) {
			var myArray = myRe1.exec(lines[i]);
			if ( myArray ) lines[i] = myArray[1];
			var myArray = myRe2.exec(lines[i]);
			if ( myArray ) lines[i] = myArray[1];
		}
		// Remove empty elements from the head and tail of the array (Trim array)

		for(i=0; i<lines.length; i++)    if(lines[i] == "") {lines.shift(); i--;} else break;
		for(i=lines.length-1; i>=0; i--) if(lines[i] == "")  lines.pop();         else break;
		str = lines.join(eol);
		return str;
		break;

	case "undefined" :
		if( verbose ) alert("Invalid usage of Trim( Object | String )\nOne parameter is required.");
		break;
	default		  :
		if( verbose ) alert("Invalid usage of Trim( Object | String )\nParameter type is unknown.");
	}
}

function removeSpaces(form_field) {
	if (!form_field )  return true;
	if ((form_field.value == null) || (form_field.value == "")) return true;
	if ( form_field.value.indexOf(" ") < 0) return true;

	var tmp;
	tmp = "";
	for (var i=0; i < form_field.value.length; i++) {
		if( form_field.value.charAt(i) != " " ) {
			tmp = tmp + form_field.value.charAt(i);
		}
	}
	form_field.value = tmp;
	return true;
}

function getDaysPerMonth(month, year) {
	if (month == 4 || month == 6 || month == 9 || month == 11) {
		return 30;
	} else if (month == 2) {
		return (28 + (year % 4 == 0 ? 1 : 0));
	}

	return 31;
}
