////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package mx.validators
{

[ResourceBundle("validators")]
    
/**
 *  The EmailValidator class validates that a String has a single &#64; sign,
 *  a period in the domain name and that the top-level domain suffix has
 *  two, three, four, or six characters.
 *  IP domain names are valid if they are enclosed in square brackets. 
 *  The validator does not check whether the domain and user name
 *  actually exist.
 *
 *  <p>You can use IP domain names if they are enclosed in square brackets; 
 *  for example, myname&#64;[206.132.22.1].
 *  You can use individual IP numbers from 0 to 255.</p>
 *  
 *  @mxml
 *
 *  <p>The <code>&lt;mx:EmailValidator&gt;</code> tag
 *  inherits all of the tag attributes of its superclass,
 *  and adds the following tag attributes:</p>
 *  
 *  <pre>
 *  &lt;mx:EmailValidator 
 *    invalidCharError="Your e-mail address contains invalid characters."
 *    invalidDomainError= "The domain in your e-mail address is incorrectly formatted." 
 *    invalidIPDomainError="The IP domain in your e-mail address is incorrectly formatted." 
 *    invalidPeriodsInDomainError="The domain in your e-mail address has consecutive periods." 
 *    missingAtSignError="An at sign (&64;) is missing in your e-mail address."
 *    missingPeriodInDomainError="The domain in your e-mail address is missing a period." 
 *    missingUsernameError="The username in your e-mail address is missing." 
 *    tooManyAtSignsError="Your e-mail address contains too many &64; characters."
 *  /&gt;
 *  </pre>
 *  
 *  @includeExample examples/EmailValidatorExample.mxml
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
public class EmailValidator extends Validator
{
	include "../core/Version.as";

	//--------------------------------------------------------------------------
	//
	//  Class constants
	//
	//--------------------------------------------------------------------------

	/**
	 *  @private
	 */
	private static const DISALLOWED_LOCALNAME_CHARS:String =
								"()<>,;:\\\"[] `~!#$%^&*={}|/?'\t\n\r";
	/**
	 *  @private
	 */							
	private static const DISALLOWED_DOMAIN_CHARS:String =
								"()<>,;:\\\"[] `~!#$%^&*+={}|/?'\t\n\r";
	
	//--------------------------------------------------------------------------
	//
	//  Class methods
	//
	//--------------------------------------------------------------------------

	/**
	 *  Convenience method for calling a validator
	 *  from within a custom validation function.
	 *  Each of the standard Flex validators has a similar convenience method.
	 *
	 *  @param validator The EmailValidator instance.
	 *
	 *  @param value A field to validate.
	 *
	 *  @param baseField Text representation of the subfield
	 *  specified in the value parameter.
	 *  For example, if the <code>value</code> parameter specifies value.email,
	 *  the <code>baseField</code> value is "email".
	 *
	 *  @return An Array of ValidationResult objects, with one
	 *  ValidationResult object for each field examined by the validator. 
	 *
	 *  @see mx.validators.ValidationResult	 
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public static function validateEmail(validator:EmailValidator,
										 value:Object,
										 baseField:String):Array
	{
		var results:Array = [];
	
		// Validate the domain name
		// If IP domain, then must follow [x.x.x.x] format
		// Can not have continous periods.
		// Must have at least one period.
		// Must end in a top level domain name that has 2, 3, 4, or 6 characters.

		var emailStr:String = String(value);
		var username:String = "";
		var domain:String = "";
		var n:int;
		var i:int;

		// Find the @
		var ampPos:int = emailStr.indexOf("@");
		if (ampPos == -1)
		{
			results.push(new ValidationResult(
				true, baseField, "missingAtSign",
				validator.missingAtSignError));
			return results;
		}
		// Make sure there are no extra @s.
		else if (emailStr.indexOf("@", ampPos + 1) != -1) 
		{ 
			results.push(new ValidationResult(
				true, baseField, "tooManyAtSigns",
				validator.tooManyAtSignsError));
			return results;
		}

		// Separate the address into username and domain.
		username = emailStr.substring(0, ampPos);
		domain = emailStr.substring(ampPos + 1);

		// Validate username has no illegal characters
		// and has at least one character.
		var usernameLen:int = username.length;
		if (usernameLen == 0)
		{
			results.push(new ValidationResult(
				true, baseField, "missingUsername",
				validator.missingUsernameError));
			return results;
		}

		for (i = 0; i < usernameLen; i++)
		{
			if (DISALLOWED_LOCALNAME_CHARS.indexOf(username.charAt(i)) != -1)
			{
				results.push(new ValidationResult(
					true, baseField, "invalidChar",
					validator.invalidCharError));
				return results;
			}
		}
		
		// name can't start with a dot
		if (username.charAt(0) == '.')
		{
			results.push(new ValidationResult(
				true, baseField, "invalidChar",
				validator.invalidCharError));
			return results;
		}
		
		var domainLen:int = domain.length;
		
		// check for IP address
		if ((domain.charAt(0) == "[") && (domain.charAt(domainLen - 1) == "]"))
		{
			// Validate IP address
			if (!isValidIPAddress(domain.substring(1, domainLen - 1)))
			{
				results.push(new ValidationResult(
						true, baseField, "invalidIPDomain",
						validator.invalidIPDomainError));
				return results;
			}
		}
		else
		{
			// Must have at least one period
			var periodPos:int = domain.indexOf(".");
			var nextPeriodPos:int = 0;
			var lastDomain:String = "";
			
			if (periodPos == -1)
			{
				results.push(new ValidationResult(
					true, baseField, "missingPeriodInDomain",
					validator.missingPeriodInDomainError));
				return results;
			}

			while (true)
			{
				nextPeriodPos = domain.indexOf(".", periodPos + 1);
				if (nextPeriodPos == -1)
				{
					lastDomain = domain.substring(periodPos + 1);
					break;
				}
				else if (nextPeriodPos == periodPos + 1)
				{
					results.push(new ValidationResult(
						true, baseField, "invalidPeriodsInDomain",
						validator.invalidPeriodsInDomainError));
					return results;
				}
				periodPos = nextPeriodPos;
			}

			// Check that there are no illegal characters in the domain.
			for (i = 0; i < domainLen; i++)
			{
				if (DISALLOWED_DOMAIN_CHARS.indexOf(domain.charAt(i)) != -1)
				{
					results.push(new ValidationResult(
						true, baseField, "invalidChar",
						validator.invalidCharError));
					return results;
				}
			}
			
			// Check that the character immediately after the @ is not a period or an hyphen.
			// And check that the character before the period is not an hyphen.
			if (domain.charAt(0) == "." || domain.charAt(0) == "-" || domain.charAt(periodPos - 1) == "-")
			{
				results.push(new ValidationResult(
					true, baseField, "invalidDomain",
					validator.invalidDomainError));
				return results;
			}
		}

		return results;
	}
	
	/**
	 * Validate a given IP address
	 * 
	 * If IP domain, then must follow [x.x.x.x] format
	 * or for IPv6, then follow [x:x:x:x:x:x:x:x] or [x::x:x:x] or some
	 * IPv4 hybrid, like [::x.x.x.x] or [0:00::192.168.0.1]
	 *
	 * @private
	 */ 
	private static function isValidIPAddress(ipAddr:String):Boolean
	{
		var ipArray:Array = [];
		var pos:int = 0;
		var newpos:int = 0;
		var item:Number;
		var n:int;
		var i:int;
		
		// if you have :, you're in IPv6 mode
		// if you have ., you're in IPv4 mode
		
		if (ipAddr.indexOf(":") != -1)
		{
			// IPv6
			
			// validate by splitting on the colons
			// to make it easier, since :: means zeros, 
			// lets rid ourselves of these wildcards in the beginning
			// and then validate normally
			
			// get rid of unlimited zeros notation so we can parse better
			var hasUnlimitedZeros:Boolean = ipAddr.indexOf("::") != -1;
			if (hasUnlimitedZeros)
			{
				ipAddr = ipAddr.replace(/^::/, "");
				ipAddr = ipAddr.replace(/::/g, ":");
			}
			
			while (true)
			{
				newpos = ipAddr.indexOf(":", pos);
				if (newpos != -1)
				{
					ipArray.push(ipAddr.substring(pos,newpos));
				}
				else
				{
					ipArray.push(ipAddr.substring(pos));
					break;
				}
				pos = newpos + 1;
			}
			
			n = ipArray.length;
			
			const lastIsV4:Boolean = ipArray[n-1].indexOf(".") != -1;
			
			if (lastIsV4)
			{
				// if no wildcards, length must be 7
				// always, never more than 7
				if ((ipArray.length != 7 && !hasUnlimitedZeros) || (ipArray.length > 7))
					return false;
	
				for (i = 0; i < n; i++)
				{
					if (i == n-1)
					{
						// IPv4 part...
						return isValidIPAddress(ipArray[i]);
					}
					
					item = parseInt(ipArray[i], 16);
					
					if (item != 0)
						return false;
				}
			}
			else
			{
			
				// if no wildcards, length must be 8
				// always, never more than 8
				if ((ipArray.length != 8 && !hasUnlimitedZeros) || (ipArray.length > 8))
					return false;
				
				for (i = 0; i < n; i++)
				{
					item = parseInt(ipArray[i], 16);
					
					if (isNaN(item) || item < 0 || item > 0xFFFF || ipArray[i] == "")
						return false;
				}
			}
			
			return true;
		}
			
		if (ipAddr.indexOf(".") != -1)
		{
			// IPv4
			
			// validate by splling on the periods
			while (true)
			{
				newpos = ipAddr.indexOf(".", pos);
				if (newpos != -1)
				{
					ipArray.push(ipAddr.substring(pos,newpos));
				}
				else
				{
					ipArray.push(ipAddr.substring(pos));
					break;
				}
				pos = newpos + 1;
			}
			
			if (ipArray.length != 4)
				return false;

			n = ipArray.length;
			for (i = 0; i < n; i++)
			{
				item = Number(ipArray[i]);
				if (isNaN(item) || item < 0 || item > 255 || ipArray[i] == "")
					return false;
			}
			
			return true;
		}
		
		return false;
	}

	//--------------------------------------------------------------------------
	//
	//  Constructor
	//
	//--------------------------------------------------------------------------

	/**
	 *  Constructor.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function EmailValidator()
	{
		super();
	}

	//--------------------------------------------------------------------------
	//
	//  Properties: Errors
	//
	//--------------------------------------------------------------------------

	//----------------------------------
	//  invalidCharError
	//----------------------------------

    /**
	 *  @private
	 *  Storage for the invalidCharError property.
	 */
	private var _invalidCharError:String;
	
    /**
	 *  @private
	 */
	private var invalidCharErrorOverride:String;
	
	[Inspectable(category="Errors", defaultValue="null")]

    /**
	 *  Error message when there are invalid characters in the e-mail address.
	 *
	 *  @default "Your e-mail address contains invalid characters."
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
	public function get invalidCharError():String
	{
		return _invalidCharError;
	}

	/**
	 *  @private
	 */
	public function set invalidCharError(value:String):void
	{
		invalidCharErrorOverride = value;

		_invalidCharError = value != null ?
							value :
							resourceManager.getString(
								"validators", "invalidCharErrorEV");
	}
	
	//----------------------------------
	//  invalidDomainError
	//----------------------------------

    /**
	 *  @private
	 *  Storage for the invalidDomainError property.
	 */
	private var _invalidDomainError:String;
	
    /**
	 *  @private
	 */
	private var invalidDomainErrorOverride:String;
	
	[Inspectable(category="Errors", defaultValue="null")]

    /**
	 *  Error message when the suffix (the top level domain)
	 *  is not 2, 3, 4 or 6 characters long.
	 *
	 *  @default "The domain in your e-mail address is incorrectly formatted."
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
	public function get invalidDomainError():String
	{
		return _invalidDomainError;
	}

	/**
	 *  @private
	 */
	public function set invalidDomainError(value:String):void
	{
		invalidDomainErrorOverride = value;

		_invalidDomainError = value != null ?
							  value :
							  resourceManager.getString(
							      "validators", "invalidDomainErrorEV");
	}

	//----------------------------------
	//  invalidIPDomainError
	//----------------------------------

    /**
	 *  @private
	 *  Storage for the invalidIPDomainError property.
	 */
	private var _invalidIPDomainError:String;
	
    /**
	 *  @private
	 */
	private var invalidIPDomainErrorOverride:String;
	
	[Inspectable(category="Errors", defaultValue="null")]

    /**
	 *  Error message when the IP domain is invalid. The IP domain must be enclosed by square brackets.
	 *
	 *  @default "The IP domain in your e-mail address is incorrectly formatted."
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
	public function get invalidIPDomainError():String
	{
		return _invalidIPDomainError;
	}

	/**
	 *  @private
	 */
	public function set invalidIPDomainError(value:String):void
	{
		invalidIPDomainErrorOverride = value;

		_invalidIPDomainError = value != null ?
								value :
								resourceManager.getString(
									"validators", "invalidIPDomainError");
	}

	//----------------------------------
	//  invalidPeriodsInDomainError
	//----------------------------------

    /**
	 *  @private
	 *  Storage for the invalidPeriodsInDomainError property.
	 */
	private var _invalidPeriodsInDomainError:String;
	
    /**
	 *  @private
	 */
	private var invalidPeriodsInDomainErrorOverride:String;
	
	[Inspectable(category="Errors", defaultValue="null")]

    /**
	 *  Error message when there are continuous periods in the domain.
	 *
	 *  @default "The domain in your e-mail address has continous periods."
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
	public function get invalidPeriodsInDomainError():String
	{
		return _invalidPeriodsInDomainError;
	}

	/**
	 *  @private
	 */
	public function set invalidPeriodsInDomainError(value:String):void
	{
		invalidPeriodsInDomainErrorOverride = value;

		_invalidPeriodsInDomainError = value != null ?
									   value :
									   resourceManager.getString(
									       "validators", "invalidPeriodsInDomainError");
	}

	//----------------------------------
	//  missingAtSignError
	//----------------------------------

    /**
	 *  @private
	 *  Storage for the missingAtSignError property.
	 */
	private var _missingAtSignError:String;
	
    /**
	 *  @private
	 */
	private var missingAtSignErrorOverride:String;
	
	[Inspectable(category="Errors", defaultValue="null")]

    /**
	 *  Error message when there is no at sign in the email address.
	 *
	 *  @default "An at sign (&64;) is missing in your e-mail address."
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
	public function get missingAtSignError():String
	{
		return _missingAtSignError;
	}

	/**
	 *  @private
	 */
	public function set missingAtSignError(value:String):void
	{
		missingAtSignErrorOverride = value;

		_missingAtSignError = value != null ?
							  value :
							  resourceManager.getString(
							      "validators", "missingAtSignError");
	}

	//----------------------------------
	//  missingPeriodInDomainError
	//----------------------------------

    /**
	 *  @private
	 *  Storage for the missingPeriodInDomainError property.
	 */
	private var _missingPeriodInDomainError:String;
	
    /**
	 *  @private
	 */
	private var missingPeriodInDomainErrorOverride:String;
	
	[Inspectable(category="Errors", defaultValue="null")]

    /**
	 *  Error message when there is no period in the domain.
	 *
	 *  @default "The domain in your e-mail address is missing a period."
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
	public function get missingPeriodInDomainError():String
	{
		return _missingPeriodInDomainError;
	}

	/**
	 *  @private
	 */
	public function set missingPeriodInDomainError(value:String):void
	{
		missingPeriodInDomainErrorOverride = value;

		_missingPeriodInDomainError = value != null ?
									  value :
									  resourceManager.getString(
									      "validators", "missingPeriodInDomainError");
	}

	//----------------------------------
	//  missingUsernameError
	//----------------------------------

    /**
	 *  @private
	 *  Storage for the missingUsernameError property.
	 */
	private var _missingUsernameError:String;
	
    /**
	 *  @private
	 */
	private var missingUsernameErrorOverride:String;
	
	[Inspectable(category="Errors", defaultValue="null")]

    /**
	 *  Error message when there is no username.
	 *
	 *  @default "The username in your e-mail address is missing."
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
	public function get missingUsernameError():String
	{
		return _missingUsernameError;
	}

	/**
	 *  @private
	 */
	public function set missingUsernameError(value:String):void
	{
		missingUsernameErrorOverride = value;

		_missingUsernameError = value != null ?
								value :
								resourceManager.getString(
									"validators", "missingUsernameError");
	}

	//----------------------------------
	//  tooManyAtSignsError
	//----------------------------------

    /**
	 *  @private
	 *  Storage for the tooManyAtSignsError property.
	 */
	private var _tooManyAtSignsError:String;
	
    /**
	 *  @private
	 */
	private var tooManyAtSignsErrorOverride:String;
	
	[Inspectable(category="Errors", defaultValue="null")]

    /**
	 *  Error message when there is more than one at sign in the e-mail address.
	 *  This property is optional. 
	 *
	 *  @default "Your e-mail address contains too many &64; characters."
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
	public function get tooManyAtSignsError():String
	{
		return _tooManyAtSignsError;
	}

	/**
	 *  @private
	 */
	public function set tooManyAtSignsError(value:String):void
	{
		tooManyAtSignsErrorOverride = value;

		_tooManyAtSignsError = value != null ?
							   value :
							   resourceManager.getString(
							       "validators", "tooManyAtSignsError");
	}

	//--------------------------------------------------------------------------
	//
	//  Overridden methods
	//
	//--------------------------------------------------------------------------
	
    /**
	 *  @private    
     */
	override protected function resourcesChanged():void
	{
		super.resourcesChanged();

		invalidCharError = invalidCharErrorOverride;
		invalidDomainError = invalidDomainErrorOverride;
		invalidIPDomainError = invalidIPDomainErrorOverride;
		invalidPeriodsInDomainError = invalidPeriodsInDomainErrorOverride;
		missingAtSignError = missingAtSignErrorOverride;
		missingPeriodInDomainError = missingPeriodInDomainErrorOverride;
		missingUsernameError = missingUsernameErrorOverride;
		tooManyAtSignsError = tooManyAtSignsErrorOverride;
	}

	/**
     *  Override of the base class <code>doValidation()</code> method
     *  to validate an e-mail address.
	 *
	 *  <p>You do not call this method directly;
	 *  Flex calls it as part of performing a validation.
	 *  If you create a custom Validator class, you must implement this method. </p>
	 *
	 *  @param value Either a String or an Object to validate.
     *
	 *  @return An Array of ValidationResult objects, with one ValidationResult 
	 *  object for each field examined by the validator. 
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	override protected function doValidation(value:Object):Array
    {
		var results:Array = super.doValidation(value);
		
		// Return if there are errors
		// or if the required property is set to false and length is 0.
		var val:String = value ? String(value) : "";
		if (results.length > 0 || ((val.length == 0) && !required))
			return results;
		else
		    return EmailValidator.validateEmail(this, value, null);
	}
}

}
