//////////////////////////////////////////////////
// Copywrite (c) 2004 by America Online, Inc.
// All Rights Reserved
//
// File:        email_validation.js
//
// Facility:    Parkview
//
// Abstract:    Javascript to check that email address format
//              conforms to industry standards per RFC document
//              RFC 3696.
//
// Environment: Linux
//
// Author:      Patrick Flannery
//
// Created:     May 10, 2004
//
//////////////////////////////////////////////////


//////////////////////////////////////////////////
// check_email_addr()
//
//	- Wrapper function which goes through RFC rules
//    for valid email addresses.
//
//	Input:  string representing email addresses
//	Output: true (valid address) / false (invalid address)
/////////////////////////////////////////////////
function check_email_addr(email_address)
{
	email_address = trim(email_address);
    // RULE: Check length is <= 255 chars
    if (email_address.length > 255)
        return false;

    // RULE: Check that "@" exists
    var at_symbol_idx = email_address.indexOf("@");

    // Check that @ sign is not quoted:
    // RULE: @ may exist outside of local/domain separator if quoted

    // Confirm that @ not escaped with a backslash
    var char_before_at = email_address.charAt(at_symbol_idx-1);
    // while backslash proceeds @, keep looping
    while (char_before_at == "\\")
    {
        at_symbol_idx  = email_address.indexOf("@", at_symbol_idx+1);
        char_before_at = email_address.charAt(at_symbol_idx-1)
    }

    //check that @ not enclosed in double-quotes
    var first_double_quote = email_address.indexOf("\"");
    var last_double_quote  = email_address.lastIndexOf("\"");
    while (at_symbol_idx > first_double_quote && at_symbol_idx < last_double_quote)
    {
        at_symbol_idx  = email_address.indexOf("@", at_symbol_idx+1);
    }

    if (at_symbol_idx == -1)
        return false;

    // Split address into "local" and "domain" parts
    var local_part  = email_address.substring(0, at_symbol_idx);
    var domain_part = email_address.substring(at_symbol_idx+1, email_address.length);

    // Call function to check "local" part
    if (!check_local(local_part))
        return false;

    // Call function to check "domain" part
    if (!check_domain(domain_part))
        return false;

    // If past all checks, return true
    return true;
}

//////////////////////////////////////////////////
// check_domain()
//
//	- Checks "domain" part of email address based on
//    rules in "Section 2" of RFC
//
//	Input:  string representing domain
//	Output: true (valid domain) / false (invalid domain)
/////////////////////////////////////////////////
function check_domain(domain_name)
{
    // RULE: check length not > 255
    if (domain_name.length > 255)
        return false;

    // RULE: for all intents and purposes, must contain at least one period
    if (domain_name.indexOf(".") == -1)
        return false;

    var regexp_label = /[^\w\.\-]/;

    // RULE: labels may be alphanumeric and a hyphen
    if (regexp_label.test(domain_name))
    {
        return false;
    }
    // RULE: if a hyphen is used, it may not appear at the beginning or end
    var hyphen_index = domain_name.indexOf("-");
    if (hyphen_index == 0 || hyphen_index == (domain_name.length -1))
        return false;

    // RULE: each label can be no longer than 63 characters
    var label_array = domain_name.split(".");
    for (var i=0; i < label_array.length; i++)
    {
        if (label_array[i].length > 63)
            return false;
    }

    // RULE: a TLD (top-level domain) may not be all-numeric


    // If past all checks, return true
    return true;
}

//////////////////////////////////////////////////
// check_local()
//
//	- Checks "local" part of email address based on
//    rules in "Section 3" of RFC
//
//	Input:  string representing local_part
//	Output: true (valid domain) / false (invalid domain)
/////////////////////////////////////////////////
function check_local(local_part)
{
    // RULE: check length not > 64
    if (local_part.length > 64)
        return false;

    // RULE: If there are enclosing quotes, any character is allowed.
    var first_double_quote = local_part.indexOf("\"");
    var last_double_quote  = local_part.lastIndexOf("\"");
    if (first_double_quote == 0 && last_double_quote == (local_part.length - 1))
    {
        // any enclosed character is allowed, return true
        return true;
    }

    // RULE: if not quoted, @ " , [ ] are invalid characters
    var invalid_chars = "@ \" , [ ]";
    var regexp_invalid = /[@|\"|\,|\[|\]]/;

    // if local_part contains any of these possible invalid chars
    if (regexp_invalid.test(local_part))
    {
        // loop through characters to see if invalid ones are escaped
        // RULE: any character is allowed if escaped with a backslash
        var last_character;
        var curr_character;
        for (var i=0; i < local_part.length; i++)
        {
            curr_character = local_part.charAt(i);
            if(invalid_chars.indexOf(curr_character) != -1)
            {
                // if first character, it is not escape
                if (i == 0)
                    return false;

                // if last character was not a backslash
                if (last_character != "\\")
                    return false;
            }
            last_character = curr_character;
        }
    }
    // RULE NOTE: apostrophe (') and acute accent (`) are not considered quoting characters

    // RULE: a period (".") may not start or end local part, nor may appear consecutively
    var first_period = local_part.indexOf("\.");
    var last_period  = local_part.lastIndexOf("\.");
    // if period is first or last, return false
    if (first_period == 0 || last_period == (local_part.length - 1))
        return false;
    // if consecutive periods, return false
    if (local_part.indexOf("..") != -1)
        return false;

    // If past all checks, return true
    return true;
}
