/*
$Id: m4.form.validators.js,v 1.4 2008-02-21 13:12:47 cde Exp $
*/

/******************************************************************************
*** CONSTRUCTOR : m4ValidationUtils
*** 
*** Collection of validation util functions
******************************************************************************/
var m4ValidationUtils={
    isAllDigits : function(argvalue) {
		argvalue = argvalue.toString();
		var validChars = "0123456789";
		var startFrom = 0;
		
		if (argvalue.substring(0, 2) == "0x") {
			validChars = "0123456789abcdefABCDEF";
		 	startFrom = 2;
		} 
		else if (argvalue.charAt(0) == "0") {
			validChars = "01234567";
		 	startFrom = 1;
		} 
		else if (argvalue.charAt(0) == "-") {
		  	startFrom = 1;
		}
		
		for (var n = startFrom; n < argvalue.length; n++) {
		  	if (validChars.indexOf(argvalue.substring(n, n+1)) == -1) return false;
		}
		
		return true;
    },

    /******************************************************************************
    *** isDecimalDigits
    *** CommonsValidator
    ***
    ******************************************************************************/
    isDecimalDigits : function(argvalue) {
        argvalue = argvalue.toString();
        var validChars = "0123456789";

        var startFrom = 0;
        if (argvalue.charAt(0) == "-") {
          startFrom = 1;
        }

        for (var n = startFrom; n < argvalue.length; n++) {
          if (validChars.indexOf(argvalue.substring(n, n+1)) == -1) return false;
        }
        
        return true;
     },
     
    /******************************************************************************
    *** date
    *** CommonsValidator
    *** Reference: Sandeep V. Tamhankar (stamhankar@hotmail.com)
    ***
    ******************************************************************************/
    validateDate : function (value, isStrict) {
    
        function jcv_isValidDate (day, month, year) {
	        if (month < 1 || month > 12) {
                return false;
            }
            if (day < 1 || day > 31) {
                return false;
            }
            if ((month == 4 || month == 6 || month == 9 || month == 11) &&
                (day == 31)) {
                return false;
            }
            if (month == 2) {
                var leap = (year % 4 == 0 &&
                    (year % 100 != 0 || year % 400 == 0));
                if (day>29 || (day == 29 && !leap)) {
                    return false;
                }
            }
            return true;
        }
    
        var bValid = true;
        var i = 0;

        var datePattern = "MM/dd/yyyy";

        var MONTH = "MM";
        var DAY = "dd";
        var YEAR = "yyyy";
        var orderMonth = datePattern.indexOf(MONTH);
        var orderDay = datePattern.indexOf(DAY);
        var orderYear = datePattern.indexOf(YEAR);
        if ((orderDay < orderYear && orderDay > orderMonth))
        {
            var iDelim1 = orderMonth + MONTH.length;
            var iDelim2 = orderDay + DAY.length;
            var delim1 = datePattern.substring(iDelim1, iDelim1 + 1);
            var delim2 = datePattern.substring(iDelim2, iDelim2 + 1);
            if (iDelim1 == orderDay && iDelim2 == orderYear){
            dateRegexp = isStrict 
                    ? new RegExp("^(\\d{2})(\\d{2})(\\d{4})$") 
                    : new RegExp("^(\\d{1,2})(\\d{1,2})(\\d{4})$");
            } else if (iDelim1 == orderDay) {
            dateRegexp = isStrict 
                    ? new RegExp("^(\\d{2})(\\d{2})[" + delim2 + "](\\d{4})$")
                    : new RegExp("^(\\d{1,2})(\\d{1,2})[" + delim2 + "](\\d{4})$");
            } else if (iDelim2 == orderYear) {
            dateRegexp = isStrict
                    ? new RegExp("^(\\d{2})[" + delim1 + "](\\d{2})(\\d{4})$")
                    : new RegExp("^(\\d{1,2})[" + delim1 + "](\\d{1,2})(\\d{4})$");
            } else {
            dateRegexp = isStrict
                    ? new RegExp("^(\\d{2})[" + delim1 + "](\\d{2})[" + delim2 + "](\\d{4})$")
                    : new RegExp("^(\\d{1,2})[" + delim1 + "](\\d{1,2})[" + delim2 + "](\\d{4})$");
            }
            var matched = dateRegexp.exec(value);
            if(matched != null) 
            {
                if (!jcv_isValidDate(matched[2], matched[1], matched[3])) {
                    bValid =  false;
                }
            } 
            else {
                bValid =  false;
            }
        } else if ((orderMonth < orderYear && orderMonth > orderDay)) {
            var iDelim1 = orderDay + DAY.length;
            var iDelim2 = orderMonth + MONTH.length;
            var delim1 = datePattern.substring(iDelim1, iDelim1 + 1);
            var delim2 = datePattern.substring(iDelim2, iDelim2 + 1);
            if (iDelim1 == orderMonth && iDelim2 == orderYear) {
                dateRegexp = isStrict 
                ? new RegExp("^(\\d{2})(\\d{2})(\\d{4})$")
                : new RegExp("^(\\d{1,2})(\\d{1,2})(\\d{4})$");
            } else if (iDelim1 == orderMonth) {
                dateRegexp = isStrict
                ? new RegExp("^(\\d{2})(\\d{2})[" + delim2 + "](\\d{4})$")
                : new RegExp("^(\\d{1,2})(\\d{1,2})[" + delim2 + "](\\d{4})$");
            } else if (iDelim2 == orderYear) {
                dateRegexp = isStrict
                ? new RegExp("^(\\d{2})[" + delim1 + "](\\d{2})(\\d{4})$")
                : new RegExp("^(\\d{1,2})[" + delim1 + "](\\d{1,2})(\\d{4})$");
            } else {
                dateRegexp = isStrict
                ? new RegExp("^(\\d{2})[" + delim1 + "](\\d{2})[" + delim2 + "](\\d{4})$")
                : new RegExp("^(\\d{1,2})[" + delim1 + "](\\d{1,2})[" + delim2 + "](\\d{4})$");
            }
            var matched = dateRegexp.exec(value);
            if(matched != null)
            {
                if (!jcv_isValidDate(matched[1], matched[2], matched[3])) {
                    bValid =  false;
                }
            } else {
                bValid =  false;
            }
        } else if ((orderMonth > orderYear && orderMonth < orderDay)) {
            var iDelim1 = orderYear + YEAR.length;
            var iDelim2 = orderMonth + MONTH.length;
            var delim1 = datePattern.substring(iDelim1, iDelim1 + 1);
            var delim2 = datePattern.substring(iDelim2, iDelim2 + 1);
            if (iDelim1 == orderMonth && iDelim2 == orderDay) {
                dateRegexp = isStrict
                ? new RegExp("^(\\d{4})(\\d{2})(\\d{2})$")
                : new RegExp("^(\\d{4})(\\d{1,2})(\\d{1,2})$");
            } else if (iDelim1 == orderMonth) {
                dateRegexp = isStrict
                ? new RegExp("^(\\d{4})(\\d{2})[" + delim2 + "](\\d{2})$")
                : new RegExp("^(\\d{4})(\\d{1,2})[" + delim2 + "](\\d{1,2})$");
            } else if (iDelim2 == orderDay) {
                dateRegexp = isStrict
                ? new RegExp("^(\\d{4})[" + delim1 + "](\\d{2})(\\d{2})$")
                : new RegExp("^(\\d{4})[" + delim1 + "](\\d{1,2})(\\d{1,2})$");
            } else {
                dateRegexp = isStrict
                ? new RegExp("^(\\d{4})[" + delim1 + "](\\d{2})[" + delim2 + "](\\d{2})$")
                : new RegExp("^(\\d{4})[" + delim1 + "](\\d{1,2})[" + delim2 + "](\\d{1,2})$");
            }
            var matched = dateRegexp.exec(value);
            if(matched != null) {
                if (!jcv_isValidDate(matched[3], matched[2], matched[1])) {
                    bValid =  false;
                }
            } else {
                bValid =  false;
            }
        }         
        return bValid;
    }
}

