function validateFields (rfObjArray) 
{
    for (var i = 0; i < rfObjArray.length; i++) {
        if (rfObjArray[i].obj.value == "") {
            alert(rfObjArray[i].msg);
            return false;
        }
    }
    return true;
}

function validateNotEmpty( strValue ) {
    /************************************************
DESCRIPTION: Validates that a string is not all
  blank (whitespace) characters.

PARAMETERS:
   strValue - String to be tested for validity

RETURNS:
   True if valid, otherwise false.
*************************************************/
    var strTemp = strValue;
    strTemp = trimAll(strTemp);
    if(strTemp.length > 0){
        return true;
    }
    return false;
}

// formatPhoneNumber - takes the field itself and outputs the given phone number in the format xxx-xxx-xxxx xxxx
// It also trys to help people put area codes
function formatPhoneNumber(obj)
{
    if (obj == null || obj.value == null || isEmpty(obj.value))
    {
        return;
    }
    value = extractDigits(obj.value);
    if (value.length < 10)
    {
        value = "???" + value;
    }
    formattedValue = "";
    for (i=0; i<value.length; i++) {
        if (i == 3 || i == 6) {
            formattedValue += '-';
        }
        else if (i==10) 
        {
            formattedValue += ' ';
        }
        formattedValue += value.charAt(i);
    }
    obj.value = formattedValue;
}
// extractDigits - a utility method to return just the number digits within a given string value
function extractDigits(field) {
    if (field == null || field == "") {
        return "";
    }
    digits = "0123456789";
    newField = "";
    for(i=0; i<field.length; i++) {
        if (digits.indexOf(field.charAt(i)) >= 0) {
            newField += field.charAt(i);
        }
    }
    return newField;
}
function requiredField (fieldObj, msg) {
    this.obj = fieldObj;
    this.msg = msg;
}
/**
  A collection of functions for formatting and validating form elements.
 */
function checkdate(objName) 
{
    var datefield = objName;
    if (validDate(objName) == false) {
        datefield.select();
        //alert("That date is invalid.  Please try again.");
        datefield.focus();
        return false;
    } else {
        return true;
    }
}
	
