"Fossies" - the Fresh Open Source Software Archive

Member "yii-1.1.22.bf1d26/framework/validators/CUrlValidator.php" (16 Jan 2020, 6653 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 "CUrlValidator.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  * CUrlValidator 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  * CUrlValidator validates that the attribute value is a valid http or https URL.
   13  *
   14  * @author Qiang Xue <qiang.xue@gmail.com>
   15  * @package system.validators
   16  * @since 1.0
   17  */
   18 class CUrlValidator extends CValidator
   19 {
   20     /**
   21      * @var string the regular expression used to validate the attribute value.
   22      * Since version 1.1.7 the pattern may contain a {schemes} token that will be replaced
   23      * by a regular expression which represents the {@see validSchemes}.
   24      */
   25     public $pattern='/^{schemes}:\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)/i';
   26     /**
   27      * @var array list of URI schemes which should be considered valid. By default, http and https
   28      * are considered to be valid schemes.
   29      * @since 1.1.7
   30      **/
   31     public $validSchemes=array('http','https');
   32     /**
   33      * @var string the default URI scheme. If the input doesn't contain the scheme part, the default
   34      * scheme will be prepended to it (thus changing the input). Defaults to null, meaning a URL must
   35      * contain the scheme part.
   36      * @since 1.1.7
   37      **/
   38     public $defaultScheme;
   39     /**
   40      * @var boolean whether the attribute value can be null or empty. Defaults to true,
   41      * meaning that if the attribute is empty, it is considered valid.
   42      */
   43     public $allowEmpty=true;
   44     /**
   45      * @var boolean whether validation process should care about IDN (internationalized domain names). Default
   46      * value is false which means that validation of URLs containing IDN will always fail.
   47      * @since 1.1.13
   48      */
   49     public $validateIDN=false;
   50 
   51     /**
   52      * Validates the attribute of the object.
   53      * If there is any error, the error message is added to the object.
   54      * @param CModel $object the object being validated
   55      * @param string $attribute the attribute being validated
   56      */
   57     protected function validateAttribute($object,$attribute)
   58     {
   59         $value=$object->$attribute;
   60         if($this->allowEmpty && $this->isEmpty($value))
   61             return;
   62         if(($value=$this->validateValue($value))!==false)
   63             $object->$attribute=$value;
   64         else
   65         {
   66             $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} is not a valid URL.');
   67             $this->addError($object,$attribute,$message);
   68         }
   69     }
   70 
   71     /**
   72      * Validates a static value to see if it is a valid URL.
   73      * Note that this method does not respect {@link allowEmpty} property.
   74      * This method is provided so that you can call it directly without going through the model validation rule mechanism.
   75      * @param string $value the value to be validated
   76      * @return mixed false if the the value is not a valid URL, otherwise the possibly modified value ({@see defaultScheme})
   77      * @since 1.1.1
   78      */
   79     public function validateValue($value)
   80     {
   81         if(is_string($value) && strlen($value)<2000)  // make sure the length is limited to avoid DOS attacks
   82         {
   83             if($this->defaultScheme!==null && strpos($value,'://')===false)
   84                 $value=$this->defaultScheme.'://'.$value;
   85 
   86             if($this->validateIDN)
   87                 $value=$this->encodeIDN($value);
   88 
   89             if(strpos($this->pattern,'{schemes}')!==false)
   90                 $pattern=str_replace('{schemes}','('.implode('|',$this->validSchemes).')',$this->pattern);
   91             else
   92                 $pattern=$this->pattern;
   93 
   94             if(preg_match($pattern,$value))
   95                 return $this->validateIDN ? $this->decodeIDN($value) : $value;
   96         }
   97         return false;
   98     }
   99 
  100     /**
  101      * Returns the JavaScript needed for performing client-side validation.
  102      * @param CModel $object the data object being validated
  103      * @param string $attribute the name of the attribute to be validated.
  104      * @return string the client-side validation script.
  105      * @see CActiveForm::enableClientValidation
  106      * @since 1.1.7
  107      */
  108     public function clientValidateAttribute($object,$attribute)
  109     {
  110         if($this->validateIDN)
  111         {
  112             Yii::app()->getClientScript()->registerCoreScript('punycode');
  113             // punycode.js works only with the domains - so we have to extract it before punycoding
  114             $validateIDN='
  115 var info = value.match(/^(.+:\/\/|)([^/]+)/);
  116 if (info)
  117     value = info[1] + punycode.toASCII(info[2]);
  118 ';
  119         }
  120         else
  121             $validateIDN='';
  122 
  123         $message=$this->message!==null ? $this->message : Yii::t('yii','{attribute} is not a valid URL.');
  124         $message=strtr($message, array(
  125             '{attribute}'=>$object->getAttributeLabel($attribute),
  126         ));
  127 
  128         if(strpos($this->pattern,'{schemes}')!==false)
  129             $pattern=str_replace('{schemes}','('.implode('|',$this->validSchemes).')',$this->pattern);
  130         else
  131             $pattern=$this->pattern;
  132 
  133         $js="
  134 $validateIDN
  135 if(!value.match($pattern)) {
  136     messages.push(".CJSON::encode($message).");
  137 }
  138 ";
  139         if($this->defaultScheme!==null)
  140         {
  141             $js="
  142 if(!value.match(/:\\/\\//)) {
  143     value=".CJSON::encode($this->defaultScheme)."+'://'+value;
  144 }
  145 $js
  146 ";
  147         }
  148 
  149         if($this->allowEmpty)
  150         {
  151             $js="
  152 if(jQuery.trim(value)!='') {
  153     $js
  154 }
  155 ";
  156         }
  157 
  158         return $js;
  159     }
  160 
  161     /**
  162      * Converts given IDN to the punycode.
  163      * @param string $value IDN to be converted.
  164      * @return string resulting punycode.
  165      * @since 1.1.13
  166      */
  167     private function encodeIDN($value)
  168     {
  169         if(preg_match_all('/^(.*):\/\/([^\/]+)(.*)$/',$value,$matches))
  170         {
  171             if(function_exists('idn_to_ascii'))
  172             {
  173                 $value=$matches[1][0].'://';
  174                 if (defined('IDNA_NONTRANSITIONAL_TO_ASCII') && defined('INTL_IDNA_VARIANT_UTS46'))
  175                 {
  176                     $value.=idn_to_ascii($matches[2][0],IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
  177                 }
  178                 else
  179                 {
  180                     $value.=idn_to_ascii($matches[2][0]);
  181                 }
  182                 $value.=$matches[3][0];
  183             }
  184             else
  185             {
  186                 require_once(Yii::getPathOfAlias('system.vendors.Net_IDNA2.Net').DIRECTORY_SEPARATOR.'IDNA2.php');
  187                 $idna=new Net_IDNA2();
  188                 $value=$matches[1][0].'://'.@$idna->encode($matches[2][0]).$matches[3][0];
  189             }
  190         }
  191         return $value;
  192     }
  193 
  194     /**
  195      * Converts given punycode to the IDN.
  196      * @param string $value punycode to be converted.
  197      * @return string resulting IDN.
  198      * @since 1.1.13
  199      */
  200     private function decodeIDN($value)
  201     {
  202         if(preg_match_all('/^(.*):\/\/([^\/]+)(.*)$/',$value,$matches))
  203         {
  204             if(function_exists('idn_to_utf8'))
  205             {
  206                 $value=$matches[1][0].'://';
  207                 if (defined('IDNA_NONTRANSITIONAL_TO_ASCII') && defined('INTL_IDNA_VARIANT_UTS46'))
  208                 {
  209                     $value.=idn_to_utf8($matches[2][0],IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
  210                 }
  211                 else
  212                 {
  213                     $value=idn_to_utf8($matches[2][0]);
  214                 }
  215                 $value.=$matches[3][0];
  216             }
  217             else
  218             {
  219                 require_once(Yii::getPathOfAlias('system.vendors.Net_IDNA2.Net').DIRECTORY_SEPARATOR.'IDNA2.php');
  220                 $idna=new Net_IDNA2();
  221                 $value=$matches[1][0].'://'.@$idna->decode($matches[2][0]).$matches[3][0];
  222             }
  223         }
  224         return $value;
  225     }
  226 }