/******************************************************************************
*** CONSTRUCTOR : m4ValidationRoutine
***
*** List of Validators
*** 
*** ADD ANY CUSTOM VALIDATORS BELOW
******************************************************************************/
var m4ValidationRoutine={

    /******************************************************************************
    *** email
    *** CommonsValidator
    ******************************************************************************/
    email : function(emailStr) {
        if (emailStr.length == 0) {
            return true;
        }
        // TLD checking turned off by default
        var checkTLD=0;
        var knownDomsPat=/^(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum)$/;
        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];
        for (i=0; i<user.length; i++) {
            if (user.charCodeAt(i)>127) {
                return false;
            }
        }
        for (i=0; i<domain.length; i++) {
            if (domain.charCodeAt(i)>127) {
                return false;
            }
        }
        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 atomPat=new RegExp("^" + atom + "$");
        var domArr=domain.split(".");
        var len=domArr.length;
        for (i=0;i<len;i++) {
            if (domArr[i].search(atomPat)==-1) {
                return false;
            }
        }
        if (checkTLD && domArr[domArr.length-1].length!=2 && 
            domArr[domArr.length-1].search(knownDomsPat)==-1) {
            return false;
        }
        if (len<2) {
            return false;
        }
        return true;
    },
    
    date : function(value)
    {
        return m4ValidationUtils.validateDate(value,false);
    },
    
    strictDate : function(value)
    {
        return m4ValidationUtils.validateDate(value,true);
    },
    
    dateTime : function(value,el)
    {
	    var parts=[["%y","\\d{2}","yy","year"],
				   ["%Y","\\d{4}","YYYY","year"],
				   ["%m","\\d{2}","mm","month"],
				   ["%d","\\d{2}","dd","day"],
				   ["%H","\\d{2}","HH","hour"],
				   ["%M","\\d{2}","MM","min"],
				   ["%S","\\d{2}","SS","sec"]];	
    	
    	function modifyFormatStr(format,type)
    	{
    		var s=format;
    		
    		for (var i=0;i<parts.length;i++)
    		{
    			s=s.replaceAll(parts[i][0],parts[i][type]);
    		}
    		
    		return s;    	
    	}

    	//Generate a regular expression from the passed in date format
    	var format=el.getAttribute("dateFormat");
    	var reg=modifyFormatStr(format,1);
    	reg="^"+reg+"$";
    
    	//Validate the format of the string
    	var re =new RegExp(reg,"g");
    	var validFormat=re.test(value);
		if (!validFormat) return false;

		//Generate a string in the format yyyy/dd/mm from %YY/%dd/%mm
    	var matchFormat=modifyFormatStr(format,2);
    	
    	var dateObj={year:2008,month:1,day:1,hour:1,min:1,sec:1};
    
    	//Use the matchFormat string to parse the passed in date
    	for (var i=0;i<parts.length;i++)
    	{
   			var part=parts[i][2];
    		var pos=matchFormat.indexOf(part);
    		
    		if (pos>=0){
    			var val=value.substr(pos,part.length);
    			dateObj[parts[i][3]]=val;
    		}
    	}
		
		//Pad time
		if (String(dateObj.hour).length==1) dateObj.hour="0"+dateObj.hour;
		if (String(dateObj.min).length==1) dateObj.min="0"+dateObj.min;
		if (String(dateObj.sec).length==1) dateObj.sec="0"+dateObj.sec; 

		//Generate date and time string to validate
    	var vDate=dateObj.month+"/"+dateObj.day+"/"+dateObj.year;
    	var vTime=dateObj.hour+":"+dateObj.min+":"+dateObj.sec;

    	//Validate date & time
    	var validDate=m4ValidationUtils.validateDate(vDate,false);
		var validTime=m4ValidationRoutine.time(vTime);
    
    	return validDate && validTime;
    },
    
    time : function(value)
    {
  	  	var re=/^((([0]?[1-9]|1[0-2])(:|\.)[0-5][0-9]((:|\.)[0-5][0-9])?( )?(AM|am|aM|Am|PM|pm|pM|Pm))|(([0]?[0-9]|1[0-9]|2[0-3])(:|\.)[0-5][0-9]((:|\.)[0-5][0-9])?))$/;
    
    	return (re.test(value));
    },
    
    alphaNumeric : function(value)
    {
        re= /^[\w ]*$/i;
        return re.test(value);     
    },
    
    number : function(value) {
        var bValid = true;
        
        if (value.length > 0) {
            if (!m4ValidationUtils.isDecimalDigits(value)) {
                bValid = false;
           }
       }

       return bValid;
    },
     text : function(value)
    {
        re= /^[a-z ]*$/i;
        return re.test(value);     
    },
    
    decimal : function(value)
    {
        var bValid = true;

        if (value.length > 0) {
            // remove '.' before checking digits
            var tempArray = value.split('.');
            //Strip off leading '0'
            var zeroIndex = 0;
            var joinedString= tempArray.join('');
            while (joinedString.charAt(zeroIndex) == '0') 
            {
                zeroIndex++;
            }
            var noZeroString = joinedString.substring(zeroIndex,joinedString.length);

            if (!m4ValidationUtils.isAllDigits(noZeroString) || tempArray.length > 2)
            {
                bValid = false;
            } 
            else 
            {
	            var iValue = parseFloat(value);
	            if (isNaN(iValue)) {
	                bValid = false;
	            }
            }
        }

        return bValid;
    },
    
    consoleCommand : function(value)
    {
        //No validation specified yet
        return true;
        
    },
    
    ip : function(IPvalue) {
        var ipPattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
        var ipArray = IPvalue.match(ipPattern); 

        if (IPvalue == "0.0.0.0")
           return false;
        else if (IPvalue == "255.255.255.255")
            return false;
        if (ipArray == null)
           return false;
        else {
            for (i = 0; i < 4; i++) {
                thisSegment = ipArray[i];
                if (thisSegment > 255) {
                    return false;
                    i = 4;
                }
                if ((i == 0) && (thisSegment > 255)) {
                    return false;
                    i = 4;
                }
            }
        }
        
        return true;
    },

    port : function(strPort){
        var intPort=Number(strPort);

        if (isNaN(intPort))
        {
           return false;
        }
        else if (intPort<1 || intPort>65535){
            return false;
        }
        
        return true;
    }   
}