function validDate(objName) 
{
    var strDatestyle = "US"; //United States date style
    //var strDatestyle = "EU";  //European date style
    var strDate;
    var strDateArray;
    var strDay;
    var strMonth;
    var strYear;
    var intday;
    var intMonth;
    var intYear;
    var booFound = false;
    var datefield = objName;
    var strSeparatorArray = new Array("-"," ","/",".");
    var intElementNr;
    var err = 0;
    var strMonthArray = new Array(12);
    strMonthArray[0] = "01";
    strMonthArray[1] = "02";
    strMonthArray[2] = "03";
    strMonthArray[3] = "04";
    strMonthArray[4] = "05";
    strMonthArray[5] = "06";
    strMonthArray[6] = "07";
    strMonthArray[7] = "08";
    strMonthArray[8] = "09";
    strMonthArray[9] = "10";
    strMonthArray[10] = "11";
    strMonthArray[11] = "12";
    strDate = datefield.value;
		
    if ((strDate.length > 0) && (strDate.length < 4)) {
        alert("That date is invalid.  Please try again.");
        return false;
    } else {
        if (strDate.length < 1) {
            return true;
        }
    }
		
    for (intElementNr = 0; intElementNr < strSeparatorArray.length; intElementNr++) {
        if (strDate.indexOf(strSeparatorArray[intElementNr]) != -1) {
            strDateArray = strDate.split(strSeparatorArray[intElementNr]);
            if (strDateArray.length != 3) {
                err = 1;
                alert("That date is invalid.  Please try again.");
                return false;
            } else {
                strDay = strDateArray[0];
                strMonth = strDateArray[1];
                strYear = strDateArray[2];
            }
            booFound = true;
        }
    }
		
    if (booFound == false) {
        if (strDate.length > 4) {
            strDay = strDate.substr(0, 2);
            strMonth = strDate.substr(2, 2);
            strYear = strDate.substr(4);
        } else {
            if (strDate.length == 4) {
                strDay = strDate.substr(0, 1);
                strMonth = strDate.substr(1, 1);
                strYear = strDate.substr(2);
            }
        }
    }
		
    if (strYear.length == 2) {
        var today = new Date();
        if (parseInt(strYear) + 2000 <= today.getFullYear()) {
            strYear = '20' + strYear;
        } else {
            strYear = '19' + strYear; 
        }
    } else {
        if (strYear.length == 3 || strYear.length < 2 || strYear.length > 4) {
            alert("Invalid Year format.  Must be yy or yyyy.");
            return false;
        }
    }
		
    //if (strYear.length == 4 && strYear.substr(0, 1) != '2') {
    //	alert("The year '" + strYear + "' is invalid.");
    //	return false;
    //}
		
    // US style
    if (strDatestyle == "US") {
        strTemp = strDay;
        strDay = strMonth;
        strMonth = strTemp;
    }
		
    intday = parseInt(strDay, 10);
    if (isNaN(intday)) {
        err = 2;
        alert("Invalid Day format.  Must be d or dd.");
        return false;
    }
		
    if (intday < 10) {
        strDay = '0' + intday;
    }
		
    intMonth = parseInt(strMonth, 10);
    if (isNaN(intMonth)) {
        for (i = 0;i<12;i++) {
            if (strMonth == strMonthArray[i]) {
                intMonth = i+1;
                strMonth = strMonthArray[i];
                i = 12;
            }
        }
        if (isNaN(intMonth)) {
            err = 3;
            alert("Invalid Month format.  Must be m or mm.");
            return false;
        }
    }
		
    intYear = parseInt(strYear, 10);
    if (isNaN(intYear)) {
        err = 4;
        alert("Invalid Year format.  Must be yy or yyyy.");
        return false;
    }
    if (intMonth > 12 || intMonth < 1) {
        err = 5;
        alert("'" + intMonth + "' is not a valid month.");
        return false;
    }
    if ((intMonth == 1 || intMonth == 3 || intMonth == 5 || intMonth == 7 || intMonth == 8 || intMonth == 10 || intMonth == 12) && (intday > 31 || intday < 1)) {
        err = 6;
        alert("Invalid Day. Must be between 1 and 31.");
        return false;
    }
    if ((intMonth == 4 || intMonth == 6 || intMonth == 9 || intMonth == 11) && (intday > 30 || intday < 1)) {
        err = 7;
        alert("Invalid Day. Must be between 1 and 30.");
        return false;
    }
		
    if (intMonth == 2) {
        if (intday < 1) {
            err = 8;
            alert("Invalid Day. Cannot be less than 1.");
            return false;
        }
        if (LeapYear(intYear) == true) {
            if (intday > 29) {
                err = 9;
                alert("Invalid Day. February has 29 days in " + intYear + " (Leap Year).");
                return false;
            }
        } else {
            if (intday > 28) {
                err = 10;
                alert("Invalid Day. February has 28 days in " + intYear + ".");
                return false;
            }
        }
    }
		
    if (strDatestyle == "US") {
        datefield.value = strMonthArray[intMonth-1] + "/" + strDay +"/" + strYear;
    } else {
        datefield.value = strDay + "." + strMonthArray[intMonth-1] + "." + strYear;
    }
    return true;
}
	
function LeapYear(intYear)
{
    if (intYear % 100 == 0) {
        if (intYear % 400 == 0) {
            return true;
        }
    } else {
        if ((intYear % 4) == 0) { 
            return true;
        }
    }
    return false;
}

