File
6 years ago
Hostname
6 years ago
Abstract.php
6 years ago
Alnum.php
6 years ago
Alpha.php
6 years ago
Between.php
6 years ago
Callback.php
6 years ago
Ccnum.php
6 years ago
CreditCard.php
6 years ago
Date.php
6 years ago
Digits.php
6 years ago
Exception.php
6 years ago
Float.php
6 years ago
GreaterThan.php
6 years ago
Hex.php
6 years ago
Hostname.php
6 years ago
Iban.php
6 years ago
Identical.php
6 years ago
InArray.php
6 years ago
Int.php
6 years ago
Interface.php
6 years ago
Ip.php
6 years ago
Isbn.php
6 years ago
LessThan.php
6 years ago
NotEmpty.php
6 years ago
PostCode.php
6 years ago
Regex.php
6 years ago
StringLength.php
6 years ago
Hostname.php
1052 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Zend Framework |
| 4 | * |
| 5 | * LICENSE |
| 6 | * |
| 7 | * This source file is subject to the new BSD license that is bundled |
| 8 | * with this package in the file LICENSE.txt. |
| 9 | * It is also available through the world-wide-web at this URL: |
| 10 | * http://framework.zend.com/license/new-bsd |
| 11 | * If you did not receive a copy of the license and are unable to |
| 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. |
| 14 | * |
| 15 | * @category Zend |
| 16 | * @package Zend_Validate |
| 17 | * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) |
| 18 | * @license http://framework.zend.com/license/new-bsd New BSD License |
| 19 | * @version $Id: Hostname.php 24307 2011-07-30 02:13:14Z adamlundrigan $ |
| 20 | */ |
| 21 | |
| 22 | /** |
| 23 | * @see Zend_Validate_Abstract |
| 24 | */ |
| 25 | // require_once 'Zend/Validate/Abstract.php'; |
| 26 | |
| 27 | /** |
| 28 | * @see Zend_Validate_Ip |
| 29 | */ |
| 30 | // require_once 'Zend/Validate/Ip.php'; |
| 31 | |
| 32 | /** |
| 33 | * Please note there are two standalone test scripts for testing IDN characters due to problems |
| 34 | * with file encoding. |
| 35 | * |
| 36 | * The first is tests/Zend/Validate/HostnameTestStandalone.php which is designed to be run on |
| 37 | * the command line. |
| 38 | * |
| 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. |
| 41 | * |
| 42 | * @category Zend |
| 43 | * @package Zend_Validate |
| 44 | * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) |
| 45 | * @license http://framework.zend.com/license/new-bsd New BSD License |
| 46 | */ |
| 47 | class Zend_Validate_Hostname extends Zend_Validate_Abstract |
| 48 | { |
| 49 | const CANNOT_DECODE_PUNYCODE = 'hostnameCannotDecodePunycode'; |
| 50 | const INVALID = 'hostnameInvalid'; |
| 51 | const INVALID_DASH = 'hostnameDashCharacter'; |
| 52 | const INVALID_HOSTNAME = 'hostnameInvalidHostname'; |
| 53 | const INVALID_HOSTNAME_SCHEMA = 'hostnameInvalidHostnameSchema'; |
| 54 | const INVALID_LOCAL_NAME = 'hostnameInvalidLocalName'; |
| 55 | const INVALID_URI = 'hostnameInvalidUri'; |
| 56 | const IP_ADDRESS_NOT_ALLOWED = 'hostnameIpAddressNotAllowed'; |
| 57 | const LOCAL_NAME_NOT_ALLOWED = 'hostnameLocalNameNotAllowed'; |
| 58 | const UNDECIPHERABLE_TLD = 'hostnameUndecipherableTld'; |
| 59 | const UNKNOWN_TLD = 'hostnameUnknownTld'; |
| 60 | const VALID_UNICODE_DOMAIN = '/^[\p{L}\p{M}]{1,63}$/iu'; |
| 61 | |
| 62 | /** |
| 63 | * @var array |
| 64 | */ |
| 65 | protected $_messageTemplates = array( |
| 66 | self::CANNOT_DECODE_PUNYCODE => "'%value%' appears to be a DNS hostname but the given punycode notation cannot be decoded", |
| 67 | self::INVALID => "Invalid type given. String expected", |
| 68 | self::INVALID_DASH => "'%value%' appears to be a DNS hostname but contains a dash in an invalid position", |
| 69 | self::INVALID_HOSTNAME => "'%value%' does not match the expected structure for a DNS hostname", |
| 70 | self::INVALID_HOSTNAME_SCHEMA => "'%value%' appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'", |
| 71 | self::INVALID_LOCAL_NAME => "'%value%' does not appear to be a valid local network name", |
| 72 | self::INVALID_URI => "'%value%' does not appear to be a valid URI hostname", |
| 73 | self::IP_ADDRESS_NOT_ALLOWED => "'%value%' appears to be an IP address, but IP addresses are not allowed", |
| 74 | self::LOCAL_NAME_NOT_ALLOWED => "'%value%' appears to be a local network name but local network names are not allowed", |
| 75 | self::UNDECIPHERABLE_TLD => "'%value%' appears to be a DNS hostname but cannot extract TLD part", |
| 76 | self::UNKNOWN_TLD => "'%value%' appears to be a DNS hostname but cannot match TLD against known list", |
| 77 | ); |
| 78 | |
| 79 | /** |
| 80 | * @var array |
| 81 | */ |
| 82 | protected $_messageVariables = array( |
| 83 | 'tld' => '_tld' |
| 84 | ); |
| 85 | |
| 86 | /** |
| 87 | * Allows Internet domain names (e.g., example.com) |
| 88 | */ |
| 89 | const ALLOW_DNS = 1; |
| 90 | |
| 91 | /** |
| 92 | * Allows IP addresses |
| 93 | */ |
| 94 | const ALLOW_IP = 2; |
| 95 | |
| 96 | /** |
| 97 | * Allows local network names (e.g., localhost, www.localdomain) |
| 98 | */ |
| 99 | const ALLOW_LOCAL = 4; |
| 100 | |
| 101 | /** |
| 102 | * Allows all types of hostnames |
| 103 | */ |
| 104 | const ALLOW_URI = 8; |
| 105 | |
| 106 | /** |
| 107 | * Allows all types of hostnames |
| 108 | */ |
| 109 | const ALLOW_ALL = 15; |
| 110 | |
| 111 | /** |
| 112 | * Array of valid top-level-domains |
| 113 | * |
| 114 | * @see ftp://data.iana.org/TLD/tlds-alpha-by-domain.txt List of all TLDs by domain |
| 115 | * @see http://www.iana.org/domains/root/db/ Official list of supported TLDs |
| 116 | * @var array |
| 117 | */ |
| 118 | protected $_validTlds = array( |
| 119 | 'aaa', 'aarp', 'abb', 'abbott', 'abogado', 'ac', 'academy', 'accenture', 'accountant', 'accountants', |
| 120 | 'aco', 'active', 'actor', 'ad', 'ads', 'adult', 'ae', 'aeg', 'aero', 'af', 'afl', 'ag', 'agency', 'ai', |
| 121 | 'aig', 'airforce', 'airtel', 'al', 'allfinanz', 'alsace', 'am', 'amica', 'amsterdam', 'analytics', |
| 122 | 'android', 'ao', 'apartments', 'app', 'apple', 'aq', 'aquarelle', 'ar', 'aramco', 'archi', 'army', 'arpa', |
| 123 | 'arte', 'as', 'asia', 'associates', 'at', 'attorney', 'au', 'auction', 'audi', 'audio', 'author', 'auto', |
| 124 | 'autos', 'aw', 'ax', 'axa', 'az', 'azure', 'ba', 'baidu', 'band', 'bank', 'bar', 'barcelona', 'barclaycard', |
| 125 | 'barclays', 'bargains', 'bauhaus', 'bayern', 'bb', 'bbc', 'bbva', 'bcn', 'bd', 'be', 'beats', 'beer', |
| 126 | 'bentley', 'berlin', 'best', 'bet', 'bf', 'bg', 'bh', 'bharti', 'bi', 'bible', 'bid', 'bike', 'bing', |
| 127 | 'bingo', 'bio', 'biz', 'bj', 'black', 'blackfriday', 'bloomberg', 'blue', 'bm', 'bms', 'bmw', 'bn', 'bnl', |
| 128 | 'bnpparibas', 'bo', 'boats', 'boehringer', 'bom', 'bond', 'boo', 'book', 'boots', 'bosch', 'bostik', 'bot', |
| 129 | 'boutique', 'br', 'bradesco', 'bridgestone', 'broadway', 'broker', 'brother', 'brussels', 'bs', 'bt', |
| 130 | 'budapest', 'bugatti', 'build', 'builders', 'business', 'buy', 'buzz', 'bv', 'bw', 'by', 'bz', 'bzh', 'ca', |
| 131 | 'cab', 'cafe', 'cal', 'call', 'camera', 'camp', 'cancerresearch', 'canon', 'capetown', 'capital', 'car', |
| 132 | 'caravan', 'cards', 'care', 'career', 'careers', 'cars', 'cartier', 'casa', 'cash', 'casino', 'cat', |
| 133 | 'catering', 'cba', 'cbn', 'cc', 'cd', 'ceb', 'center', 'ceo', 'cern', 'cf', 'cfa', 'cfd', 'cg', 'ch', |
| 134 | 'chanel', 'channel', 'chat', 'cheap', 'chloe', 'christmas', 'chrome', 'church', 'ci', 'cipriani', |
| 135 | 'circle', 'cisco', 'citic', 'city', 'cityeats', 'ck', 'cl', 'claims', 'cleaning', 'click', 'clinic', |
| 136 | 'clinique', 'clothing', 'cloud', 'club', 'clubmed', 'cm', 'cn', 'co', 'coach', 'codes', 'coffee', |
| 137 | 'college', 'cologne', 'com', 'commbank', 'community', 'company', 'computer', 'comsec', 'condos', |
| 138 | 'construction', 'consulting', 'contact', 'contractors', 'cooking', 'cool', 'coop', 'corsica', 'country', |
| 139 | 'coupons', 'courses', 'cr', 'credit', 'creditcard', 'creditunion', 'cricket', 'crown', 'crs', 'cruises', |
| 140 | 'csc', 'cu', 'cuisinella', 'cv', 'cw', 'cx', 'cy', 'cymru', 'cyou', 'cz', 'dabur', 'dad', 'dance', 'date', |
| 141 | 'dating', 'datsun', 'day', 'dclk', 'de', 'dealer', 'deals', 'degree', 'delivery', 'dell', 'delta', 'democrat', |
| 142 | 'dental', 'dentist', 'desi', 'design', 'dev', 'diamonds', 'diet', 'digital', 'direct', 'directory', |
| 143 | 'discount', 'dj', 'dk', 'dm', 'dnp', 'do', 'docs', 'dog', 'doha', 'domains', 'doosan', 'download', 'drive', |
| 144 | 'dubai', 'durban', 'dvag', 'dz', 'earth', 'eat', 'ec', 'edu', 'education', 'ee', 'eg', 'email', 'emerck', |
| 145 | 'energy', 'engineer', 'engineering', 'enterprises', 'epson', 'equipment', 'er', 'erni', 'es', 'esq', |
| 146 | 'estate', 'et', 'eu', 'eurovision', 'eus', 'events', 'everbank', 'exchange', 'expert', 'exposed', 'express', |
| 147 | 'fage', 'fail', 'fairwinds', 'faith', 'family', 'fan', 'fans', 'farm', 'fashion', 'fast', 'feedback', |
| 148 | 'ferrero', 'fi', 'film', 'final', 'finance', 'financial', 'firestone', 'firmdale', 'fish', 'fishing', |
| 149 | 'fit', 'fitness', 'fj', 'fk', 'flights', 'florist', 'flowers', 'flsmidth', 'fly', 'fm', 'fo', 'foo', |
| 150 | 'football', 'ford', 'forex', 'forsale', 'forum', 'foundation', 'fox', 'fr', 'frl', 'frogans', 'fund', |
| 151 | 'furniture', 'futbol', 'fyi', 'ga', 'gal', 'gallery', 'game', 'garden', 'gb', 'gbiz', 'gd', 'gdn', 'ge', |
| 152 | 'gea', 'gent', 'genting', 'gf', 'gg', 'ggee', 'gh', 'gi', 'gift', 'gifts', 'gives', 'giving', 'gl', 'glass', |
| 153 | 'gle', 'global', 'globo', 'gm', 'gmail', 'gmo', 'gmx', 'gn', 'gold', 'goldpoint', 'golf', 'goo', 'goog', |
| 154 | 'google', 'gop', 'got', 'gov', 'gp', 'gq', 'gr', 'grainger', 'graphics', 'gratis', 'green', 'gripe', 'group', |
| 155 | 'gs', 'gt', 'gu', 'gucci', 'guge', 'guide', 'guitars', 'guru', 'gw', 'gy', 'hamburg', 'hangout', 'haus', |
| 156 | 'healthcare', 'help', 'here', 'hermes', 'hiphop', 'hitachi', 'hiv', 'hk', 'hm', 'hn', 'hockey', 'holdings', |
| 157 | 'holiday', 'homedepot', 'homes', 'honda', 'horse', 'host', 'hosting', 'hoteles', 'hotmail', 'house', 'how', |
| 158 | 'hr', 'hsbc', 'ht', 'hu', 'hyundai', 'ibm', 'icbc', 'ice', 'icu', 'id', 'ie', 'ifm', 'iinet', 'il', 'im', |
| 159 | 'immo', 'immobilien', 'in', 'industries', 'infiniti', 'info', 'ing', 'ink', 'institute', 'insurance', 'insure', |
| 160 | 'int', 'international', 'investments', 'io', 'ipiranga', 'iq', 'ir', 'irish', 'is', 'ist', 'istanbul', 'it', |
| 161 | 'itau', 'iwc', 'jaguar', 'java', 'jcb', 'je', 'jetzt', 'jewelry', 'jlc', 'jll', 'jm', 'jmp', 'jo', 'jobs', |
| 162 | 'joburg', 'jot', 'joy', 'jp', 'jprs', 'juegos', 'kaufen', 'kddi', 'ke', 'kfh', 'kg', 'kh', 'ki', 'kia', 'kim', |
| 163 | 'kinder', 'kitchen', 'kiwi', 'km', 'kn', 'koeln', 'komatsu', 'kp', 'kpn', 'kr', 'krd', 'kred', 'kw', 'ky', |
| 164 | 'kyoto', 'kz', 'la', 'lacaixa', 'lamborghini', 'lamer', 'lancaster', 'land', 'landrover', 'lasalle', 'lat', |
| 165 | 'latrobe', 'law', 'lawyer', 'lb', 'lc', 'lds', 'lease', 'leclerc', 'legal', 'lexus', 'lgbt', 'li', 'liaison', |
| 166 | 'lidl', 'life', 'lifestyle', 'lighting', 'like', 'limited', 'limo', 'lincoln', 'linde', 'link', 'live', |
| 167 | 'living', 'lixil', 'lk', 'loan', 'loans', 'lol', 'london', 'lotte', 'lotto', 'love', 'lr', 'ls', 'lt', 'ltd', |
| 168 | 'ltda', 'lu', 'lupin', 'luxe', 'luxury', 'lv', 'ly', 'ma', 'madrid', 'maif', 'maison', 'man', 'management', |
| 169 | 'mango', 'market', 'marketing', 'markets', 'marriott', 'mba', 'mc', 'md', 'me', 'med', 'media', 'meet', |
| 170 | 'melbourne', 'meme', 'memorial', 'men', 'menu', 'meo', 'mg', 'mh', 'miami', 'microsoft', 'mil', 'mini', 'mk', |
| 171 | 'ml', 'mm', 'mma', 'mn', 'mo', 'mobi', 'mobily', 'moda', 'moe', 'moi', 'mom', 'monash', 'money', 'montblanc', |
| 172 | 'mormon', 'mortgage', 'moscow', 'motorcycles', 'mov', 'movie', 'movistar', 'mp', 'mq', 'mr', 'ms', 'mt', |
| 173 | 'mtn', 'mtpc', 'mtr', 'mu', 'museum', 'mutuelle', 'mv', 'mw', 'mx', 'my', 'mz', 'na', 'nadex', 'nagoya', |
| 174 | 'name', 'navy', 'nc', 'ne', 'nec', 'net', 'netbank', 'network', 'neustar', 'new', 'news', 'nexus', 'nf', |
| 175 | 'ng', 'ngo', 'nhk', 'ni', 'nico', 'ninja', 'nissan', 'nl', 'no', 'nokia', 'norton', 'nowruz', 'np', 'nr', |
| 176 | 'nra', 'nrw', 'ntt', 'nu', 'nyc', 'nz', 'obi', 'office', 'okinawa', 'om', 'omega', 'one', 'ong', 'onl', |
| 177 | 'online', 'ooo', 'oracle', 'orange', 'org', 'organic', 'origins', 'osaka', 'otsuka', 'ovh', 'pa', 'page', |
| 178 | 'panerai', 'paris', 'pars', 'partners', 'parts', 'party', 'pe', 'pet', 'pf', 'pg', 'ph', 'pharmacy', |
| 179 | 'philips', 'photo', 'photography', 'photos', 'physio', 'piaget', 'pics', 'pictet', 'pictures', 'pid', 'pin', |
| 180 | 'ping', 'pink', 'pizza', 'pk', 'pl', 'place', 'play', 'playstation', 'plumbing', 'plus', 'pm', 'pn', 'pohl', |
| 181 | 'poker', 'porn', 'post', 'pr', 'praxi', 'press', 'pro', 'prod', 'productions', 'prof', 'promo', 'properties', |
| 182 | 'property', 'protection', 'ps', 'pt', 'pub', 'pw', 'py', 'qa', 'qpon', 'quebec', 'racing', 're', 'read', |
| 183 | 'realtor', 'realty', 'recipes', 'red', 'redstone', 'redumbrella', 'rehab', 'reise', 'reisen', 'reit', 'ren', |
| 184 | 'rent', 'rentals', 'repair', 'report', 'republican', 'rest', 'restaurant', 'review', 'reviews', 'rexroth', |
| 185 | 'rich', 'ricoh', 'rio', 'rip', 'ro', 'rocher', 'rocks', 'rodeo', 'room', 'rs', 'rsvp', 'ru', 'ruhr', 'run', |
| 186 | 'rw', 'rwe', 'ryukyu', 'sa', 'saarland', 'safe', 'safety', 'sakura', 'sale', 'salon', 'samsung', 'sandvik', |
| 187 | 'sandvikcoromant', 'sanofi', 'sap', 'sapo', 'sarl', 'sas', 'saxo', 'sb', 'sbs', 'sc', 'sca', 'scb', |
| 188 | 'schaeffler', 'schmidt', 'scholarships', 'school', 'schule', 'schwarz', 'science', 'scor', 'scot', 'sd', |
| 189 | 'se', 'seat', 'security', 'seek', 'sener', 'services', 'seven', 'sew', 'sex', 'sexy', 'sfr', 'sg', 'sh', |
| 190 | 'sharp', 'shell', 'shia', 'shiksha', 'shoes', 'show', 'shriram', 'si', 'singles', 'site', 'sj', 'sk', 'ski', |
| 191 | 'sky', 'skype', 'sl', 'sm', 'smile', 'sn', 'sncf', 'so', 'soccer', 'social', 'software', 'sohu', 'solar', |
| 192 | 'solutions', 'sony', 'soy', 'space', 'spiegel', 'spreadbetting', 'sr', 'srl', 'st', 'stada', 'star', 'starhub', |
| 193 | 'statefarm', 'statoil', 'stc', 'stcgroup', 'stockholm', 'storage', 'studio', 'study', 'style', 'su', 'sucks', |
| 194 | 'supplies', 'supply', 'support', 'surf', 'surgery', 'suzuki', 'sv', 'swatch', 'swiss', 'sx', 'sy', 'sydney', |
| 195 | 'symantec', 'systems', 'sz', 'tab', 'taipei', 'tatamotors', 'tatar', 'tattoo', 'tax', 'taxi', 'tc', 'tci', |
| 196 | 'td', 'team', 'tech', 'technology', 'tel', 'telefonica', 'temasek', 'tennis', 'tf', 'tg', 'th', 'thd', |
| 197 | 'theater', 'theatre', 'tickets', 'tienda', 'tips', 'tires', 'tirol', 'tj', 'tk', 'tl', 'tm', 'tn', 'to', |
| 198 | 'today', 'tokyo', 'tools', 'top', 'toray', 'toshiba', 'tours', 'town', 'toyota', 'toys', 'tr', 'trade', |
| 199 | 'trading', 'training', 'travel', 'travelers', 'travelersinsurance', 'trust', 'trv', 'tt', 'tui', 'tushu', |
| 200 | 'tv', 'tw', 'tz', 'ua', 'ubs', 'ug', 'uk', 'university', 'uno', 'uol', 'us', 'uy', 'uz', 'va', 'vacations', |
| 201 | 'vana', 'vc', 've', 'vegas', 'ventures', 'verisign', 'versicherung', 'vet', 'vg', 'vi', 'viajes', 'video', |
| 202 | 'villas', 'vin', 'vip', 'virgin', 'vision', 'vista', 'vistaprint', 'viva', 'vlaanderen', 'vn', 'vodka', 'vote', |
| 203 | 'voting', 'voto', 'voyage', 'vu', 'wales', 'walter', 'wang', 'wanggou', 'watch', 'watches', 'webcam', 'weber', |
| 204 | 'website', 'wed', 'wedding', 'weir', 'wf', 'whoswho', 'wien', 'wiki', 'williamhill', 'win', 'windows', 'wine', |
| 205 | 'wme', 'work', 'works', 'world', 'ws', 'wtc', 'wtf', 'xbox', 'xerox', 'xin', 'xperia', 'xxx', 'xyz', 'yachts', 'yamaxun', 'yandex', 'ye', |
| 206 | 'yodobashi', 'yoga', 'yokohama', 'youtube', 'yt', 'za', 'zara', 'zero', 'zip', 'zm', 'zone', 'zuerich', 'zw' |
| 207 | ); |
| 208 | |
| 209 | /** |
| 210 | * @var string |
| 211 | */ |
| 212 | protected $_tld; |
| 213 | |
| 214 | /** |
| 215 | * Array for valid Idns |
| 216 | * @see http://www.iana.org/domains/idn-tables/ Official list of supported IDN Chars |
| 217 | * (.AC) Ascension Island http://www.nic.ac/pdf/AC-IDN-Policy.pdf |
| 218 | * (.AR) Argentinia http://www.nic.ar/faqidn.html |
| 219 | * (.AS) American Samoa http://www.nic.as/idn/chars.cfm |
| 220 | * (.AT) Austria http://www.nic.at/en/service/technical_information/idn/charset_converter/ |
| 221 | * (.BIZ) International http://www.iana.org/domains/idn-tables/ |
| 222 | * (.BR) Brazil http://registro.br/faq/faq6.html |
| 223 | * (.BV) Bouvett Island http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html |
| 224 | * (.CAT) Catalan http://www.iana.org/domains/idn-tables/tables/cat_ca_1.0.html |
| 225 | * (.CH) Switzerland https://nic.switch.ch/reg/ocView.action?res=EF6GW2JBPVTG67DLNIQXU234MN6SC33JNQQGI7L6#anhang1 |
| 226 | * (.CL) Chile http://www.iana.org/domains/idn-tables/tables/cl_latn_1.0.html |
| 227 | * (.COM) International http://www.verisign.com/information-services/naming-services/internationalized-domain-names/index.html |
| 228 | * (.DE) Germany http://www.denic.de/en/domains/idns/liste.html |
| 229 | * (.DK) Danmark http://www.dk-hostmaster.dk/index.php?id=151 |
| 230 | * (.ES) Spain https://www.nic.es/media/2008-05/1210147705287.pdf |
| 231 | * (.FI) Finland http://www.ficora.fi/en/index/palvelut/fiverkkotunnukset/aakkostenkaytto.html |
| 232 | * (.GR) Greece https://grweb.ics.forth.gr/CharacterTable1_en.jsp |
| 233 | * (.HU) Hungary http://www.domain.hu/domain/English/szabalyzat/szabalyzat.html |
| 234 | * (.INFO) International http://www.nic.info/info/idn |
| 235 | * (.IO) British Indian Ocean Territory http://www.nic.io/IO-IDN-Policy.pdf |
| 236 | * (.IR) Iran http://www.nic.ir/Allowable_Characters_dot-iran |
| 237 | * (.IS) Iceland http://www.isnic.is/domain/rules.php |
| 238 | * (.KR) Korea http://www.iana.org/domains/idn-tables/tables/kr_ko-kr_1.0.html |
| 239 | * (.LI) Liechtenstein https://nic.switch.ch/reg/ocView.action?res=EF6GW2JBPVTG67DLNIQXU234MN6SC33JNQQGI7L6#anhang1 |
| 240 | * (.LT) Lithuania http://www.domreg.lt/static/doc/public/idn_symbols-en.pdf |
| 241 | * (.MD) Moldova http://www.register.md/ |
| 242 | * (.MUSEUM) International http://www.iana.org/domains/idn-tables/tables/museum_latn_1.0.html |
| 243 | * (.NET) International http://www.verisign.com/information-services/naming-services/internationalized-domain-names/index.html |
| 244 | * (.NO) Norway http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html |
| 245 | * (.NU) Niue http://www.worldnames.net/ |
| 246 | * (.ORG) International http://www.pir.org/index.php?db=content/FAQs&tbl=FAQs_Registrant&id=2 |
| 247 | * (.PE) Peru https://www.nic.pe/nuevas_politicas_faq_2.php |
| 248 | * (.PL) Poland http://www.dns.pl/IDN/allowed_character_sets.pdf |
| 249 | * (.PR) Puerto Rico http://www.nic.pr/idn_rules.asp |
| 250 | * (.PT) Portugal https://online.dns.pt/dns_2008/do?com=DS;8216320233;111;+PAGE(4000058)+K-CAT-CODIGO(C.125)+RCNT(100); |
| 251 | * (.RU) Russia http://www.iana.org/domains/idn-tables/tables/ru_ru-ru_1.0.html |
| 252 | * (.SA) Saudi Arabia http://www.iana.org/domains/idn-tables/tables/sa_ar_1.0.html |
| 253 | * (.SE) Sweden http://www.iis.se/english/IDN_campaignsite.shtml?lang=en |
| 254 | * (.SH) Saint Helena http://www.nic.sh/SH-IDN-Policy.pdf |
| 255 | * (.SJ) Svalbard and Jan Mayen http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html |
| 256 | * (.TH) Thailand http://www.iana.org/domains/idn-tables/tables/th_th-th_1.0.html |
| 257 | * (.TM) Turkmenistan http://www.nic.tm/TM-IDN-Policy.pdf |
| 258 | * (.TR) Turkey https://www.nic.tr/index.php |
| 259 | * (.VE) Venice http://www.iana.org/domains/idn-tables/tables/ve_es_1.0.html |
| 260 | * (.VN) Vietnam http://www.vnnic.vn/english/5-6-300-2-2-04-20071115.htm#1.%20Introduction |
| 261 | * |
| 262 | * @var array |
| 263 | */ |
| 264 | protected $_validIdns = array( |
| 265 | 'AC' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿāă� |
| 266 | ćĉċčďđēėęěĝġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśŝşšţťŧūŭůűųŵŷźżž]{1,63}$/iu'), |
| 267 | 'AR' => array(1 => '/^[\x{002d}0-9a-zà-ãç-êìíñ-õü]{1,63}$/iu'), |
| 268 | 'AS' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿāă� |
| 269 | ćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĸĺļľłńņňŋōŏőœŕŗřśŝşšţťŧũūŭůűųŵŷźż]{1,63}$/iu'), |
| 270 | 'AT' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿœšž]{1,63}$/iu'), |
| 271 | 'BIZ' => 'Hostname/Biz.php', |
| 272 | 'BR' => array(1 => '/^[\x{002d}0-9a-zà-ãçéíó-õúü]{1,63}$/iu'), |
| 273 | 'BV' => array(1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'), |
| 274 | 'CAT' => array(1 => '/^[\x{002d}0-9a-z·àç-éíïòóúü]{1,63}$/iu'), |
| 275 | 'CH' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿœ]{1,63}$/iu'), |
| 276 | 'CL' => array(1 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu'), |
| 277 | 'CN' => 'Hostname/Cn.php', |
| 278 | 'COM' => 'Hostname/Com.php', |
| 279 | 'DE' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿă� |
| 280 | āćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'), |
| 281 | 'DK' => array(1 => '/^[\x{002d}0-9a-zäéöü]{1,63}$/iu'), |
| 282 | 'ES' => array(1 => '/^[\x{002d}0-9a-zàáçèéíïñòóúü·]{1,63}$/iu'), |
| 283 | 'EU' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿ]{1,63}$/iu', |
| 284 | 2 => '/^[\x{002d}0-9a-zāă� |
| 285 | ćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĺļľŀłńņňʼnŋōŏőœŕŗřśŝšťŧũūŭůűųŵŷźżž]{1,63}$/iu', |
| 286 | 3 => '/^[\x{002d}0-9a-zșț]{1,63}$/iu', |
| 287 | 4 => '/^[\x{002d}0-9a-zΐάέήίΰαβγδεζηθικλμνξοπρςστ� |
| 288 | φχψωϊϋόύώ]{1,63}$/iu', |
| 289 | 5 => '/^[\x{002d}0-9a-zабвгдежзийклмнопрстуф� |
| 290 | цчшщъыьэюя]{1,63}$/iu', |
| 291 | 6 => '/^[\x{002d}0-9a-zἀ-ἇἐ-ἕἠ-ἧἰ-ἷὀ-� |
| 292 | ὐ-ὗὠ-ὧὰ-ώᾀ-ᾇᾐ-ᾗᾠ-ᾧᾰ-ᾴᾶᾷῂῃῄῆῇῐ-ΐῖῗῠ-ῧῲῳῴῶῷ]{1,63}$/iu'), |
| 293 | 'FI' => array(1 => '/^[\x{002d}0-9a-zäåö]{1,63}$/iu'), |
| 294 | 'GR' => array(1 => '/^[\x{002d}0-9a-zΆΈΉΊΌΎ-ΡΣ-ώἀ-ἕἘ-Ἕἠ-� |
| 295 | Ὀ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼῂῃῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲῳῴῶ-ῼ]{1,63}$/iu'), |
| 296 | 'HK' => 'Hostname/Cn.php', |
| 297 | 'HU' => array(1 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu'), |
| 298 | 'INFO'=> array(1 => '/^[\x{002d}0-9a-zäåæéöøü]{1,63}$/iu', |
| 299 | 2 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu', |
| 300 | 3 => '/^[\x{002d}0-9a-záæéíðóöúýþ]{1,63}$/iu', |
| 301 | 4 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu', |
| 302 | 5 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu', |
| 303 | 6 => '/^[\x{002d}0-9a-z� |
| 304 | čėęįšūųž]{1,63}$/iu', |
| 305 | 7 => '/^[\x{002d}0-9a-zó� |
| 306 | ćęłńśźż]{1,63}$/iu', |
| 307 | 8 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu'), |
| 308 | 'IO' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿă� |
| 309 | āćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'), |
| 310 | 'IS' => array(1 => '/^[\x{002d}0-9a-záéýúíóþæöð]{1,63}$/iu'), |
| 311 | 'JP' => 'Hostname/Jp.php', |
| 312 | 'KR' => array(1 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu'), |
| 313 | 'LI' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿœ]{1,63}$/iu'), |
| 314 | 'LT' => array(1 => '/^[\x{002d}0-9� |
| 315 | čęėįšųūž]{1,63}$/iu'), |
| 316 | 'MD' => array(1 => '/^[\x{002d}0-9ăâîşţ]{1,63}$/iu'), |
| 317 | 'MUSEUM' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿāă� |
| 318 | ćċčďđēėęěğġģħīįıķĺļľłńņňŋōőœŕŗřśşšţťŧūůűųŵŷźżžǎǐǒǔ\x{01E5}\x{01E7}\x{01E9}\x{01EF}ə\x{0292}ẁẃ� |
| 319 | ỳ]{1,63}$/iu'), |
| 320 | 'NET' => 'Hostname/Com.php', |
| 321 | 'NO' => array(1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'), |
| 322 | 'NU' => 'Hostname/Com.php', |
| 323 | 'ORG' => array(1 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu', |
| 324 | 2 => '/^[\x{002d}0-9a-zó� |
| 325 | ćęłńśźż]{1,63}$/iu', |
| 326 | 3 => '/^[\x{002d}0-9a-záäåæéëíðóöøúüýþ]{1,63}$/iu', |
| 327 | 4 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu', |
| 328 | 5 => '/^[\x{002d}0-9a-z� |
| 329 | čėęįšūųž]{1,63}$/iu', |
| 330 | 6 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu', |
| 331 | 7 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu'), |
| 332 | 'PE' => array(1 => '/^[\x{002d}0-9a-zñáéíóúü]{1,63}$/iu'), |
| 333 | 'PL' => array(1 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu', |
| 334 | 2 => '/^[\x{002d}а-ик-ш\x{0450}ѓѕјљњќџ]{1,63}$/iu', |
| 335 | 3 => '/^[\x{002d}0-9a-zâîăşţ]{1,63}$/iu', |
| 336 | 4 => '/^[\x{002d}0-9а-яё\x{04C2}]{1,63}$/iu', |
| 337 | 5 => '/^[\x{002d}0-9a-zàáâèéêìíîòóôùúûċġħż]{1,63}$/iu', |
| 338 | 6 => '/^[\x{002d}0-9a-zàäåæéêòóôöøü]{1,63}$/iu', |
| 339 | 7 => '/^[\x{002d}0-9a-zó� |
| 340 | ćęłńśźż]{1,63}$/iu', |
| 341 | 8 => '/^[\x{002d}0-9a-zàáâãçéêíòóôõúü]{1,63}$/iu', |
| 342 | 9 => '/^[\x{002d}0-9a-zâîăşţ]{1,63}$/iu', |
| 343 | 10=> '/^[\x{002d}0-9a-záäéíóôúýčďĺľňŕšťž]{1,63}$/iu', |
| 344 | 11=> '/^[\x{002d}0-9a-zçë]{1,63}$/iu', |
| 345 | 12=> '/^[\x{002d}0-9а-ик-шђјљњћџ]{1,63}$/iu', |
| 346 | 13=> '/^[\x{002d}0-9a-zćčđšž]{1,63}$/iu', |
| 347 | 14=> '/^[\x{002d}0-9a-zâçöûüğış]{1,63}$/iu', |
| 348 | 15=> '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu', |
| 349 | 16=> '/^[\x{002d}0-9a-zäõöüšž]{1,63}$/iu', |
| 350 | 17=> '/^[\x{002d}0-9a-zĉĝĥĵŝŭ]{1,63}$/iu', |
| 351 | 18=> '/^[\x{002d}0-9a-zâäéëîô]{1,63}$/iu', |
| 352 | 19=> '/^[\x{002d}0-9a-zàáâäåæçèéêëìíîïðñòôöøùúûüýćčłńřśš]{1,63}$/iu', |
| 353 | 20=> '/^[\x{002d}0-9a-zäåæõöøüšž]{1,63}$/iu', |
| 354 | 21=> '/^[\x{002d}0-9a-zàáçèéìíòóùú]{1,63}$/iu', |
| 355 | 22=> '/^[\x{002d}0-9a-zàáéíóöúüőű]{1,63}$/iu', |
| 356 | 23=> '/^[\x{002d}0-9ΐά-ώ]{1,63}$/iu', |
| 357 | 24=> '/^[\x{002d}0-9a-zàáâåæçèéêëðóôöøüþœ]{1,63}$/iu', |
| 358 | 25=> '/^[\x{002d}0-9a-záäéíóöúüýčďěňřšťůž]{1,63}$/iu', |
| 359 | 26=> '/^[\x{002d}0-9a-z·àçèéíïòóúü]{1,63}$/iu', |
| 360 | 27=> '/^[\x{002d}0-9а-ъьюя\x{0450}\x{045D}]{1,63}$/iu', |
| 361 | 28=> '/^[\x{002d}0-9а-яёіў]{1,63}$/iu', |
| 362 | 29=> '/^[\x{002d}0-9a-z� |
| 363 | čėęįšūųž]{1,63}$/iu', |
| 364 | 30=> '/^[\x{002d}0-9a-záäåæéëíðóöøúüýþ]{1,63}$/iu', |
| 365 | 31=> '/^[\x{002d}0-9a-zàâæçèéêëîïñôùûüÿœ]{1,63}$/iu', |
| 366 | 32=> '/^[\x{002d}0-9а-щъыьэюяёєіїґ]{1,63}$/iu', |
| 367 | 33=> '/^[\x{002d}0-9א-ת]{1,63}$/iu'), |
| 368 | 'PR' => array(1 => '/^[\x{002d}0-9a-záéíóúñäëïüöâêîôûàèùæçœãõ]{1,63}$/iu'), |
| 369 | 'PT' => array(1 => '/^[\x{002d}0-9a-záàâãçéêíóôõú]{1,63}$/iu'), |
| 370 | 'RU' => array(1 => '/^[\x{002d}0-9а-яё]{1,63}$/iu'), |
| 371 | 'SA' => array(1 => '/^[\x{002d}.0-9\x{0621}-\x{063A}\x{0641}-\x{064A}\x{0660}-\x{0669}]{1,63}$/iu'), |
| 372 | 'SE' => array(1 => '/^[\x{002d}0-9a-zäåéöü]{1,63}$/iu'), |
| 373 | 'SH' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿă� |
| 374 | āćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'), |
| 375 | 'SJ' => array(1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'), |
| 376 | 'TH' => array(1 => '/^[\x{002d}0-9a-z\x{0E01}-\x{0E3A}\x{0E40}-\x{0E4D}\x{0E50}-\x{0E59}]{1,63}$/iu'), |
| 377 | 'TM' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿāă� |
| 378 | ćĉċčďđēėęěĝġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśŝşšţťŧūŭůűųŵŷźżž]{1,63}$/iu'), |
| 379 | 'TW' => 'Hostname/Cn.php', |
| 380 | 'TR' => array(1 => '/^[\x{002d}0-9a-zğıüşöç]{1,63}$/iu'), |
| 381 | 'VE' => array(1 => '/^[\x{002d}0-9a-záéíóúüñ]{1,63}$/iu'), |
| 382 | 'VN' => array(1 => '/^[ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚÝàáâãèéêìíòóôõùúýĂăĐđĨĩŨũƠơƯư\x{1EA0}-\x{1EF9}]{1,63}$/iu'), |
| 383 | 'कॉम' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 384 | 'セール' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 385 | '佛山' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 386 | '� |
| 387 | �善' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 388 | '集团' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 389 | '在线' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 390 | '한국' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 391 | '点看' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 392 | 'คอม' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 393 | 'ভারত' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 394 | '� |
| 395 | �卦' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 396 | '� |
| 397 | وقع' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 398 | '� |
| 399 | �益' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 400 | '� |
| 401 | �司' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 402 | '移动' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 403 | '我爱你' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 404 | 'москва' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 405 | 'қаз' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 406 | 'онлайн' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 407 | 'сайт' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 408 | '联通' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 409 | 'срб' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 410 | 'бел' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 411 | 'קום' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 412 | '时尚' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 413 | '淡马锡' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 414 | 'ファッション' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 415 | 'орг' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 416 | 'नेट' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 417 | 'ストア' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 418 | '삼성' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 419 | 'சிங்கப்பூர்' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 420 | '商标' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 421 | '商店' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 422 | '商城' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 423 | 'дети' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 424 | 'мкд' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 425 | 'ею' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 426 | 'ポイント' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 427 | '新闻' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 428 | '工行' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 429 | 'كو� |
| 430 | ' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 431 | '中文网' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 432 | '中信' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 433 | '中国' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 434 | '中國' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 435 | '娱乐' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 436 | '谷歌' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 437 | 'భారత్' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 438 | 'ලංකා' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 439 | '购物' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 440 | 'クラウド' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 441 | 'ભારત' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 442 | 'भारत' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 443 | '网店' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 444 | 'संगठन' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 445 | '餐� |
| 446 | ' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 447 | '网络' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 448 | 'ком' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 449 | 'укр' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 450 | '香港' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 451 | '诺基亚' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 452 | '食品' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 453 | '飞利浦' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 454 | '台湾' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 455 | '台灣' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 456 | '手表' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 457 | '手机' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 458 | 'мон' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 459 | 'الجزائر' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 460 | 'ع� |
| 461 | ان' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 462 | 'ارا� |
| 463 | كو' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 464 | 'ایران' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 465 | 'ا� |
| 466 | ارات' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 467 | 'بازار' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 468 | 'الاردن' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 469 | '� |
| 470 | وبايلي' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 471 | 'بھارت' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 472 | 'ال� |
| 473 | غرب' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 474 | 'السعودية' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 475 | 'سودان' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 476 | 'ه� |
| 477 | راه' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 478 | 'عراق' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 479 | '� |
| 480 | ليسيا' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 481 | '澳門' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 482 | '닷컴' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 483 | '政府' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 484 | 'شبكة' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 485 | 'بيتك' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 486 | 'გე' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 487 | '机构' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 488 | '组织机构' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 489 | '健康' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 490 | 'ไทย' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 491 | 'سورية' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 492 | 'рус' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 493 | 'рф' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 494 | '珠宝' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 495 | 'تونس' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 496 | '大拿' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 497 | 'みんな' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 498 | 'グーグル' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 499 | 'ελ' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 500 | '世界' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 501 | '書籍' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 502 | 'ਭਾਰਤ' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 503 | '网址' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 504 | '닷넷' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 505 | 'コム' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 506 | '游戏' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 507 | 'VERMöGENSBERATER' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 508 | 'VERMöGENSBERATUNG' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 509 | '企业' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 510 | '信息' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 511 | '嘉里大� |
| 512 | �店' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 513 | '� |
| 514 | صر' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 515 | 'قطر' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 516 | '广东' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 517 | 'இலங்கை' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 518 | 'இந்தியா' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 519 | 'հայ' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 520 | '新加坡' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 521 | 'فلسطين' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 522 | '政务' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 523 | '家電' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 524 | '微博' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 525 | 'ابوظبي' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 526 | '网站' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 527 | '大众汽车' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 528 | '香格里拉' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 529 | 'бг' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 530 | '電訊盈科' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 531 | 'العليان' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 532 | '嘉里' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 533 | 'বাংলা' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 534 | 'католик' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 535 | '通販' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 536 | 'پاکستان' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 537 | 'كاثوليك' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 538 | '天主教' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 539 | 'ಭಾರತ' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 540 | 'ଭାରତ' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 541 | 'ভাৰত' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 542 | 'भारतम्' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 543 | 'भारोत' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 544 | 'اتصالات' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 545 | 'بارت' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 546 | 'ڀارت' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 547 | 'عرب' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 548 | 'ഭാരതം' => array(1 => self::VALID_UNICODE_DOMAIN), |
| 549 | ); |
| 550 | |
| 551 | |
| 552 | protected $_idnLength = array( |
| 553 | 'BIZ' => array(5 => 17, 11 => 15, 12 => 20), |
| 554 | 'CN' => array(1 => 20), |
| 555 | 'COM' => array(3 => 17, 5 => 20), |
| 556 | 'HK' => array(1 => 15), |
| 557 | 'INFO'=> array(4 => 17), |
| 558 | 'KR' => array(1 => 17), |
| 559 | 'NET' => array(3 => 17, 5 => 20), |
| 560 | 'ORG' => array(6 => 17), |
| 561 | 'TW' => array(1 => 20), |
| 562 | 'ایران' => array(1 => 30), |
| 563 | '中国' => array(1 => 20), |
| 564 | '� |
| 565 | �司' => array(1 => 20), |
| 566 | '网络' => array(1 => 20), |
| 567 | ); |
| 568 | |
| 569 | protected $_options = array( |
| 570 | 'allow' => self::ALLOW_DNS, |
| 571 | 'idn' => true, |
| 572 | 'tld' => true, |
| 573 | 'ip' => null |
| 574 | ); |
| 575 | |
| 576 | /** |
| 577 | * Sets validator options |
| 578 | * |
| 579 | * @param integer $allow OPTIONAL Set what types of hostname to allow (default ALLOW_DNS) |
| 580 | * @param boolean $validateIdn OPTIONAL Set whether IDN domains are validated (default true) |
| 581 | * @param boolean $validateTld OPTIONAL Set whether the TLD element of a hostname is validated (default true) |
| 582 | * @param Zend_Validate_Ip $ipValidator OPTIONAL |
| 583 | * @return void |
| 584 | * @see http://www.iana.org/cctld/specifications-policies-cctlds-01apr02.htm Technical Specifications for ccTLDs |
| 585 | */ |
| 586 | public function __construct($options = array()) |
| 587 | { |
| 588 | if ($options instanceof Zend_Config) { |
| 589 | $options = $options->toArray(); |
| 590 | } else if (!is_array($options)) { |
| 591 | $options = func_get_args(); |
| 592 | $temp['allow'] = array_shift($options); |
| 593 | if (!empty($options)) { |
| 594 | $temp['idn'] = array_shift($options); |
| 595 | } |
| 596 | |
| 597 | if (!empty($options)) { |
| 598 | $temp['tld'] = array_shift($options); |
| 599 | } |
| 600 | |
| 601 | if (!empty($options)) { |
| 602 | $temp['ip'] = array_shift($options); |
| 603 | } |
| 604 | |
| 605 | $options = $temp; |
| 606 | } |
| 607 | |
| 608 | $options += $this->_options; |
| 609 | $this->setOptions($options); |
| 610 | } |
| 611 | |
| 612 | /** |
| 613 | * Returns all set options |
| 614 | * |
| 615 | * @return array |
| 616 | */ |
| 617 | public function getOptions() |
| 618 | { |
| 619 | return $this->_options; |
| 620 | } |
| 621 | |
| 622 | /** |
| 623 | * Sets the options for this validator |
| 624 | * |
| 625 | * @param array $options |
| 626 | * @return Zend_Validate_Hostname |
| 627 | */ |
| 628 | public function setOptions($options) |
| 629 | { |
| 630 | if (array_key_exists('allow', $options)) { |
| 631 | $this->setAllow($options['allow']); |
| 632 | } |
| 633 | |
| 634 | if (array_key_exists('idn', $options)) { |
| 635 | $this->setValidateIdn($options['idn']); |
| 636 | } |
| 637 | |
| 638 | if (array_key_exists('tld', $options)) { |
| 639 | $this->setValidateTld($options['tld']); |
| 640 | } |
| 641 | |
| 642 | if (array_key_exists('ip', $options)) { |
| 643 | $this->setIpValidator($options['ip']); |
| 644 | } |
| 645 | |
| 646 | return $this; |
| 647 | } |
| 648 | |
| 649 | /** |
| 650 | * Returns the set ip validator |
| 651 | * |
| 652 | * @return Zend_Validate_Ip |
| 653 | */ |
| 654 | public function getIpValidator() |
| 655 | { |
| 656 | return $this->_options['ip']; |
| 657 | } |
| 658 | |
| 659 | /** |
| 660 | * @param Zend_Validate_Ip $ipValidator OPTIONAL |
| 661 | * @return void; |
| 662 | */ |
| 663 | public function setIpValidator(Zend_Validate_Ip $ipValidator = null) |
| 664 | { |
| 665 | if ($ipValidator === null) { |
| 666 | $ipValidator = new Zend_Validate_Ip(); |
| 667 | } |
| 668 | |
| 669 | $this->_options['ip'] = $ipValidator; |
| 670 | return $this; |
| 671 | } |
| 672 | |
| 673 | /** |
| 674 | * Returns the allow option |
| 675 | * |
| 676 | * @return integer |
| 677 | */ |
| 678 | public function getAllow() |
| 679 | { |
| 680 | return $this->_options['allow']; |
| 681 | } |
| 682 | |
| 683 | /** |
| 684 | * Sets the allow option |
| 685 | * |
| 686 | * @param integer $allow |
| 687 | * @return Zend_Validate_Hostname Provides a fluent interface |
| 688 | */ |
| 689 | public function setAllow($allow) |
| 690 | { |
| 691 | $this->_options['allow'] = $allow; |
| 692 | return $this; |
| 693 | } |
| 694 | |
| 695 | /** |
| 696 | * Returns the set idn option |
| 697 | * |
| 698 | * @return boolean |
| 699 | */ |
| 700 | public function getValidateIdn() |
| 701 | { |
| 702 | return $this->_options['idn']; |
| 703 | } |
| 704 | |
| 705 | /** |
| 706 | * Set whether IDN domains are validated |
| 707 | * |
| 708 | * This only applies when DNS hostnames are validated |
| 709 | * |
| 710 | * @param boolean $allowed Set allowed to true to validate IDNs, and false to not validate them |
| 711 | */ |
| 712 | public function setValidateIdn ($allowed) |
| 713 | { |
| 714 | $this->_options['idn'] = (bool) $allowed; |
| 715 | return $this; |
| 716 | } |
| 717 | |
| 718 | /** |
| 719 | * Returns the set tld option |
| 720 | * |
| 721 | * @return boolean |
| 722 | */ |
| 723 | public function getValidateTld() |
| 724 | { |
| 725 | return $this->_options['tld']; |
| 726 | } |
| 727 | |
| 728 | /** |
| 729 | * Set whether the TLD element of a hostname is validated |
| 730 | * |
| 731 | * This only applies when DNS hostnames are validated |
| 732 | * |
| 733 | * @param boolean $allowed Set allowed to true to validate TLDs, and false to not validate them |
| 734 | */ |
| 735 | public function setValidateTld ($allowed) |
| 736 | { |
| 737 | $this->_options['tld'] = (bool) $allowed; |
| 738 | return $this; |
| 739 | } |
| 740 | |
| 741 | /** |
| 742 | * Defined by Zend_Validate_Interface |
| 743 | * |
| 744 | * Returns true if and only if the $value is a valid hostname with respect to the current allow option |
| 745 | * |
| 746 | * @param string $value |
| 747 | * @throws Zend_Validate_Exception if a fatal error occurs for validation process |
| 748 | * @return boolean |
| 749 | */ |
| 750 | public function isValid($value) |
| 751 | { |
| 752 | if (!is_string($value)) { |
| 753 | $this->_error(self::INVALID); |
| 754 | return false; |
| 755 | } |
| 756 | |
| 757 | $this->_setValue($value); |
| 758 | // Check input against IP address schema |
| 759 | if (preg_match('/^[0-9a-f:.]*$/i', $value) && |
| 760 | $this->_options['ip']->setTranslator($this->getTranslator())->isValid($value)) { |
| 761 | if (!($this->_options['allow'] & self::ALLOW_IP)) { |
| 762 | $this->_error(self::IP_ADDRESS_NOT_ALLOWED); |
| 763 | return false; |
| 764 | } else { |
| 765 | return true; |
| 766 | } |
| 767 | } |
| 768 | |
| 769 | // RFC3986 3.2.2 states: |
| 770 | // |
| 771 | // The rightmost domain label of a fully qualified domain name |
| 772 | // in DNS may be followed by a single "." and should be if it is |
| 773 | // necessary to distinguish between the complete domain name and |
| 774 | // some local domain. |
| 775 | // |
| 776 | // (see ZF-6363) |
| 777 | |
| 778 | // Local hostnames are allowed to be partitial (ending '.') |
| 779 | if ($this->_options['allow'] & self::ALLOW_LOCAL) { |
| 780 | if (substr($value, -1) === '.') { |
| 781 | $value = substr($value, 0, -1); |
| 782 | if (substr($value, -1) === '.') { |
| 783 | // Empty hostnames (ending '..') are not allowed |
| 784 | $this->_error(self::INVALID_LOCAL_NAME); |
| 785 | return false; |
| 786 | } |
| 787 | } |
| 788 | } |
| 789 | |
| 790 | $domainParts = explode('.', $value); |
| 791 | |
| 792 | // Prevent partitial IP V4 adresses (ending '.') |
| 793 | if ((count($domainParts) == 4) && preg_match('/^[0-9.a-e:.]*$/i', $value) && |
| 794 | $this->_options['ip']->setTranslator($this->getTranslator())->isValid($value)) { |
| 795 | $this->_error(self::INVALID_LOCAL_NAME); |
| 796 | } |
| 797 | |
| 798 | // Check input against DNS hostname schema |
| 799 | if ((count($domainParts) > 1) && (strlen($value) >= 4) && (strlen($value) <= 254)) { |
| 800 | $status = false; |
| 801 | |
| 802 | $origenc = PHP_VERSION_ID < 50600 |
| 803 | ? iconv_get_encoding('internal_encoding') |
| 804 | : ini_get('default_charset'); |
| 805 | if (PHP_VERSION_ID < 50600) { |
| 806 | iconv_set_encoding('internal_encoding', 'UTF-8'); |
| 807 | } else { |
| 808 | @ini_set('default_charset', 'UTF-8'); |
| 809 | } |
| 810 | |
| 811 | do { |
| 812 | // First check TLD |
| 813 | $matches = array(); |
| 814 | if (preg_match('/([^.]{2,63})$/i', end($domainParts), $matches) || |
| 815 | (end($domainParts) == 'ایران') || (end($domainParts) == '中国') || |
| 816 | (end($domainParts) == '� |
| 817 | �司') || (end($domainParts) == '网络')) { |
| 818 | |
| 819 | reset($domainParts); |
| 820 | |
| 821 | // Hostname characters are: *(label dot)(label dot label); max 254 chars |
| 822 | // label: id-prefix [*ldh{61} id-prefix]; max 63 chars |
| 823 | // id-prefix: alpha / digit |
| 824 | // ldh: alpha / digit / dash |
| 825 | |
| 826 | // Match TLD against known list |
| 827 | $this->_tld = strtolower($matches[1]); |
| 828 | if ($this->_options['tld']) { |
| 829 | if (!in_array($this->_tld, $this->_validTlds)) { |
| 830 | $this->_error(self::UNKNOWN_TLD); |
| 831 | $status = false; |
| 832 | break; |
| 833 | } |
| 834 | } |
| 835 | |
| 836 | /** |
| 837 | * Match against IDN hostnames |
| 838 | * Note: Keep label regex short to avoid issues with long patterns when matching IDN hostnames |
| 839 | * @see Zend_Validate_Hostname_Interface |
| 840 | */ |
| 841 | $regexChars = array(0 => '/^[a-z0-9\x2d]{1,63}$/i'); |
| 842 | if ($this->_options['idn'] && isset($this->_validIdns[strtoupper($this->_tld)])) { |
| 843 | if (is_string($this->_validIdns[strtoupper($this->_tld)])) { |
| 844 | $regexChars += include(dirname(__FILE__) . DIRECTORY_SEPARATOR . $this->_validIdns[strtoupper($this->_tld)]); |
| 845 | } else { |
| 846 | $regexChars += $this->_validIdns[strtoupper($this->_tld)]; |
| 847 | } |
| 848 | } |
| 849 | |
| 850 | // Check each hostname part |
| 851 | $check = 0; |
| 852 | foreach ($domainParts as $domainPart) { |
| 853 | // Decode Punycode domainnames to IDN |
| 854 | if (strpos($domainPart, 'xn--') === 0) { |
| 855 | $domainPart = $this->decodePunycode(substr($domainPart, 4)); |
| 856 | if ($domainPart === false) { |
| 857 | return false; |
| 858 | } |
| 859 | } |
| 860 | |
| 861 | // Check dash (-) does not start, end or appear in 3rd and 4th positions |
| 862 | if ((strpos($domainPart, '-') === 0) |
| 863 | || ((strlen($domainPart) > 2) && (strpos($domainPart, '-', 2) == 2) && (strpos($domainPart, '-', 3) == 3)) |
| 864 | || (strpos($domainPart, '-') === (strlen($domainPart) - 1))) { |
| 865 | $this->_error(self::INVALID_DASH); |
| 866 | $status = false; |
| 867 | break 2; |
| 868 | } |
| 869 | |
| 870 | // Check each domain part |
| 871 | $checked = false; |
| 872 | foreach($regexChars as $regexKey => $regexChar) { |
| 873 | $status = @preg_match($regexChar, $domainPart); |
| 874 | if ($status > 0) { |
| 875 | $length = 63; |
| 876 | if (array_key_exists(strtoupper($this->_tld), $this->_idnLength) |
| 877 | && (array_key_exists($regexKey, $this->_idnLength[strtoupper($this->_tld)]))) { |
| 878 | $length = $this->_idnLength[strtoupper($this->_tld)]; |
| 879 | } |
| 880 | |
| 881 | if (iconv_strlen($domainPart, 'UTF-8') > $length) { |
| 882 | $this->_error(self::INVALID_HOSTNAME); |
| 883 | } else { |
| 884 | $checked = true; |
| 885 | break; |
| 886 | } |
| 887 | } |
| 888 | } |
| 889 | |
| 890 | if ($checked) { |
| 891 | ++$check; |
| 892 | } |
| 893 | } |
| 894 | |
| 895 | // If one of the labels doesn't match, the hostname is invalid |
| 896 | if ($check !== count($domainParts)) { |
| 897 | $this->_error(self::INVALID_HOSTNAME_SCHEMA); |
| 898 | $status = false; |
| 899 | } |
| 900 | } else { |
| 901 | // Hostname not long enough |
| 902 | $this->_error(self::UNDECIPHERABLE_TLD); |
| 903 | $status = false; |
| 904 | } |
| 905 | } while (false); |
| 906 | |
| 907 | if (PHP_VERSION_ID < 50600) { |
| 908 | iconv_set_encoding('internal_encoding', $origenc); |
| 909 | } else { |
| 910 | @ini_set('default_charset', $origenc); |
| 911 | } |
| 912 | |
| 913 | // If the input passes as an Internet domain name, and domain names are allowed, then the hostname |
| 914 | // passes validation |
| 915 | if ($status && ($this->_options['allow'] & self::ALLOW_DNS)) { |
| 916 | return true; |
| 917 | } |
| 918 | } else if ($this->_options['allow'] & self::ALLOW_DNS) { |
| 919 | $this->_error(self::INVALID_HOSTNAME); |
| 920 | } |
| 921 | |
| 922 | // Check for URI Syntax (RFC3986) |
| 923 | if ($this->_options['allow'] & self::ALLOW_URI) { |
| 924 | if (preg_match("/^([a-zA-Z0-9-._~!$&'()*+,;=]|%[[:xdigit:]]{2}){1,254}$/i", $value)) { |
| 925 | return true; |
| 926 | } else { |
| 927 | $this->_error(self::INVALID_URI); |
| 928 | } |
| 929 | } |
| 930 | |
| 931 | // Check input against local network name schema; last chance to pass validation |
| 932 | $regexLocal = '/^(([a-zA-Z0-9\x2d]{1,63}\x2e)*[a-zA-Z0-9\x2d]{1,63}[\x2e]{0,1}){1,254}$/'; |
| 933 | $status = @preg_match($regexLocal, $value); |
| 934 | |
| 935 | // If the input passes as a local network name, and local network names are allowed, then the |
| 936 | // hostname passes validation |
| 937 | $allowLocal = $this->_options['allow'] & self::ALLOW_LOCAL; |
| 938 | if ($status && $allowLocal) { |
| 939 | return true; |
| 940 | } |
| 941 | |
| 942 | // If the input does not pass as a local network name, add a message |
| 943 | if (!$status) { |
| 944 | $this->_error(self::INVALID_LOCAL_NAME); |
| 945 | } |
| 946 | |
| 947 | // If local network names are not allowed, add a message |
| 948 | if ($status && !$allowLocal) { |
| 949 | $this->_error(self::LOCAL_NAME_NOT_ALLOWED); |
| 950 | } |
| 951 | |
| 952 | return false; |
| 953 | } |
| 954 | |
| 955 | /** |
| 956 | * Decodes a punycode encoded string to it's original utf8 string |
| 957 | * In case of a decoding failure the original string is returned |
| 958 | * |
| 959 | * @param string $encoded Punycode encoded string to decode |
| 960 | * @return string |
| 961 | */ |
| 962 | protected function decodePunycode($encoded) |
| 963 | { |
| 964 | $found = preg_match('/([^a-z0-9\x2d]{1,10})$/i', $encoded); |
| 965 | if (empty($encoded) || ($found > 0)) { |
| 966 | // no punycode encoded string, return as is |
| 967 | $this->_error(self::CANNOT_DECODE_PUNYCODE); |
| 968 | return false; |
| 969 | } |
| 970 | |
| 971 | $separator = strrpos($encoded, '-'); |
| 972 | if ($separator > 0) { |
| 973 | for ($x = 0; $x < $separator; ++$x) { |
| 974 | // prepare decoding matrix |
| 975 | $decoded[] = ord($encoded[$x]); |
| 976 | } |
| 977 | } else { |
| 978 | $this->_error(self::CANNOT_DECODE_PUNYCODE); |
| 979 | return false; |
| 980 | } |
| 981 | |
| 982 | $lengthd = count($decoded); |
| 983 | $lengthe = strlen($encoded); |
| 984 | |
| 985 | // decoding |
| 986 | $init = true; |
| 987 | $base = 72; |
| 988 | $index = 0; |
| 989 | $char = 0x80; |
| 990 | |
| 991 | for ($indexe = ($separator) ? ($separator + 1) : 0; $indexe < $lengthe; ++$lengthd) { |
| 992 | for ($old_index = $index, $pos = 1, $key = 36; 1 ; $key += 36) { |
| 993 | $hex = ord($encoded[$indexe++]); |
| 994 | $digit = ($hex - 48 < 10) ? $hex - 22 |
| 995 | : (($hex - 65 < 26) ? $hex - 65 |
| 996 | : (($hex - 97 < 26) ? $hex - 97 |
| 997 | : 36)); |
| 998 | |
| 999 | $index += $digit * $pos; |
| 1000 | $tag = ($key <= $base) ? 1 : (($key >= $base + 26) ? 26 : ($key - $base)); |
| 1001 | if ($digit < $tag) { |
| 1002 | break; |
| 1003 | } |
| 1004 | |
| 1005 | $pos = (int) ($pos * (36 - $tag)); |
| 1006 | } |
| 1007 | |
| 1008 | $delta = intval($init ? (($index - $old_index) / 700) : (($index - $old_index) / 2)); |
| 1009 | $delta += intval($delta / ($lengthd + 1)); |
| 1010 | for ($key = 0; $delta > 910 / 2; $key += 36) { |
| 1011 | $delta = intval($delta / 35); |
| 1012 | } |
| 1013 | |
| 1014 | $base = intval($key + 36 * $delta / ($delta + 38)); |
| 1015 | $init = false; |
| 1016 | $char += (int) ($index / ($lengthd + 1)); |
| 1017 | $index %= ($lengthd + 1); |
| 1018 | if ($lengthd > 0) { |
| 1019 | for ($i = $lengthd; $i > $index; $i--) { |
| 1020 | $decoded[$i] = $decoded[($i - 1)]; |
| 1021 | } |
| 1022 | } |
| 1023 | |
| 1024 | $decoded[$index++] = $char; |
| 1025 | } |
| 1026 | |
| 1027 | // convert decoded ucs4 to utf8 string |
| 1028 | foreach ($decoded as $key => $value) { |
| 1029 | if ($value < 128) { |
| 1030 | $decoded[$key] = chr($value); |
| 1031 | } elseif ($value < (1 << 11)) { |
| 1032 | $decoded[$key] = chr(192 + ($value >> 6)); |
| 1033 | $decoded[$key] .= chr(128 + ($value & 63)); |
| 1034 | } elseif ($value < (1 << 16)) { |
| 1035 | $decoded[$key] = chr(224 + ($value >> 12)); |
| 1036 | $decoded[$key] .= chr(128 + (($value >> 6) & 63)); |
| 1037 | $decoded[$key] .= chr(128 + ($value & 63)); |
| 1038 | } elseif ($value < (1 << 21)) { |
| 1039 | $decoded[$key] = chr(240 + ($value >> 18)); |
| 1040 | $decoded[$key] .= chr(128 + (($value >> 12) & 63)); |
| 1041 | $decoded[$key] .= chr(128 + (($value >> 6) & 63)); |
| 1042 | $decoded[$key] .= chr(128 + ($value & 63)); |
| 1043 | } else { |
| 1044 | $this->_error(self::CANNOT_DECODE_PUNYCODE); |
| 1045 | return false; |
| 1046 | } |
| 1047 | } |
| 1048 | |
| 1049 | return implode($decoded); |
| 1050 | } |
| 1051 | } |
| 1052 |