//////////////////////////////////////////////////////////////////////////////// // // 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 @ 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. * *

You can use IP domain names if they are enclosed in square brackets; * for example, myname@[206.132.22.1]. * You can use individual IP numbers from 0 to 255.

* * @mxml * *

The <mx:EmailValidator> tag * inherits all of the tag attributes of its superclass, * and adds the following tag attributes:

* *
 *  <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."
 *  />
 *  
* * @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 = "()<>,;:\\\"[] `~!#$%^&*={}|/?'"; /** * @private */ private static const DISALLOWED_DOMAIN_CHARS:String = "()<>,;:\\\"[] `~!#$%^&*+={}|/?'"; //-------------------------------------------------------------------------- // // 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 value parameter specifies value.email, * the baseField 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; } } 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); if (lastDomain.length != 3 && lastDomain.length != 2 && lastDomain.length != 4 && lastDomain.length != 6) { results.push(new ValidationResult( true, baseField, "invalidDomain", validator.invalidDomainError)); return results; } 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. if (domain.charAt(0) == ".") { 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) 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) 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 doValidation() method * to validate an e-mail address. * *

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.

* * @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); } } }