/*******************************************************************************
FILE: RegExpValidate.js

DESCRIPTION: This file contains a library of validation functions
  using javascript regular expressions.  Library also contains functions that re-
  format fields for display or for storage.


  VALIDATION FUNCTIONS:

  isEmailValid - checks format of email address
  isUSPhoneValid- checks format of US phone number
  isNumericValid- checks for valid numeric value
  isIntegerValid- checks for valid integer value
  isNotEmpty - checks for blank form field
  isUSZipValid- checks for valid US zip code
  isUSDateValid- checks for valid date in US format
  isValueValid- checks a string against supplied pattern

  FORMAT FUNCTIONS:

  rightTrim - removes trailing spaces from a string
  leftTrim - removes leading spaces from a string
  trimAll - removes leading and trailing spaces from a string
  removeCurrency - removes currency formatting characters (), $
  addCurrency - inserts currency formatting characters
  removeCommas - removes comma separators from a number
  addCommas - adds comma separators to a number
  removeCharacters - removes characters from a string that match passed pattern


AUTHOR: Karen Gayda

DATE: 03/24/2000
 *******************************************************************************/

function isEmailValid( strValue) 
{
    /************************************************
DESCRIPTION: issValidthat a string contains a
  valid email pattern.

 PARAMETERS:
   strValue - String to be tested for validity

RETURNS:
   True if valid, otherwise false.

REMARKS: Accounts for email with country appended
  does not validate that email contains valid URL
  type (.com, .gov, etc.) or valid country suffix.
     *************************************************/
    var objRegExp  =
    /(^[a-z0-9]([a-z0-9_\.\-]*)@([a-z0-9_\.\-]*)([.][a-z]+)$)/i;

    //check for valid email
    return objRegExp.test(strValue);
}

function isStateCodeValid(strValue)
{
    if (strValue == '' || strValue.length != 2)
    {
        return false;
    }
    strValue = strValue.toUpperCase();
    return "AL,AK,AZ,AR,CA,CO,CT,DE,FL,GA,HI,ID,IL,IN,IA,KS,KY,LA,ME,MD,MA,MI,MN,MS,MO,MT,NE,NV,NH,NJ,NM,NY,NC,ND,OH,OK,OR,PA,RI,SC,SD,TN,TX,UT,VT,VA,WA,WV,WI,WY,".
    indexOf(strValue + ",") != -1;
}

function isUSPhone(strValue )
{
    /************************************************
DESCRIPTION: Validates that a string contains valid
  US phone pattern.
  Ex. 999-999-9999 or 999-999-9999

PARAMETERS:
   strValue - String to be tested for validity

RETURNS:
   True if valid, otherwise false.
     *************************************************/
    var objRegExp  = /\d{3}\-\d{3}\-\d{4}$/;

    //check for valid us phone with or without space between
    //area code
    return objRegExp.test(strValue);
}

