"Fossies" - the Fresh Open Source Software Archive

Member "yii-1.1.22.bf1d26/framework/validators/CEmailValidator.php" (16 Jan 2020, 7548 Bytes) of package /linux/www/yii-1.1.22.bf1d26.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "CEmailValidator.php" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.1.21.733ac5_vs_1.1.22.bf1d26.

    1 <?php
    2 /**
    3  * CEmailValidator class file.
    4  *
    5  * @author Qiang Xue <qiang.xue@gmail.com>
    6  * @link http://www.yiiframework.com/
    7  * @copyright 2008-2013 Yii Software LLC
    8  * @license http://www.yiiframework.com/license/
    9  */
   10 
   11 /**
   12  * CEmailValidator validates that the attribute value is a valid email address.
   13  *
   14  * @author Qiang Xue <qiang.xue@gmail.com>
   15  * @package system.validators
   16  * @since 1.0
   17  */
   18 class CEmailValidator extends CValidator
   19 {
   20     /**
   21      * @var string the regular expression used to validate the attribute value.
   22      * @see http://www.regular-expressions.info/email.html
   23      */
   24     public $pattern='/^[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/';
   25     /**
   26      * @var string the regular expression used to validate email addresses with the name part.
   27      * This property is used only when {@link allowName} is true.
   28      * @see allowName
   29      */
   30     public $fullPattern='/^[^@]*<[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?>$/';
   31     /**
   32      * @var boolean whether to allow name in the email address (e.g. "Qiang Xue <qiang.xue@gmail.com>"). Defaults to false.
   33      * @see fullPattern
   34      */
   35     public $allowName=false;
   36     /**
   37      * @var boolean whether to check the MX record for the email address.
   38      * Defaults to false. To enable it, you need to make sure the PHP function 'checkdnsrr'
   39      * exists in your PHP installation.
   40      * Please note that this check may fail due to temporary problems even if email is deliverable.
   41      */
   42     public $checkMX=false;
   43     /**
   44      * @var boolean whether to check port 25 for the email address.
   45      * Defaults to false. To enable it, ensure that the PHP functions 'dns_get_record' and
   46      * 'fsockopen' are available in your PHP installation.
   47      * Please note that this check may fail due to temporary problems even if email is deliverable.
   48      */
   49     public $checkPort=false;
   50     /**
   51      * @var null|int timeout to use when attempting to open connection to port in checkMxPorts. If null (default)
   52      * use default_socket_timeout value from php.ini. If not null the timeout is set in seconds.
   53      * @since 1.1.19
   54      */
   55     public $timeout=null;
   56     /**
   57      * @var boolean whether the attribute value can be null or empty. Defaults to true,
   58      * meaning that if the attribute is empty, it is considered valid.
   59      */
   60     public $allowEmpty=true;
   61     /**
   62      * @var boolean whether validation process should care about IDN (internationalized domain names). Default
   63      * value is false which means that validation of emails containing IDN will always fail.
   64      * @since 1.1.13
   65      */
   66     public $validateIDN=false;
   67 
   68     /**
   69      * Validates the attribute of the object.
   70      * If there is any error, the error message is added to the object.
   71      * @param CModel $object the object being validated
   72      * @param string $attribute the attribute being validated
   73      */
   74     protected function validateAttribute($object,$attribute)
   75     {
   76         $value=$object->$attribute;
   77         if($this->allowEmpty && $this->isEmpty($value))
   78             return;
   79 
   80         if(!$this->validateValue($value))
   81         {
   82             $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} is not a valid email address.');
   83             $this->addError($object,$attribute,$message);
   84         }
   85     }
   86 
   87     /**
   88      * Validates a static value to see if it is a valid email.
   89      * This method is provided so that you can call it directly without going through the model validation rule mechanism.
   90      *
   91      * Note that this method does not respect the {@link allowEmpty} property.
   92      *
   93      * @param mixed $value the value to be validated
   94      * @return boolean whether the value is a valid email
   95      * @since 1.1.1
   96      * @see https://github.com/yiisoft/yii/issues/3764#issuecomment-75457805
   97      */
   98     public function validateValue($value)
   99     {
  100         if(is_string($value) && $this->validateIDN)
  101             $value=$this->encodeIDN($value);
  102         // make sure string length is limited to avoid DOS attacks
  103         $valid=is_string($value) && strlen($value)<=254 && (preg_match($this->pattern,$value) || $this->allowName && preg_match($this->fullPattern,$value));
  104         if($valid)
  105             $domain=rtrim(substr($value,strpos($value,'@')+1),'>');
  106         if($valid && $this->checkMX && function_exists('checkdnsrr'))
  107             $valid=checkdnsrr($domain,'MX');
  108         if($valid && $this->checkPort && function_exists('fsockopen') && function_exists('dns_get_record'))
  109             $valid=$this->checkMxPorts($domain);
  110         return $valid;
  111     }
  112 
  113     /**
  114      * Returns the JavaScript needed for performing client-side validation.
  115      * @param CModel $object the data object being validated
  116      * @param string $attribute the name of the attribute to be validated.
  117      * @return string the client-side validation script.
  118      * @see CActiveForm::enableClientValidation
  119      * @since 1.1.7
  120      */
  121     public function clientValidateAttribute($object,$attribute)
  122     {
  123         if($this->validateIDN)
  124         {
  125             Yii::app()->getClientScript()->registerCoreScript('punycode');
  126             // punycode.js works only with the domains - so we have to extract it before punycoding
  127             $validateIDN='
  128 var info = value.match(/^(.[^@]+)@(.+)$/);
  129 if (info)
  130     value = info[1] + "@" + punycode.toASCII(info[2]);
  131 ';
  132         }
  133         else
  134             $validateIDN='';
  135 
  136         $message=$this->message!==null ? $this->message : Yii::t('yii','{attribute} is not a valid email address.');
  137         $message=strtr($message, array(
  138             '{attribute}'=>$object->getAttributeLabel($attribute),
  139         ));
  140 
  141         $condition="!value.match({$this->pattern})";
  142         if($this->allowName)
  143             $condition.=" && !value.match({$this->fullPattern})";
  144 
  145         return "
  146 $validateIDN
  147 if(".($this->allowEmpty ? "jQuery.trim(value)!='' && " : '').$condition.") {
  148     messages.push(".CJSON::encode($message).");
  149 }
  150 ";
  151     }
  152 
  153     /**
  154      * Retrieves the list of MX records for $domain and checks if port 25
  155      * is opened on any of these.
  156      * @since 1.1.11
  157      * @param string $domain domain to be checked
  158      * @return boolean true if a reachable MX server has been found
  159      */
  160     protected function checkMxPorts($domain)
  161     {
  162         $records=dns_get_record($domain, DNS_MX);
  163         if($records===false || empty($records))
  164             return false;
  165         $timeout=is_int($this->timeout)?$this->timeout:((int)ini_get('default_socket_timeout'));
  166         usort($records,array($this,'mxSort'));
  167         foreach($records as $record)
  168         {
  169             $handle=@fsockopen($record['target'],25,$errno,$errstr,$timeout);
  170             if($handle!==false)
  171             {
  172                 fclose($handle);
  173                 return true;
  174             }
  175         }
  176         return false;
  177     }
  178 
  179     /**
  180      * Determines if one MX record has higher priority as another
  181      * (i.e. 'pri' is lower). Used by {@link checkMxPorts}.
  182      * @since 1.1.11
  183      * @param mixed $a first item for comparison
  184      * @param mixed $b second item for comparison
  185      * @return boolean
  186      */
  187     protected function mxSort($a, $b)
  188     {
  189         return $a['pri']-$b['pri'];
  190     }
  191 
  192     /**
  193      * Converts given IDN to the punycode.
  194      * @param string $value IDN to be converted.
  195      * @return string resulting punycode.
  196      * @since 1.1.13
  197      */
  198     private function encodeIDN($value)
  199     {
  200         if(preg_match_all('/^(.*)@(.*)$/',$value,$matches))
  201         {
  202             if(function_exists('idn_to_ascii'))
  203             {
  204                 $value=$matches[1][0].'@';
  205                 if (defined('IDNA_NONTRANSITIONAL_TO_ASCII') && defined('INTL_IDNA_VARIANT_UTS46'))
  206                 {
  207                     $value.=idn_to_ascii($matches[2][0],IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
  208                 }
  209                 else
  210                 {
  211                     $value.=idn_to_ascii($matches[2][0]);
  212                 }
  213             }
  214             else
  215             {
  216                 require_once(Yii::getPathOfAlias('system.vendors.Net_IDNA2.Net').DIRECTORY_SEPARATOR.'IDNA2.php');
  217                 $idna=new Net_IDNA2();
  218                 $value=$matches[1][0].'@'.@$idna->encode($matches[2][0]);
  219             }
  220         }
  221         return $value;
  222     }
  223 }