web/lib/Zend/Validate/Hostname.php
changeset 807 877f952ae2bd
parent 207 621fa6caec0c
child 1230 68c69c656a2c
equal deleted inserted replaced
805:5e7a0fedabdf 807:877f952ae2bd
    12  * obtain it through the world-wide-web, please send an email
    12  * obtain it through the world-wide-web, please send an email
    13  * to license@zend.com so we can send you a copy immediately.
    13  * to license@zend.com so we can send you a copy immediately.
    14  *
    14  *
    15  * @category   Zend
    15  * @category   Zend
    16  * @package    Zend_Validate
    16  * @package    Zend_Validate
    17  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
    17  * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
    18  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    18  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    19  * @version    $Id: Hostname.php 22830 2010-08-12 16:05:09Z thomas $
    19  * @version    $Id: Hostname.php 25061 2012-11-02 21:24:09Z rob $
    20  */
    20  */
    21 
    21 
    22 /**
    22 /**
    23  * @see Zend_Validate_Abstract
    23  * @see Zend_Validate_Abstract
    24  */
    24  */
    39  * The second is tests/Zend/Validate/HostnameTestForm.php which is designed to be run via HTML
    39  * The second is tests/Zend/Validate/HostnameTestForm.php which is designed to be run via HTML
    40  * to allow users to test entering UTF-8 characters in a form.
    40  * to allow users to test entering UTF-8 characters in a form.
    41  *
    41  *
    42  * @category   Zend
    42  * @category   Zend
    43  * @package    Zend_Validate
    43  * @package    Zend_Validate
    44  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
    44  * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
    45  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    45  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    46  */
    46  */
    47 class Zend_Validate_Hostname extends Zend_Validate_Abstract
    47 class Zend_Validate_Hostname extends Zend_Validate_Abstract
    48 {
    48 {
    49     const CANNOT_DECODE_PUNYCODE  = 'hostnameCannotDecodePunycode';
    49     const CANNOT_DECODE_PUNYCODE  = 'hostnameCannotDecodePunycode';
    98     const ALLOW_LOCAL = 4;
    98     const ALLOW_LOCAL = 4;
    99 
    99 
   100     /**
   100     /**
   101      * Allows all types of hostnames
   101      * Allows all types of hostnames
   102      */
   102      */
   103     const ALLOW_ALL   = 7;
   103     const ALLOW_URI = 8;
   104 
   104 
   105     /**
   105     /**
   106      * Allows all types of hostnames
   106      * Allows all types of hostnames
   107      */
   107      */
   108     const ALLOW_URI = 8;
   108     const ALLOW_ALL = 15;
   109 
   109 
   110     /**
   110     /**
   111      * Array of valid top-level-domains
   111      * Array of valid top-level-domains
   112      *
   112      *
   113      * @see ftp://data.iana.org/TLD/tlds-alpha-by-domain.txt  List of all TLDs by domain
   113      * @see ftp://data.iana.org/TLD/tlds-alpha-by-domain.txt  List of all TLDs by domain
   131         'pf', 'pg', 'ph', 'pk', 'pl', 'pm', 'pn', 'pr', 'pro', 'ps', 'pt', 'pw', 'py', 'qa', 're',
   131         'pf', 'pg', 'ph', 'pk', 'pl', 'pm', 'pn', 'pr', 'pro', 'ps', 'pt', 'pw', 'py', 'qa', 're',
   132         'ro', 'rs', 'ru', 'rw', 'sa', 'sb', 'sc', 'sd', 'se', 'sg', 'sh', 'si', 'sj', 'sk', 'sl',
   132         'ro', 'rs', 'ru', 'rw', 'sa', 'sb', 'sc', 'sd', 'se', 'sg', 'sh', 'si', 'sj', 'sk', 'sl',
   133         'sm', 'sn', 'so', 'sr', 'st', 'su', 'sv', 'sy', 'sz', 'tc', 'td', 'tel', 'tf', 'tg', 'th',
   133         'sm', 'sn', 'so', 'sr', 'st', 'su', 'sv', 'sy', 'sz', 'tc', 'td', 'tel', 'tf', 'tg', 'th',
   134         'tj', 'tk', 'tl', 'tm', 'tn', 'to', 'tp', 'tr', 'travel', 'tt', 'tv', 'tw', 'tz', 'ua',
   134         'tj', 'tk', 'tl', 'tm', 'tn', 'to', 'tp', 'tr', 'travel', 'tt', 'tv', 'tw', 'tz', 'ua',
   135         'ug', 'uk', 'um', 'us', 'uy', 'uz', 'va', 'vc', 've', 'vg', 'vi', 'vn', 'vu', 'wf', 'ws',
   135         'ug', 'uk', 'um', 'us', 'uy', 'uz', 'va', 'vc', 've', 'vg', 'vi', 'vn', 'vu', 'wf', 'ws',
   136         'ye', 'yt', 'yu', 'za', 'zm', 'zw'
   136         'xxx', 'ye', 'yt', 'yu', 'za', 'zm', 'zw'
   137     );
   137     );
   138 
   138 
   139     /**
   139     /**
   140      * @var string
   140      * @var string
   141      */
   141      */
   203         'CH'  => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿœ]{1,63}$/iu'),
   203         'CH'  => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿœ]{1,63}$/iu'),
   204         'CL'  => array(1 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu'),
   204         'CL'  => array(1 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu'),
   205         'CN'  => 'Hostname/Cn.php',
   205         'CN'  => 'Hostname/Cn.php',
   206         'COM' => 'Zend/Validate/Hostname/Com.php',
   206         'COM' => 'Zend/Validate/Hostname/Com.php',
   207         'DE'  => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'),
   207         'DE'  => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'),
   208         'DK'  => array(1 => '/^[\x{002d}0-9a-zäéöü]{1,63}$/iu'),
   208         'DK'  => array(1 => '/^[\x{002d}0-9a-zäéöüæøå]{1,63}$/iu'),
   209         'ES'  => array(1 => '/^[\x{002d}0-9a-zàáçèéíïñòóúü·]{1,63}$/iu'),
   209         'ES'  => array(1 => '/^[\x{002d}0-9a-zàáçèéíïñòóúü·]{1,63}$/iu'),
   210         'EU'  => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿ]{1,63}$/iu',
   210         'EU'  => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿ]{1,63}$/iu',
   211             2 => '/^[\x{002d}0-9a-zāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĺļľŀłńņňʼnŋōŏőœŕŗřśŝšťŧũūŭůűųŵŷźżž]{1,63}$/iu',
   211             2 => '/^[\x{002d}0-9a-zāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĺļľŀłńņňʼnŋōŏőœŕŗřśŝšťŧũūŭůűųŵŷźżž]{1,63}$/iu',
   212             3 => '/^[\x{002d}0-9a-zșț]{1,63}$/iu',
   212             3 => '/^[\x{002d}0-9a-zșț]{1,63}$/iu',
   213             4 => '/^[\x{002d}0-9a-zΐάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ]{1,63}$/iu',
   213             4 => '/^[\x{002d}0-9a-zΐάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ]{1,63}$/iu',
   281         'PT'  => array(1 => '/^[\x{002d}0-9a-záàâãçéêíóôõú]{1,63}$/iu'),
   281         'PT'  => array(1 => '/^[\x{002d}0-9a-záàâãçéêíóôõú]{1,63}$/iu'),
   282         'RU'  => array(1 => '/^[\x{002d}0-9а-яё]{1,63}$/iu'),
   282         'RU'  => array(1 => '/^[\x{002d}0-9а-яё]{1,63}$/iu'),
   283         'SA'  => array(1 => '/^[\x{002d}.0-9\x{0621}-\x{063A}\x{0641}-\x{064A}\x{0660}-\x{0669}]{1,63}$/iu'),
   283         'SA'  => array(1 => '/^[\x{002d}.0-9\x{0621}-\x{063A}\x{0641}-\x{064A}\x{0660}-\x{0669}]{1,63}$/iu'),
   284         'SE'  => array(1 => '/^[\x{002d}0-9a-zäåéöü]{1,63}$/iu'),
   284         'SE'  => array(1 => '/^[\x{002d}0-9a-zäåéöü]{1,63}$/iu'),
   285         'SH'  => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'),
   285         'SH'  => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'),
       
   286         'SI'  => array(
       
   287             1 => '/^[\x{002d}0-9a-zà-öø-ÿ]{1,63}$/iu',
       
   288             2 => '/^[\x{002d}0-9a-zāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĺļľŀłńņňʼnŋōŏőœŕŗřśŝšťŧũūŭůűųŵŷźżž]{1,63}$/iu',
       
   289             3 => '/^[\x{002d}0-9a-zșț]{1,63}$/iu'),
   286         'SJ'  => array(1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'),
   290         'SJ'  => array(1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'),
   287         'TH'  => array(1 => '/^[\x{002d}0-9a-z\x{0E01}-\x{0E3A}\x{0E40}-\x{0E4D}\x{0E50}-\x{0E59}]{1,63}$/iu'),
   291         'TH'  => array(1 => '/^[\x{002d}0-9a-z\x{0E01}-\x{0E3A}\x{0E40}-\x{0E4D}\x{0E50}-\x{0E59}]{1,63}$/iu'),
   288         'TM'  => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćĉċčďđēėęěĝġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśŝşšţťŧūŭůűųŵŷźżž]{1,63}$/iu'),
   292         'TM'  => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćĉċčďđēėęěĝġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśŝşšţťŧūŭůűųŵŷźżž]{1,63}$/iu'),
   289         'TW'  => 'Zend/Validate/Hostname/Cn.php',
   293         'TW'  => 'Zend/Validate/Hostname/Cn.php',
   290         'TR'  => array(1 => '/^[\x{002d}0-9a-zğıüşöç]{1,63}$/iu'),
   294         'TR'  => array(1 => '/^[\x{002d}0-9a-zğıüşöç]{1,63}$/iu'),
   500             return false;
   504             return false;
   501         }
   505         }
   502 
   506 
   503         $this->_setValue($value);
   507         $this->_setValue($value);
   504         // Check input against IP address schema
   508         // Check input against IP address schema
   505         if (preg_match('/^[0-9.a-e:.]*$/i', $value) &&
   509         if (preg_match('/^[0-9a-f:.]*$/i', $value) &&
   506             $this->_options['ip']->setTranslator($this->getTranslator())->isValid($value)) {
   510             $this->_options['ip']->setTranslator($this->getTranslator())->isValid($value)) {
   507             if (!($this->_options['allow'] & self::ALLOW_IP)) {
   511             if (!($this->_options['allow'] & self::ALLOW_IP)) {
   508                 $this->_error(self::IP_ADDRESS_NOT_ALLOWED);
   512                 $this->_error(self::IP_ADDRESS_NOT_ALLOWED);
   509                 return false;
   513                 return false;
   510             } else {
   514             } else {
   511                 return true;
   515                 return true;
   512             }
   516             }
   513         }
   517         }
   514 
   518 
       
   519         // RFC3986 3.2.2 states:
       
   520         // 
       
   521         //     The rightmost domain label of a fully qualified domain name
       
   522         //     in DNS may be followed by a single "." and should be if it is 
       
   523         //     necessary to distinguish between the complete domain name and
       
   524         //     some local domain.
       
   525         //     
       
   526         // (see ZF-6363)
       
   527         
       
   528         // Local hostnames are allowed to be partitial (ending '.')
       
   529         if ($this->_options['allow'] & self::ALLOW_LOCAL) {
       
   530             if (substr($value, -1) === '.') {
       
   531                 $value = substr($value, 0, -1);
       
   532                 if (substr($value, -1) === '.') {
       
   533                     // Empty hostnames (ending '..') are not allowed
       
   534                     $this->_error(self::INVALID_LOCAL_NAME);
       
   535                     return false;
       
   536                 }
       
   537             }
       
   538         }
       
   539 
       
   540         $domainParts = explode('.', $value);
       
   541 
       
   542         // Prevent partitial IP V4 adresses (ending '.')
       
   543         if ((count($domainParts) == 4) && preg_match('/^[0-9.a-e:.]*$/i', $value) &&
       
   544             $this->_options['ip']->setTranslator($this->getTranslator())->isValid($value)) {
       
   545             $this->_error(self::INVALID_LOCAL_NAME);
       
   546         }
       
   547 
   515         // Check input against DNS hostname schema
   548         // Check input against DNS hostname schema
   516         $domainParts = explode('.', $value);
       
   517         if ((count($domainParts) > 1) && (strlen($value) >= 4) && (strlen($value) <= 254)) {
   549         if ((count($domainParts) > 1) && (strlen($value) >= 4) && (strlen($value) <= 254)) {
   518             $status = false;
   550             $status = false;
   519 
   551 
   520             $origenc = iconv_get_encoding('internal_encoding');
   552             $origenc = iconv_get_encoding('internal_encoding');
   521             iconv_set_encoding('internal_encoding', 'UTF-8');
   553             iconv_set_encoding('internal_encoding', 'UTF-8');
   632                 $this->_error(self::INVALID_URI);
   664                 $this->_error(self::INVALID_URI);
   633             }
   665             }
   634         }
   666         }
   635 
   667 
   636         // Check input against local network name schema; last chance to pass validation
   668         // Check input against local network name schema; last chance to pass validation
   637         $regexLocal = '/^(([a-zA-Z0-9\x2d]{1,63}\x2e)*[a-zA-Z0-9\x2d]{1,63}){1,254}$/';
   669         $regexLocal = '/^(([a-zA-Z0-9\x2d]{1,63}\x2e)*[a-zA-Z0-9\x2d]{1,63}[\x2e]{0,1}){1,254}$/';
   638         $status = @preg_match($regexLocal, $value);
   670         $status = @preg_match($regexLocal, $value);
   639 
   671 
   640         // If the input passes as a local network name, and local network names are allowed, then the
   672         // If the input passes as a local network name, and local network names are allowed, then the
   641         // hostname passes validation
   673         // hostname passes validation
   642         $allowLocal = $this->_options['allow'] & self::ALLOW_LOCAL;
   674         $allowLocal = $this->_options['allow'] & self::ALLOW_LOCAL;