function  isNumeric(strValue ) 
{
    /******************************************************************************
DESCRIPTION: Validates that a string contains only valid numbers.

PARAMETERS:
   strValue - String to be tested for validity

RETURNS:
   True if valid, otherwise false.
     ******************************************************************************/
    var objRegExp  =  /(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/;

    //check for numeric characters
    return objRegExp.test(strValue);
}

function isInteger(strValue ) 
{
    /************************************************
DESCRIPTION: Validates that a string contains only
    valid integer number.

PARAMETERS:
   strValue - String to be tested for validity

RETURNS:
   True if valid, otherwise false.
     ******************************************************************************/
    var objRegExp  = /(^-?\d\d*$)/;

    //check for integer characters
    return objRegExp.test(strValue);
}

function isNotEmpty( strValue ) 
{
    /************************************************
DESCRIPTION: Validates that a string is not all
  blank (whitespace) characters.

PARAMETERS:
   strValue - String to be tested for validity

RETURNS:
   True if valid, otherwise false.
     *************************************************/
    var strTemp = strValue;
    strTemp = trimAll(strTemp);
    if(strTemp.length > 0){
        return true;
    }
    return false;
}

function isEmpty( strValue)
{
    return !isNotEmpty(strValue);
}

function isUSZip(strValue ) 
{
    /************************************************
DESCRIPTION: Validates that a string a United
  States zip code in 5 digit format or zip+4
  format. 99999 or 99999-9999

PARAMETERS:
   strValue - String to be tested for validity

RETURNS:
   True if valid, otherwise false.

     *************************************************/
    var objRegExp  = /(^\d{5}$)|(^\d{5}-\d{4}$)/;

    //check for valid US Zipcode
    return objRegExp.test(strValue);
}


function isValue(strValue, strMatchPattern ) 
{
    /************************************************
DESCRIPTION: Validates that a string a matches
  a valid regular expression value.

PARAMETERS:
   strValue - String to be tested for validity
   strMatchPattern - String containing a valid
      regular expression match pattern.

RETURNS:
   True if valid, otherwise false.
     *************************************************/
    var objRegExp = new RegExp( strMatchPattern);

    //check if string matches pattern
    return objRegExp.test(strValue);
}


function rightTrim( strValue ) 
{
    /************************************************
DESCRIPTION: Trims trailing whitespace chars.

PARAMETERS:
   strValue - String to be trimmed.

RETURNS:
   Source string with right whitespaces removed.
     *************************************************/
    var objRegExp = /^([\w\W]*)(\b\s*)$/;

    if(objRegExp.test(strValue)) {
        //remove trailing a whitespace characters
        strValue = strValue.replace(objRegExp, '$1');
    }
    return strValue;
}

function leftTrim( strValue ) 
{
    /************************************************
DESCRIPTION: Trims leading whitespace chars.

PARAMETERS:
   strValue - String to be trimmed

RETURNS:
   Source string with left whitespaces removed.
     *************************************************/
    var objRegExp = /^(\s*)(\b[\w\W]*)$/;

    if(objRegExp.test(strValue)) {
        //remove leading a whitespace characters
        strValue = strValue.replace(objRegExp, '$2');
    }
    return strValue;
}

function trimAll( strValue ) 
{

    /************************************************
DESCRIPTION: Removes leading and trailing spaces.

PARAMETERS: Source string from which spaces will
  be removed;

RETURNS: Source string with whitespaces removed.
     *************************************************/
    var objRegExp = /^(\s*)$/;

    //check for all spaces
    if(objRegExp.test(strValue)) 
    {
        strValue = strValue.replace(objRegExp, '');
        if( strValue.length == 0)
        {
            return strValue;
        }

        //check for leading & trailing spaces
        objRegExp = /^(\s*)([\W\w]*)(\b\s*$)/;
        if(objRegExp.test(strValue)) 
        {
            //remove leading and trailing whitespace characters
            strValue = strValue.replace(objRegExp, '$2');
        }
        return strValue;
    }
    return strValue;
}

function removeCurrency( strValue ) 
{
    /************************************************
DESCRIPTION: Removes currency formatting from
  source string.

PARAMETERS:
  strValue - Source string from which currency formatting
     will be removed;

RETURNS: Source string with commas removed.
     *************************************************/
    var objRegExp = /\(/;
    var strMinus = '';

    //check if negative
    if(objRegExp.test(strValue))
    {
        strMinus = '-';
    }

    objRegExp = /\)|\(|[,]/g;
    strValue = strValue.replace(objRegExp,'');
    if(strValue.indexOf('$') >= 0)
    {
        strValue = strValue.substring(1, strValue.length);
    }
    return strMinus + strValue;
}

function addCurrency( strValue ) 
{
    /************************************************
DESCRIPTION: Formats a number as currency.

PARAMETERS:
  strValue - Source string to be formatted

REMARKS: Assumes number passed is a valid
  numeric value in the rounded to 2 decimal
  places.  If not, returns original value.
     *************************************************/
    var objRegExp = /-?[0-9]+\.[0-9]{2}$/;

    if( objRegExp.test(strValue)) 
    {
        objRegExp.compile('^-');
        strValue = addCommas(strValue);
        if (objRegExp.test(strValue)){
            strValue = '(' + strValue.replace(objRegExp,'') + ')';
        }
        return '$' + strValue;
    }
    else
    {
        return strValue;
    }
}

function removeCommas( strValue ) 
{
    /************************************************
DESCRIPTION: Removes commas from source string.

PARAMETERS:
  strValue - Source string from which commas will
    be removed;

RETURNS: Source string with commas removed.
     *************************************************/
    var objRegExp = /,/g; //search for commas globally

    //replace all matches with empty strings
    return strValue.replace(objRegExp,'');
}

function addCommas( strValue ) 
{

    /************************************************
DESCRIPTION: Inserts commas into numeric string.

PARAMETERS:
  strValue - source string containing commas.

RETURNS: String modified with comma grouping if
  source was all numeric, otherwise source is
  returned.

REMARKS: Used with integers or numbers with
  2 or less decimal places.
     *************************************************/
    var objRegExp  = new RegExp('(-?[0-9]+)([0-9]{3})');

    //check for match to search criteria
    while(objRegExp.test(strValue)) 
    {
        //replace original string with first group match,
        //a comma, then second group match
        strValue = strValue.replace(objRegExp, '$1,$2');
    }
    return strValue;
}

function removeCharacters( strValue, strMatchPattern ) 
{

    /************************************************
DESCRIPTION: Removes characters from a source string
  based upon matches of the supplied pattern.

PARAMETERS:
  strValue - source string containing number.

RETURNS: String modified with characters
  matching search pattern removed

USAGE:  strNoSpaces = removeCharacters( ' sfdf  dfd',
                                '\s*')
     *************************************************/
    var objRegExp =  new RegExp( strMatchPattern, 'gi' );

    //replace passed pattern matches with blanks
    return strValue.replace(objRegExp,'');
}

//onkeypress="error.innerHTML=capsLockCheck(arguments[0])"
function capsLockCheck( e ) 
{
    if( !e ) { 
        e = window.event;
    }
    if( !e ) { 
        return ""
    }
    //what (case sensitive in good browsers) key was pressed
    var theKey = e.which ? e.which : ( e.keyCode ? e.keyCode : ( e.charCode ? e.charCode : 0 ) );
    //was the shift key was pressed
    var theShift = e.shiftKey || ( e.modifiers && ( e.modifiers & 4 ) ); //bitWise AND
    //if upper case, check if shift is not pressed. if lower case, check if shift is pressed
    if (( theKey > 64 && theKey < 91 && !theShift ) || ( theKey > 96 && theKey < 123 && theShift ))
    {
        return "Caps Lock is on.  Passwords are case sensative.";
    }
    else
    {
        return "";
    }
}

/* ************************************************************
Created: 20060120
Author:  Steve Moitozo <god at zilla dot us>
Description: This is a quick and dirty password quality meter 
		 written in JavaScript
License: MIT License (see below)
=================================
Revision Author: Dick Ervasti (dick dot ervasti at quty dot com)
Revision Description: Exchanged text based prompts for a graphic thermometer
=================================
Revision Author: Jay Bigam jayb <o> tearupyourlawn <o> com
Revision Date: Feb. 26, 2007
Revision Description: Changed D. Ervasti's table based "thermometer" to CSS.
Revision Notes: - Verified to work in FF2, IE7 and Safari2
                - Modified messages to reflect Minimum strength requirement
                - Added formSubmit button disabled until minimum requirement met
=================================
Modified: 20061111 - Steve Moitozo corrected regex for letters and numbers
                     Thanks to Zack Smith -- zacksmithdesign.com
                     and put MIT License back in
					 
---------------------------------------------------------------
Copyright (c) 2006 Steve Moitozo <god at zilla dot us>
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
   The above copyright notice and this permission notice shall
be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.
---------------------------------------------------------------
 ************************************************************ */
function testPassword(passwd)
{
    var description = new Array();
    description[0] = "Unsafe";
    description[1] = "Weak";
    description[2] = "Fair";
    description[3] = "Good";
    description[4] = "Strong";
    description[5] = "Begin Typing";
    var intScore   = 0
    var strVerdict = 0
		
    // PASSWORD LENGTH
    if (passwd.length==0 || !passwd.length)                         // length 0
    {
        intScore = -1
    }
    else if (passwd.length>0 && passwd.length<5) // length between 1 and 4
    {
        intScore = (intScore+3)
    }
    else if (passwd.length>4 && passwd.length<8) // length between 5 and 7
    {
        intScore = (intScore+6)
    }
    else if (passwd.length>7 && passwd.length<12)// length between 8 and 15
    {
        intScore = (intScore+12)
    }
    else if (passwd.length>11)                    // length 16 or more
    {
        intScore = (intScore+18)
    }
		
		
    // LETTERS (Not exactly implemented as dictacted above because of my limited understanding of Regex)
    if (passwd.match(/[a-z]/))                              // [verified] at least one lower case letter
    {
        intScore = (intScore+1)
    }
		
    if (passwd.match(/[A-Z]/))                              // [verified] at least one upper case letter
    {
        intScore = (intScore+5)
    }
		
    // NUMBERS
    if (passwd.match(/\d+/))                                 // [verified] at least one number
    {
        intScore = (intScore+5)
    }
		
    if (passwd.match(/(.*[0-9].*[0-9].*[0-9])/))             // [verified] at least three numbers
    {
        intScore = (intScore+5)
    }	
		
    // SPECIAL CHAR
    if (passwd.match(/.[!,@,#,$,%,^,&,*,?,_,~]/))            // [verified] at least one special character
    {
        intScore = (intScore+5)
    }
		
    // [verified] at least two special characters
    if (passwd.match(/(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])/))
    {
        intScore = (intScore+5)
    }
		
    // COMBOS
    if (passwd.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/))        // [verified] both upper and lower case
    {
        intScore = (intScore+2)
    }
    if (passwd.match(/([a-zA-Z])/) && passwd.match(/([0-9])/)) // [verified] both letters and numbers
    {
        intScore = (intScore+2)
    }
    // [verified] letters, numbers, and special characters
    if (passwd.match(/([a-zA-Z0-9].*[!,@,#,$,%,^,&,*,?,_,~])|([!,@,#,$,%,^,&,*,?,_,~].*[a-zA-Z0-9])/))
    {
        intScore = (intScore+7)
    }
    // Not having a combo or enough length is docked a ton
    if (passwd.match(/^\d+$/) || passwd.match(/^[a-zA-Z]+$/) || (passwd.length < 5)) 
    {
        intScore = (intScore-20)
        if (intScore < 0)
            intScore = 0
    }
	
    var valid = true;
    if(intScore == -1)
    {
        strVerdict = description[5];
        document.getElementById("meterEmpty").style.width= "100%";
        document.getElementById("meterFull").style.width= "0";
        valid = false;
    }
    else if(intScore > -1 && intScore < 9)
    {
        strVerdict = description[0];
        document.getElementById("meterEmpty").style.width= "100%";
        document.getElementById("meterFull").style.width= "0%";
        valid = false;
    }
    else if (intScore > 8 && intScore < 16)
    {
        strVerdict = description[1];
        document.getElementById("meterEmpty").style.width= "100%";
        document.getElementById("meterFull").style.width= "25%";
    }
    else if (intScore > 15 && intScore < 27)
    {
        strVerdict = description[2];
        document.getElementById("meterEmpty").style.width= "100%";
        document.getElementById("meterFull").style.width= "50%";
    }
    else if (intScore > 26 && intScore < 34)
    {
        strVerdict = description[3];
        document.getElementById("meterEmpty").style.width= "100%";
        document.getElementById("meterFull").style.width= "75%";
    }
    else
    {
        strVerdict = description[4];
        document.getElementById("meterEmpty").style.width= "100%";
        document.getElementById("meterFull").style.width= "100%";
    }
	
    document.getElementById("Words").innerHTML= (strVerdict);
    return valid;
}

function isSsnValid(string)
{
    var area = string.substring(0,3);
    var group = string.substring(4,6);
    var sn = string.substring(7);

    var valid = false;
    var firstDigit = string.charAt(0);
    for (var i = 1 ; i < string.length ; i++)
    {
        var c = string.charAt(i);
        if ((c != '-') && (c != firstDigit))
        {
            valid = true;
            break;
        }
    }

    return ((area.length == 3) && (group.length == 2) && (sn.length == 4) &&
        (sn != "0000") && (area != "000") && (area != "666") &&
        (string.match("[0-9]{3}-[0-9]{2}-[0-9]{4}")) && valid);
}