| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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. |
| * |
| * <p>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.</p> |
| * |
| * @mxml |
| * |
| * <p>The <code><mx:EmailValidator></code> tag |
| * inherits all of the tag attributes of its superclass, |
| * and adds the following tag attributes:</p> |
| * |
| * <pre> |
| * <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." |
| * /> |
| * </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); |
| } |
| } |
| |
| } |