|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00025 require_once 'Zend/Validate/Abstract.php'; 00026 00030 require_once 'Zend/Validate/Ip.php'; 00031 00047 class Zend_Validate_Hostname extends Zend_Validate_Abstract 00048 { 00049 const INVALID = 'hostnameInvalid'; 00050 const IP_ADDRESS_NOT_ALLOWED = 'hostnameIpAddressNotAllowed'; 00051 const UNKNOWN_TLD = 'hostnameUnknownTld'; 00052 const INVALID_DASH = 'hostnameDashCharacter'; 00053 const INVALID_HOSTNAME_SCHEMA = 'hostnameInvalidHostnameSchema'; 00054 const UNDECIPHERABLE_TLD = 'hostnameUndecipherableTld'; 00055 const INVALID_HOSTNAME = 'hostnameInvalidHostname'; 00056 const INVALID_LOCAL_NAME = 'hostnameInvalidLocalName'; 00057 const LOCAL_NAME_NOT_ALLOWED = 'hostnameLocalNameNotAllowed'; 00058 const CANNOT_DECODE_PUNYCODE = 'hostnameCannotDecodePunycode'; 00059 00063 protected $_messageTemplates = array( 00064 self::INVALID => "Invalid type given, value should be a string", 00065 self::IP_ADDRESS_NOT_ALLOWED => "'%value%' appears to be an IP address, but IP addresses are not allowed", 00066 self::UNKNOWN_TLD => "'%value%' appears to be a DNS hostname but cannot match TLD against known list", 00067 self::INVALID_DASH => "'%value%' appears to be a DNS hostname but contains a dash in an invalid position", 00068 self::INVALID_HOSTNAME_SCHEMA => "'%value%' appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'", 00069 self::UNDECIPHERABLE_TLD => "'%value%' appears to be a DNS hostname but cannot extract TLD part", 00070 self::INVALID_HOSTNAME => "'%value%' does not match the expected structure for a DNS hostname", 00071 self::INVALID_LOCAL_NAME => "'%value%' does not appear to be a valid local network name", 00072 self::LOCAL_NAME_NOT_ALLOWED => "'%value%' appears to be a local network name but local network names are not allowed", 00073 self::CANNOT_DECODE_PUNYCODE => "'%value%' appears to be a DNS hostname but the given punycode notation cannot be decoded", 00074 ); 00075 00079 protected $_messageVariables = array( 00080 'tld' => '_tld' 00081 ); 00082 00086 const ALLOW_DNS = 1; 00087 00091 const ALLOW_IP = 2; 00092 00096 const ALLOW_LOCAL = 4; 00097 00101 const ALLOW_ALL = 7; 00102 00110 protected $_validTlds = array( 00111 'ac', 'ad', 'ae', 'aero', 'af', 'ag', 'ai', 'al', 'am', 'an', 'ao', 'aq', 'ar', 'arpa', 00112 'as', 'asia', 'at', 'au', 'aw', 'ax', 'az', 'ba', 'bb', 'bd', 'be', 'bf', 'bg', 'bh', 'bi', 00113 'biz', 'bj', 'bm', 'bn', 'bo', 'br', 'bs', 'bt', 'bv', 'bw', 'by', 'bz', 'ca', 'cat', 'cc', 00114 'cd', 'cf', 'cg', 'ch', 'ci', 'ck', 'cl', 'cm', 'cn', 'co', 'com', 'coop', 'cr', 'cu', 00115 'cv', 'cx', 'cy', 'cz', 'de', 'dj', 'dk', 'dm', 'do', 'dz', 'ec', 'edu', 'ee', 'eg', 'er', 00116 'es', 'et', 'eu', 'fi', 'fj', 'fk', 'fm', 'fo', 'fr', 'ga', 'gb', 'gd', 'ge', 'gf', 'gg', 00117 'gh', 'gi', 'gl', 'gm', 'gn', 'gov', 'gp', 'gq', 'gr', 'gs', 'gt', 'gu', 'gw', 'gy', 'hk', 00118 'hm', 'hn', 'hr', 'ht', 'hu', 'id', 'ie', 'il', 'im', 'in', 'info', 'int', 'io', 'iq', 00119 'ir', 'is', 'it', 'je', 'jm', 'jo', 'jobs', 'jp', 'ke', 'kg', 'kh', 'ki', 'km', 'kn', 'kp', 00120 'kr', 'kw', 'ky', 'kz', 'la', 'lb', 'lc', 'li', 'lk', 'lr', 'ls', 'lt', 'lu', 'lv', 'ly', 00121 'ma', 'mc', 'md', 'me', 'mg', 'mh', 'mil', 'mk', 'ml', 'mm', 'mn', 'mo', 'mobi', 'mp', 00122 'mq', 'mr', 'ms', 'mt', 'mu', 'museum', 'mv', 'mw', 'mx', 'my', 'mz', 'na', 'name', 'nc', 00123 'ne', 'net', 'nf', 'ng', 'ni', 'nl', 'no', 'np', 'nr', 'nu', 'nz', 'om', 'org', 'pa', 'pe', 00124 'pf', 'pg', 'ph', 'pk', 'pl', 'pm', 'pn', 'pr', 'pro', 'ps', 'pt', 'pw', 'py', 'qa', 're', 00125 'ro', 'rs', 'ru', 'rw', 'sa', 'sb', 'sc', 'sd', 'se', 'sg', 'sh', 'si', 'sj', 'sk', 'sl', 00126 'sm', 'sn', 'so', 'sr', 'st', 'su', 'sv', 'sy', 'sz', 'tc', 'td', 'tel', 'tf', 'tg', 'th', 00127 'tj', 'tk', 'tl', 'tm', 'tn', 'to', 'tp', 'tr', 'travel', 'tt', 'tv', 'tw', 'tz', 'ua', 00128 'ug', 'uk', 'um', 'us', 'uy', 'uz', 'va', 'vc', 've', 'vg', 'vi', 'vn', 'vu', 'wf', 'ws', 00129 'ye', 'yt', 'yu', 'za', 'zm', 'zw' 00130 ); 00131 00135 protected $_tld; 00136 00187 protected $_validIdns = array( 00188 'AC' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćĉċčďđēėęěĝġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśŝşšţťŧūŭůűųŵŷźżž]{1,63}$/iu'), 00189 'AR' => array(1 => '/^[\x{002d}0-9a-zà-ãç-êìíñ-õü]{1,63}$/iu'), 00190 'AS' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĸĺļľłńņňŋōŏőœŕŗřśŝşšţťŧũūŭůűųŵŷźż]{1,63}$/iu'), 00191 'AT' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿœšž]{1,63}$/iu'), 00192 'BIZ' => 'Hostname/Biz.php', 00193 'BR' => array(1 => '/^[\x{002d}0-9a-zà-ãçéíó-õúü]{1,63}$/iu'), 00194 'BV' => array(1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'), 00195 'CAT' => array(1 => '/^[\x{002d}0-9a-z·àç-éíïòóúü]{1,63}$/iu'), 00196 'CH' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿœ]{1,63}$/iu'), 00197 'CL' => array(1 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu'), 00198 'CN' => 'Hostname/Cn.php', 00199 'COM' => 'Zend/Validate/Hostname/Com.php', 00200 'DE' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'), 00201 'DK' => array(1 => '/^[\x{002d}0-9a-zäéöü]{1,63}$/iu'), 00202 'ES' => array(1 => '/^[\x{002d}0-9a-zàáçèéíïñòóúü·]{1,63}$/iu'), 00203 'EU' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿ]{1,63}$/iu', 00204 2 => '/^[\x{002d}0-9a-zāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĺļľŀłńņňʼnŋōŏőœŕŗřśŝšťŧũūŭůűųŵŷźżž]{1,63}$/iu', 00205 3 => '/^[\x{002d}0-9a-zșț]{1,63}$/iu', 00206 4 => '/^[\x{002d}0-9a-zΐάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ]{1,63}$/iu', 00207 5 => '/^[\x{002d}0-9a-zабвгдежзийклмнопрстуфхцчшщъыьэюя]{1,63}$/iu', 00208 6 => '/^[\x{002d}0-9a-zἀ-ἇἐ-ἕἠ-ἧἰ-ἷὀ-ὅὐ-ὗὠ-ὧὰ-ώᾀ-ᾇᾐ-ᾗᾠ-ᾧᾰ-ᾴᾶᾷῂῃῄῆῇῐ-ΐῖῗῠ-ῧῲῳῴῶῷ]{1,63}$/iu'), 00209 'FI' => array(1 => '/^[\x{002d}0-9a-zäåö]{1,63}$/iu'), 00210 'GR' => array(1 => '/^[\x{002d}0-9a-zΆΈΉΊΌΎ-ΡΣ-ώἀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼῂῃῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲῳῴῶ-ῼ]{1,63}$/iu'), 00211 'HK' => 'Zend/Validate/Hostname/Cn.php', 00212 'HU' => array(1 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu'), 00213 'INFO'=> array(1 => '/^[\x{002d}0-9a-zäåæéöøü]{1,63}$/iu', 00214 2 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu', 00215 3 => '/^[\x{002d}0-9a-záæéíðóöúýþ]{1,63}$/iu', 00216 4 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu', 00217 5 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu', 00218 6 => '/^[\x{002d}0-9a-ząčėęįšūųž]{1,63}$/iu', 00219 7 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu', 00220 8 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu'), 00221 'IO' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'), 00222 'IS' => array(1 => '/^[\x{002d}0-9a-záéýúíóþæöð]{1,63}$/iu'), 00223 'JP' => 'Zend/Validate/Hostname/Jp.php', 00224 'KR' => array(1 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu'), 00225 'LI' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿœ]{1,63}$/iu'), 00226 'LT' => array(1 => '/^[\x{002d}0-9ąčęėįšųūž]{1,63}$/iu'), 00227 'MD' => array(1 => '/^[\x{002d}0-9ăâîşţ]{1,63}$/iu'), 00228 'MUSEUM' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćċčďđēėęěğġģħīįıķĺļľłńņňŋōőœŕŗřśşšţťŧūůűųŵŷźżžǎǐǒǔ\x{01E5}\x{01E7}\x{01E9}\x{01EF}ə\x{0292}ẁẃẅỳ]{1,63}$/iu'), 00229 'NET' => 'Zend/Validate/Hostname/Com.php', 00230 'NO' => array(1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'), 00231 'NU' => 'Zend/Validate/Hostname/Com.php', 00232 'ORG' => array(1 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu', 00233 2 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu', 00234 3 => '/^[\x{002d}0-9a-záäåæéëíðóöøúüýþ]{1,63}$/iu', 00235 4 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu', 00236 5 => '/^[\x{002d}0-9a-ząčėęįšūųž]{1,63}$/iu', 00237 6 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu', 00238 7 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu'), 00239 'PE' => array(1 => '/^[\x{002d}0-9a-zñáéíóúü]{1,63}$/iu'), 00240 'PL' => array(1 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu', 00241 2 => '/^[\x{002d}а-ик-ш\x{0450}ѓѕјљњќџ]{1,63}$/iu', 00242 3 => '/^[\x{002d}0-9a-zâîăşţ]{1,63}$/iu', 00243 4 => '/^[\x{002d}0-9а-яё\x{04C2}]{1,63}$/iu', 00244 5 => '/^[\x{002d}0-9a-zàáâèéêìíîòóôùúûċġħż]{1,63}$/iu', 00245 6 => '/^[\x{002d}0-9a-zàäåæéêòóôöøü]{1,63}$/iu', 00246 7 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu', 00247 8 => '/^[\x{002d}0-9a-zàáâãçéêíòóôõúü]{1,63}$/iu', 00248 9 => '/^[\x{002d}0-9a-zâîăşţ]{1,63}$/iu', 00249 10=> '/^[\x{002d}0-9a-záäéíóôúýčďĺľňŕšťž]{1,63}$/iu', 00250 11=> '/^[\x{002d}0-9a-zçë]{1,63}$/iu', 00251 12=> '/^[\x{002d}0-9а-ик-шђјљњћџ]{1,63}$/iu', 00252 13=> '/^[\x{002d}0-9a-zćčđšž]{1,63}$/iu', 00253 14=> '/^[\x{002d}0-9a-zâçöûüğış]{1,63}$/iu', 00254 15=> '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu', 00255 16=> '/^[\x{002d}0-9a-zäõöüšž]{1,63}$/iu', 00256 17=> '/^[\x{002d}0-9a-zĉĝĥĵŝŭ]{1,63}$/iu', 00257 18=> '/^[\x{002d}0-9a-zâäéëîô]{1,63}$/iu', 00258 19=> '/^[\x{002d}0-9a-zàáâäåæçèéêëìíîïðñòôöøùúûüýćčłńřśš]{1,63}$/iu', 00259 20=> '/^[\x{002d}0-9a-zäåæõöøüšž]{1,63}$/iu', 00260 21=> '/^[\x{002d}0-9a-zàáçèéìíòóùú]{1,63}$/iu', 00261 22=> '/^[\x{002d}0-9a-zàáéíóöúüőű]{1,63}$/iu', 00262 23=> '/^[\x{002d}0-9ΐά-ώ]{1,63}$/iu', 00263 24=> '/^[\x{002d}0-9a-zàáâåæçèéêëðóôöøüþœ]{1,63}$/iu', 00264 25=> '/^[\x{002d}0-9a-záäéíóöúüýčďěňřšťůž]{1,63}$/iu', 00265 26=> '/^[\x{002d}0-9a-z·àçèéíïòóúü]{1,63}$/iu', 00266 27=> '/^[\x{002d}0-9а-ъьюя\x{0450}\x{045D}]{1,63}$/iu', 00267 28=> '/^[\x{002d}0-9а-яёіў]{1,63}$/iu', 00268 29=> '/^[\x{002d}0-9a-ząčėęįšūųž]{1,63}$/iu', 00269 30=> '/^[\x{002d}0-9a-záäåæéëíðóöøúüýþ]{1,63}$/iu', 00270 31=> '/^[\x{002d}0-9a-zàâæçèéêëîïñôùûüÿœ]{1,63}$/iu', 00271 32=> '/^[\x{002d}0-9а-щъыьэюяёєіїґ]{1,63}$/iu', 00272 33=> '/^[\x{002d}0-9א-ת]{1,63}$/iu'), 00273 'PR' => array(1 => '/^[\x{002d}0-9a-záéíóúñäëïüöâêîôûàèùæçœãõ]{1,63}$/iu'), 00274 'PT' => array(1 => '/^[\x{002d}0-9a-záàâãçéêíóôõú]{1,63}$/iu'), 00275 'RU' => array(1 => '/^[\x{002d}0-9а-яё]{1,63}$/iu'), 00276 'SA' => array(1 => '/^[\x{002d}.0-9\x{0621}-\x{063A}\x{0641}-\x{064A}\x{0660}-\x{0669}]{1,63}$/iu'), 00277 'SE' => array(1 => '/^[\x{002d}0-9a-zäåéöü]{1,63}$/iu'), 00278 'SH' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'), 00279 'SJ' => array(1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'), 00280 'TH' => array(1 => '/^[\x{002d}0-9a-z\x{0E01}-\x{0E3A}\x{0E40}-\x{0E4D}\x{0E50}-\x{0E59}]{1,63}$/iu'), 00281 'TM' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćĉċčďđēėęěĝġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśŝşšţťŧūŭůűųŵŷźżž]{1,63}$/iu'), 00282 'TW' => 'Zend/Validate/Hostname/Cn.php', 00283 'TR' => array(1 => '/^[\x{002d}0-9a-zğıüşöç]{1,63}$/iu'), 00284 'VE' => array(1 => '/^[\x{002d}0-9a-záéíóúüñ]{1,63}$/iu'), 00285 'VN' => array(1 => '/^[ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚÝàáâãèéêìíòóôõùúýĂăĐđĨĩŨũƠơƯư\x{1EA0}-\x{1EF9}]{1,63}$/iu'), 00286 'ایران' => array(1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'), 00287 '中国' => 'Zend/Validate/Hostname/Cn.php', 00288 '公司' => 'Zend/Validate/Hostname/Cn.php', 00289 '网络' => 'Zend/Validate/Hostname/Cn.php' 00290 ); 00291 00292 protected $_idnLength = array( 00293 'BIZ' => array(5 => 17, 11 => 15, 12 => 20), 00294 'CN' => array(1 => 20), 00295 'COM' => array(3 => 17, 5 => 20), 00296 'HK' => array(1 => 15), 00297 'INFO'=> array(4 => 17), 00298 'KR' => array(1 => 17), 00299 'NET' => array(3 => 17, 5 => 20), 00300 'ORG' => array(6 => 17), 00301 'TW' => array(1 => 20), 00302 'ایران' => array(1 => 30), 00303 '中国' => array(1 => 20), 00304 '公司' => array(1 => 20), 00305 '网络' => array(1 => 20), 00306 ); 00307 00308 protected $_options = array( 00309 'allow' => self::ALLOW_DNS, 00310 'idn' => true, 00311 'tld' => true, 00312 'ip' => null 00313 ); 00314 00325 public function __construct($options = array()) 00326 { 00327 if ($options instanceof Zend_Config) { 00328 $options = $options->toArray(); 00329 } else if (!is_array($options)) { 00330 $options = func_get_args(); 00331 $temp['allow'] = array_shift($options); 00332 if (!empty($options)) { 00333 $temp['idn'] = array_shift($options); 00334 } 00335 00336 if (!empty($options)) { 00337 $temp['tld'] = array_shift($options); 00338 } 00339 00340 if (!empty($options)) { 00341 $temp['ip'] = array_shift($options); 00342 } 00343 00344 $options = $temp; 00345 } 00346 00347 $options += $this->_options; 00348 $this->setOptions($options); 00349 } 00350 00356 public function getOptions() 00357 { 00358 return $this->_options; 00359 } 00360 00367 public function setOptions($options) 00368 { 00369 if (array_key_exists('allow', $options)) { 00370 $this->setAllow($options['allow']); 00371 } 00372 00373 if (array_key_exists('idn', $options)) { 00374 $this->setValidateIdn($options['idn']); 00375 } 00376 00377 if (array_key_exists('tld', $options)) { 00378 $this->setValidateTld($options['tld']); 00379 } 00380 00381 if (array_key_exists('ip', $options)) { 00382 $this->setIpValidator($options['ip']); 00383 } 00384 00385 return $this; 00386 } 00387 00393 public function getIpValidator() 00394 { 00395 return $this->_options['ip']; 00396 } 00397 00402 public function setIpValidator(Zend_Validate_Ip $ipValidator = null) 00403 { 00404 if ($ipValidator === null) { 00405 $ipValidator = new Zend_Validate_Ip(); 00406 } 00407 00408 $this->_options['ip'] = $ipValidator; 00409 return $this; 00410 } 00411 00417 public function getAllow() 00418 { 00419 return $this->_options['allow']; 00420 } 00421 00428 public function setAllow($allow) 00429 { 00430 $this->_options['allow'] = $allow; 00431 return $this; 00432 } 00433 00439 public function getValidateIdn() 00440 { 00441 return $this->_options['idn']; 00442 } 00443 00451 public function setValidateIdn ($allowed) 00452 { 00453 $this->_options['idn'] = (bool) $allowed; 00454 return $this; 00455 } 00456 00462 public function getValidateTld() 00463 { 00464 return $this->_options['tld']; 00465 } 00466 00474 public function setValidateTld ($allowed) 00475 { 00476 $this->_options['tld'] = (bool) $allowed; 00477 return $this; 00478 } 00479 00489 public function isValid($value) 00490 { 00491 if (!is_string($value)) { 00492 $this->_error(self::INVALID); 00493 return false; 00494 } 00495 00496 $this->_setValue($value); 00497 // Check input against IP address schema 00498 if (preg_match('/^[0-9.a-e:.]*$/i', $value) && 00499 $this->_options['ip']->setTranslator($this->getTranslator())->isValid($value)) { 00500 if (!($this->_options['allow'] & self::ALLOW_IP)) { 00501 $this->_error(self::IP_ADDRESS_NOT_ALLOWED); 00502 return false; 00503 } else { 00504 return true; 00505 } 00506 } 00507 00508 // Check input against DNS hostname schema 00509 $domainParts = explode('.', $value); 00510 if ((count($domainParts) > 1) && (strlen($value) >= 4) && (strlen($value) <= 254)) { 00511 $status = false; 00512 00513 $origenc = iconv_get_encoding('internal_encoding'); 00514 iconv_set_encoding('internal_encoding', 'UTF-8'); 00515 do { 00516 // First check TLD 00517 $matches = array(); 00518 if (preg_match('/([^.]{2,10})$/i', end($domainParts), $matches) || 00519 (end($domainParts) == 'ایران') || (end($domainParts) == '中国') || 00520 (end($domainParts) == '公司') || (end($domainParts) == '网络')) { 00521 00522 reset($domainParts); 00523 00524 // Hostname characters are: *(label dot)(label dot label); max 254 chars 00525 // label: id-prefix [*ldh{61} id-prefix]; max 63 chars 00526 // id-prefix: alpha / digit 00527 // ldh: alpha / digit / dash 00528 00529 // Match TLD against known list 00530 $this->_tld = strtolower($matches[1]); 00531 if ($this->_options['tld']) { 00532 if (!in_array($this->_tld, $this->_validTlds)) { 00533 $this->_error(self::UNKNOWN_TLD); 00534 $status = false; 00535 break; 00536 } 00537 } 00538 00544 $regexChars = array(0 => '/^[a-z0-9\x2d]{1,63}$/i'); 00545 if ($this->_options['idn'] && isset($this->_validIdns[strtoupper($this->_tld)])) { 00546 if (is_string($this->_validIdns[strtoupper($this->_tld)])) { 00547 $regexChars += include($this->_validIdns[strtoupper($this->_tld)]); 00548 } else { 00549 $regexChars += $this->_validIdns[strtoupper($this->_tld)]; 00550 } 00551 } 00552 00553 // Check each hostname part 00554 $check = 0; 00555 foreach ($domainParts as $domainPart) { 00556 // Decode Punycode domainnames to IDN 00557 if (strpos($domainPart, 'xn--') === 0) { 00558 $domainPart = $this->decodePunycode(substr($domainPart, 4)); 00559 if ($domainPart === false) { 00560 return false; 00561 } 00562 } 00563 00564 // Check dash (-) does not start, end or appear in 3rd and 4th positions 00565 if ((strpos($domainPart, '-') === 0) 00566 || ((strlen($domainPart) > 2) && (strpos($domainPart, '-', 2) == 2) && (strpos($domainPart, '-', 3) == 3)) 00567 || (strpos($domainPart, '-') === (strlen($domainPart) - 1))) { 00568 $this->_error(self::INVALID_DASH); 00569 $status = false; 00570 break 2; 00571 } 00572 00573 // Check each domain part 00574 $checked = false; 00575 foreach($regexChars as $regexKey => $regexChar) { 00576 $status = @preg_match($regexChar, $domainPart); 00577 if ($status > 0) { 00578 $length = 63; 00579 if (array_key_exists(strtoupper($this->_tld), $this->_idnLength) 00580 && (array_key_exists($regexKey, $this->_idnLength[strtoupper($this->_tld)]))) { 00581 $length = $this->_idnLength[strtoupper($this->_tld)]; 00582 } 00583 00584 if (iconv_strlen($domainPart, 'UTF-8') > $length) { 00585 $this->_error(self::INVALID_HOSTNAME); 00586 } else { 00587 $checked = true; 00588 break; 00589 } 00590 } 00591 } 00592 00593 if ($checked) { 00594 ++$check; 00595 } 00596 } 00597 00598 // If one of the labels doesn't match, the hostname is invalid 00599 if ($check !== count($domainParts)) { 00600 $this->_error(self::INVALID_HOSTNAME_SCHEMA); 00601 $status = false; 00602 } 00603 } else { 00604 // Hostname not long enough 00605 $this->_error(self::UNDECIPHERABLE_TLD); 00606 $status = false; 00607 } 00608 } while (false); 00609 00610 iconv_set_encoding('internal_encoding', $origenc); 00611 // If the input passes as an Internet domain name, and domain names are allowed, then the hostname 00612 // passes validation 00613 if ($status && ($this->_options['allow'] & self::ALLOW_DNS)) { 00614 return true; 00615 } 00616 } else if ($this->_options['allow'] & self::ALLOW_DNS) { 00617 $this->_error(self::INVALID_HOSTNAME); 00618 } 00619 00620 // Check input against local network name schema; last chance to pass validation 00621 $regexLocal = '/^(([a-zA-Z0-9\x2d]{1,63}\x2e)*[a-zA-Z0-9\x2d]{1,63}){1,254}$/'; 00622 $status = @preg_match($regexLocal, $value); 00623 00624 // If the input passes as a local network name, and local network names are allowed, then the 00625 // hostname passes validation 00626 $allowLocal = $this->_options['allow'] & self::ALLOW_LOCAL; 00627 if ($status && $allowLocal) { 00628 return true; 00629 } 00630 00631 // If the input does not pass as a local network name, add a message 00632 if (!$status) { 00633 $this->_error(self::INVALID_LOCAL_NAME); 00634 } 00635 00636 // If local network names are not allowed, add a message 00637 if ($status && !$allowLocal) { 00638 $this->_error(self::LOCAL_NAME_NOT_ALLOWED); 00639 } 00640 00641 return false; 00642 } 00643 00651 protected function decodePunycode($encoded) 00652 { 00653 $found = preg_match('/([^a-z0-9\x2d]{1,10})$/i', $encoded); 00654 if (empty($encoded) || ($found > 0)) { 00655 // no punycode encoded string, return as is 00656 $this->_error(self::CANNOT_DECODE_PUNYCODE); 00657 return false; 00658 } 00659 00660 $separator = strrpos($encoded, '-'); 00661 if ($separator > 0) { 00662 for ($x = 0; $x < $separator; ++$x) { 00663 // prepare decoding matrix 00664 $decoded[] = ord($encoded[$x]); 00665 } 00666 } else { 00667 $this->_error(self::CANNOT_DECODE_PUNYCODE); 00668 return false; 00669 } 00670 00671 $lengthd = count($decoded); 00672 $lengthe = strlen($encoded); 00673 00674 // decoding 00675 $init = true; 00676 $base = 72; 00677 $index = 0; 00678 $char = 0x80; 00679 00680 for ($indexe = ($separator) ? ($separator + 1) : 0; $indexe < $lengthe; ++$lengthd) { 00681 for ($old_index = $index, $pos = 1, $key = 36; 1 ; $key += 36) { 00682 $hex = ord($encoded[$indexe++]); 00683 $digit = ($hex - 48 < 10) ? $hex - 22 00684 : (($hex - 65 < 26) ? $hex - 65 00685 : (($hex - 97 < 26) ? $hex - 97 00686 : 36)); 00687 00688 $index += $digit * $pos; 00689 $tag = ($key <= $base) ? 1 : (($key >= $base + 26) ? 26 : ($key - $base)); 00690 if ($digit < $tag) { 00691 break; 00692 } 00693 00694 $pos = (int) ($pos * (36 - $tag)); 00695 } 00696 00697 $delta = intval($init ? (($index - $old_index) / 700) : (($index - $old_index) / 2)); 00698 $delta += intval($delta / ($lengthd + 1)); 00699 for ($key = 0; $delta > 910 / 2; $key += 36) { 00700 $delta = intval($delta / 35); 00701 } 00702 00703 $base = intval($key + 36 * $delta / ($delta + 38)); 00704 $init = false; 00705 $char += (int) ($index / ($lengthd + 1)); 00706 $index %= ($lengthd + 1); 00707 if ($lengthd > 0) { 00708 for ($i = $lengthd; $i > $index; $i--) { 00709 $decoded[$i] = $decoded[($i - 1)]; 00710 } 00711 } 00712 00713 $decoded[$index++] = $char; 00714 } 00715 00716 // convert decoded ucs4 to utf8 string 00717 foreach ($decoded as $key => $value) { 00718 if ($value < 128) { 00719 $decoded[$key] = chr($value); 00720 } elseif ($value < (1 << 11)) { 00721 $decoded[$key] = chr(192 + ($value >> 6)); 00722 $decoded[$key] .= chr(128 + ($value & 63)); 00723 } elseif ($value < (1 << 16)) { 00724 $decoded[$key] = chr(224 + ($value >> 12)); 00725 $decoded[$key] .= chr(128 + (($value >> 6) & 63)); 00726 $decoded[$key] .= chr(128 + ($value & 63)); 00727 } elseif ($value < (1 << 21)) { 00728 $decoded[$key] = chr(240 + ($value >> 18)); 00729 $decoded[$key] .= chr(128 + (($value >> 12) & 63)); 00730 $decoded[$key] .= chr(128 + (($value >> 6) & 63)); 00731 $decoded[$key] .= chr(128 + ($value & 63)); 00732 } else { 00733 $this->_error(self::CANNOT_DECODE_PUNYCODE); 00734 return false; 00735 } 00736 } 00737 00738 return implode($decoded); 00739 } 00740 }