[5146] | 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-2010 Zend Technologies USA Inc. (http://www.zend.com) |
---|
| 18 | * @license http://framework.zend.com/license/new-bsd New BSD License |
---|
| 19 | * @version $Id: EmailAddress.php 22668 2010-07-25 14:50:46Z thomas $ |
---|
| 20 | */ |
---|
| 21 | |
---|
| 22 | /** |
---|
| 23 | * @see Zend_Validate_Abstract |
---|
| 24 | */ |
---|
| 25 | require_once 'Zend/Validate/Abstract.php'; |
---|
| 26 | |
---|
| 27 | /** |
---|
| 28 | * @see Zend_Validate_Hostname |
---|
| 29 | */ |
---|
| 30 | require_once 'Zend/Validate/Hostname.php'; |
---|
| 31 | |
---|
| 32 | /** |
---|
| 33 | * @category Zend |
---|
| 34 | * @package Zend_Validate |
---|
| 35 | * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
---|
| 36 | * @license http://framework.zend.com/license/new-bsd New BSD License |
---|
| 37 | */ |
---|
| 38 | class Zend_Validate_EmailAddress extends Zend_Validate_Abstract |
---|
| 39 | { |
---|
| 40 | const INVALID = 'emailAddressInvalid'; |
---|
| 41 | const INVALID_FORMAT = 'emailAddressInvalidFormat'; |
---|
| 42 | const INVALID_HOSTNAME = 'emailAddressInvalidHostname'; |
---|
| 43 | const INVALID_MX_RECORD = 'emailAddressInvalidMxRecord'; |
---|
| 44 | const INVALID_SEGMENT = 'emailAddressInvalidSegment'; |
---|
| 45 | const DOT_ATOM = 'emailAddressDotAtom'; |
---|
| 46 | const QUOTED_STRING = 'emailAddressQuotedString'; |
---|
| 47 | const INVALID_LOCAL_PART = 'emailAddressInvalidLocalPart'; |
---|
| 48 | const LENGTH_EXCEEDED = 'emailAddressLengthExceeded'; |
---|
| 49 | |
---|
| 50 | /** |
---|
| 51 | * @var array |
---|
| 52 | */ |
---|
| 53 | protected $_messageTemplates = array( |
---|
| 54 | self::INVALID => "Invalid type given. String expected", |
---|
| 55 | self::INVALID_FORMAT => "'%value%' is no valid email address in the basic format local-part@hostname", |
---|
| 56 | self::INVALID_HOSTNAME => "'%hostname%' is no valid hostname for email address '%value%'", |
---|
| 57 | self::INVALID_MX_RECORD => "'%hostname%' does not appear to have a valid MX record for the email address '%value%'", |
---|
| 58 | self::INVALID_SEGMENT => "'%hostname%' is not in a routable network segment. The email address '%value%' should not be resolved from public network", |
---|
| 59 | self::DOT_ATOM => "'%localPart%' can not be matched against dot-atom format", |
---|
| 60 | self::QUOTED_STRING => "'%localPart%' can not be matched against quoted-string format", |
---|
| 61 | self::INVALID_LOCAL_PART => "'%localPart%' is no valid local part for email address '%value%'", |
---|
| 62 | self::LENGTH_EXCEEDED => "'%value%' exceeds the allowed length", |
---|
| 63 | ); |
---|
| 64 | |
---|
| 65 | /** |
---|
| 66 | * @see http://en.wikipedia.org/wiki/IPv4 |
---|
| 67 | * @var array |
---|
| 68 | */ |
---|
| 69 | protected $_invalidIp = array( |
---|
| 70 | '0' => '0.0.0.0/8', |
---|
| 71 | '10' => '10.0.0.0/8', |
---|
| 72 | '127' => '127.0.0.0/8', |
---|
| 73 | '128' => '128.0.0.0/16', |
---|
| 74 | '169' => '169.254.0.0/16', |
---|
| 75 | '172' => '172.16.0.0/12', |
---|
| 76 | '191' => '191.255.0.0/16', |
---|
| 77 | '192' => array( |
---|
| 78 | '192.0.0.0/24', |
---|
| 79 | '192.0.2.0/24', |
---|
| 80 | '192.88.99.0/24', |
---|
| 81 | '192.168.0.0/16' |
---|
| 82 | ), |
---|
| 83 | '198' => '198.18.0.0/15', |
---|
| 84 | '223' => '223.255.255.0/24', |
---|
| 85 | '224' => '224.0.0.0/4', |
---|
| 86 | '240' => '240.0.0.0/4' |
---|
| 87 | ); |
---|
| 88 | |
---|
| 89 | /** |
---|
| 90 | * @var array |
---|
| 91 | */ |
---|
| 92 | protected $_messageVariables = array( |
---|
| 93 | 'hostname' => '_hostname', |
---|
| 94 | 'localPart' => '_localPart' |
---|
| 95 | ); |
---|
| 96 | |
---|
| 97 | /** |
---|
| 98 | * @var string |
---|
| 99 | */ |
---|
| 100 | protected $_hostname; |
---|
| 101 | |
---|
| 102 | /** |
---|
| 103 | * @var string |
---|
| 104 | */ |
---|
| 105 | protected $_localPart; |
---|
| 106 | |
---|
| 107 | /** |
---|
| 108 | * Internal options array |
---|
| 109 | */ |
---|
| 110 | protected $_options = array( |
---|
| 111 | 'mx' => false, |
---|
| 112 | 'deep' => false, |
---|
| 113 | 'domain' => true, |
---|
| 114 | 'allow' => Zend_Validate_Hostname::ALLOW_DNS, |
---|
| 115 | 'hostname' => null |
---|
| 116 | ); |
---|
| 117 | |
---|
| 118 | /** |
---|
| 119 | * Instantiates hostname validator for local use |
---|
| 120 | * |
---|
| 121 | * The following option keys are supported: |
---|
| 122 | * 'hostname' => A hostname validator, see Zend_Validate_Hostname |
---|
| 123 | * 'allow' => Options for the hostname validator, see Zend_Validate_Hostname::ALLOW_* |
---|
| 124 | * 'mx' => If MX check should be enabled, boolean |
---|
| 125 | * 'deep' => If a deep MX check should be done, boolean |
---|
| 126 | * |
---|
| 127 | * @param array|Zend_Config $options OPTIONAL |
---|
| 128 | * @return void |
---|
| 129 | */ |
---|
| 130 | public function __construct($options = array()) |
---|
| 131 | { |
---|
| 132 | if ($options instanceof Zend_Config) { |
---|
| 133 | $options = $options->toArray(); |
---|
| 134 | } else if (!is_array($options)) { |
---|
| 135 | $options = func_get_args(); |
---|
| 136 | $temp['allow'] = array_shift($options); |
---|
| 137 | if (!empty($options)) { |
---|
| 138 | $temp['mx'] = array_shift($options); |
---|
| 139 | } |
---|
| 140 | |
---|
| 141 | if (!empty($options)) { |
---|
| 142 | $temp['hostname'] = array_shift($options); |
---|
| 143 | } |
---|
| 144 | |
---|
| 145 | $options = $temp; |
---|
| 146 | } |
---|
| 147 | |
---|
| 148 | $options += $this->_options; |
---|
| 149 | $this->setOptions($options); |
---|
| 150 | } |
---|
| 151 | |
---|
| 152 | /** |
---|
| 153 | * Returns all set Options |
---|
| 154 | * |
---|
| 155 | * @return array |
---|
| 156 | */ |
---|
| 157 | public function getOptions() |
---|
| 158 | { |
---|
| 159 | return $this->_options; |
---|
| 160 | } |
---|
| 161 | |
---|
| 162 | /** |
---|
| 163 | * Set options for the email validator |
---|
| 164 | * |
---|
| 165 | * @param array $options |
---|
| 166 | * @return Zend_Validate_EmailAddress fluid interface |
---|
| 167 | */ |
---|
| 168 | public function setOptions(array $options = array()) |
---|
| 169 | { |
---|
| 170 | if (array_key_exists('messages', $options)) { |
---|
| 171 | $this->setMessages($options['messages']); |
---|
| 172 | } |
---|
| 173 | |
---|
| 174 | if (array_key_exists('hostname', $options)) { |
---|
| 175 | if (array_key_exists('allow', $options)) { |
---|
| 176 | $this->setHostnameValidator($options['hostname'], $options['allow']); |
---|
| 177 | } else { |
---|
| 178 | $this->setHostnameValidator($options['hostname']); |
---|
| 179 | } |
---|
| 180 | } |
---|
| 181 | |
---|
| 182 | if (array_key_exists('mx', $options)) { |
---|
| 183 | $this->setValidateMx($options['mx']); |
---|
| 184 | } |
---|
| 185 | |
---|
| 186 | if (array_key_exists('deep', $options)) { |
---|
| 187 | $this->setDeepMxCheck($options['deep']); |
---|
| 188 | } |
---|
| 189 | |
---|
| 190 | if (array_key_exists('domain', $options)) { |
---|
| 191 | $this->setDomainCheck($options['domain']); |
---|
| 192 | } |
---|
| 193 | |
---|
| 194 | return $this; |
---|
| 195 | } |
---|
| 196 | |
---|
| 197 | /** |
---|
| 198 | * Sets the validation failure message template for a particular key |
---|
| 199 | * Adds the ability to set messages to the attached hostname validator |
---|
| 200 | * |
---|
| 201 | * @param string $messageString |
---|
| 202 | * @param string $messageKey OPTIONAL |
---|
| 203 | * @return Zend_Validate_Abstract Provides a fluent interface |
---|
| 204 | * @throws Zend_Validate_Exception |
---|
| 205 | */ |
---|
| 206 | public function setMessage($messageString, $messageKey = null) |
---|
| 207 | { |
---|
| 208 | $messageKeys = $messageKey; |
---|
| 209 | if ($messageKey === null) { |
---|
| 210 | $keys = array_keys($this->_messageTemplates); |
---|
| 211 | $messageKeys = current($keys); |
---|
| 212 | } |
---|
| 213 | |
---|
| 214 | if (!isset($this->_messageTemplates[$messageKeys])) { |
---|
| 215 | $this->_options['hostname']->setMessage($messageString, $messageKey); |
---|
| 216 | } |
---|
| 217 | |
---|
| 218 | $this->_messageTemplates[$messageKeys] = $messageString; |
---|
| 219 | return $this; |
---|
| 220 | } |
---|
| 221 | |
---|
| 222 | /** |
---|
| 223 | * Returns the set hostname validator |
---|
| 224 | * |
---|
| 225 | * @return Zend_Validate_Hostname |
---|
| 226 | */ |
---|
| 227 | public function getHostnameValidator() |
---|
| 228 | { |
---|
| 229 | return $this->_options['hostname']; |
---|
| 230 | } |
---|
| 231 | |
---|
| 232 | /** |
---|
| 233 | * @param Zend_Validate_Hostname $hostnameValidator OPTIONAL |
---|
| 234 | * @param int $allow OPTIONAL |
---|
| 235 | * @return void |
---|
| 236 | */ |
---|
| 237 | public function setHostnameValidator(Zend_Validate_Hostname $hostnameValidator = null, $allow = Zend_Validate_Hostname::ALLOW_DNS) |
---|
| 238 | { |
---|
| 239 | if (!$hostnameValidator) { |
---|
| 240 | $hostnameValidator = new Zend_Validate_Hostname($allow); |
---|
| 241 | } |
---|
| 242 | |
---|
| 243 | $this->_options['hostname'] = $hostnameValidator; |
---|
| 244 | $this->_options['allow'] = $allow; |
---|
| 245 | return $this; |
---|
| 246 | } |
---|
| 247 | |
---|
| 248 | /** |
---|
| 249 | * Whether MX checking via getmxrr is supported or not |
---|
| 250 | * |
---|
| 251 | * This currently only works on UNIX systems |
---|
| 252 | * |
---|
| 253 | * @return boolean |
---|
| 254 | */ |
---|
| 255 | public function validateMxSupported() |
---|
| 256 | { |
---|
| 257 | return function_exists('getmxrr'); |
---|
| 258 | } |
---|
| 259 | |
---|
| 260 | /** |
---|
| 261 | * Returns the set validateMx option |
---|
| 262 | * |
---|
| 263 | * @return boolean |
---|
| 264 | */ |
---|
| 265 | public function getValidateMx() |
---|
| 266 | { |
---|
| 267 | return $this->_options['mx']; |
---|
| 268 | } |
---|
| 269 | |
---|
| 270 | /** |
---|
| 271 | * Set whether we check for a valid MX record via DNS |
---|
| 272 | * |
---|
| 273 | * This only applies when DNS hostnames are validated |
---|
| 274 | * |
---|
| 275 | * @param boolean $mx Set allowed to true to validate for MX records, and false to not validate them |
---|
| 276 | * @return Zend_Validate_EmailAddress Fluid Interface |
---|
| 277 | */ |
---|
| 278 | public function setValidateMx($mx) |
---|
| 279 | { |
---|
| 280 | if ((bool) $mx && !$this->validateMxSupported()) { |
---|
| 281 | require_once 'Zend/Validate/Exception.php'; |
---|
| 282 | throw new Zend_Validate_Exception('MX checking not available on this system'); |
---|
| 283 | } |
---|
| 284 | |
---|
| 285 | $this->_options['mx'] = (bool) $mx; |
---|
| 286 | return $this; |
---|
| 287 | } |
---|
| 288 | |
---|
| 289 | /** |
---|
| 290 | * Returns the set deepMxCheck option |
---|
| 291 | * |
---|
| 292 | * @return boolean |
---|
| 293 | */ |
---|
| 294 | public function getDeepMxCheck() |
---|
| 295 | { |
---|
| 296 | return $this->_options['deep']; |
---|
| 297 | } |
---|
| 298 | |
---|
| 299 | /** |
---|
| 300 | * Set whether we check MX record should be a deep validation |
---|
| 301 | * |
---|
| 302 | * @param boolean $deep Set deep to true to perform a deep validation process for MX records |
---|
| 303 | * @return Zend_Validate_EmailAddress Fluid Interface |
---|
| 304 | */ |
---|
| 305 | public function setDeepMxCheck($deep) |
---|
| 306 | { |
---|
| 307 | $this->_options['deep'] = (bool) $deep; |
---|
| 308 | return $this; |
---|
| 309 | } |
---|
| 310 | |
---|
| 311 | /** |
---|
| 312 | * Returns the set domainCheck option |
---|
| 313 | * |
---|
| 314 | * @return unknown |
---|
| 315 | */ |
---|
| 316 | public function getDomainCheck() |
---|
| 317 | { |
---|
| 318 | return $this->_options['domain']; |
---|
| 319 | } |
---|
| 320 | |
---|
| 321 | /** |
---|
| 322 | * Sets if the domain should also be checked |
---|
| 323 | * or only the local part of the email address |
---|
| 324 | * |
---|
| 325 | * @param boolean $domain |
---|
| 326 | * @return Zend_Validate_EmailAddress Fluid Interface |
---|
| 327 | */ |
---|
| 328 | public function setDomainCheck($domain = true) |
---|
| 329 | { |
---|
| 330 | $this->_options['domain'] = (boolean) $domain; |
---|
| 331 | return $this; |
---|
| 332 | } |
---|
| 333 | |
---|
| 334 | /** |
---|
| 335 | * Returns if the given host is reserved |
---|
| 336 | * |
---|
| 337 | * @param string $host |
---|
| 338 | * @return boolean |
---|
| 339 | */ |
---|
| 340 | private function _isReserved($host){ |
---|
| 341 | if (!preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $host)) { |
---|
| 342 | $host = gethostbyname($host); |
---|
| 343 | } |
---|
| 344 | |
---|
| 345 | $octet = explode('.',$host); |
---|
| 346 | if ((int)$octet[0] >= 224) { |
---|
| 347 | return true; |
---|
| 348 | } else if (array_key_exists($octet[0], $this->_invalidIp)) { |
---|
| 349 | foreach ((array)$this->_invalidIp[$octet[0]] as $subnetData) { |
---|
| 350 | // we skip the first loop as we already know that octet matches |
---|
| 351 | for ($i = 1; $i < 4; $i++) { |
---|
| 352 | if (strpos($subnetData, $octet[$i]) !== $i * 4) { |
---|
| 353 | break; |
---|
| 354 | } |
---|
| 355 | } |
---|
| 356 | |
---|
| 357 | $host = explode("/", $subnetData); |
---|
| 358 | $binaryHost = ""; |
---|
| 359 | $tmp = explode(".", $host[0]); |
---|
| 360 | for ($i = 0; $i < 4 ; $i++) { |
---|
| 361 | $binaryHost .= str_pad(decbin($tmp[$i]), 8, "0", STR_PAD_LEFT); |
---|
| 362 | } |
---|
| 363 | |
---|
| 364 | $segmentData = array( |
---|
| 365 | 'network' => (int)$this->_toIp(str_pad(substr($binaryHost, 0, $host[1]), 32, 0)), |
---|
| 366 | 'broadcast' => (int)$this->_toIp(str_pad(substr($binaryHost, 0, $host[1]), 32, 1)) |
---|
| 367 | ); |
---|
| 368 | |
---|
| 369 | for ($j = $i; $j < 4; $j++) { |
---|
| 370 | if ((int)$octet[$j] < $segmentData['network'][$j] || |
---|
| 371 | (int)$octet[$j] > $segmentData['broadcast'][$j]) { |
---|
| 372 | return false; |
---|
| 373 | } |
---|
| 374 | } |
---|
| 375 | } |
---|
| 376 | |
---|
| 377 | return true; |
---|
| 378 | } else { |
---|
| 379 | return false; |
---|
| 380 | } |
---|
| 381 | } |
---|
| 382 | |
---|
| 383 | /** |
---|
| 384 | * Converts a binary string to an IP address |
---|
| 385 | * |
---|
| 386 | * @param string $binary |
---|
| 387 | * @return mixed |
---|
| 388 | */ |
---|
| 389 | private function _toIp($binary) |
---|
| 390 | { |
---|
| 391 | $ip = array(); |
---|
| 392 | $tmp = explode(".", chunk_split($binary, 8, ".")); |
---|
| 393 | for ($i = 0; $i < 4 ; $i++) { |
---|
| 394 | $ip[$i] = bindec($tmp[$i]); |
---|
| 395 | } |
---|
| 396 | |
---|
| 397 | return $ip; |
---|
| 398 | } |
---|
| 399 | |
---|
| 400 | /** |
---|
| 401 | * Internal method to validate the local part of the email address |
---|
| 402 | * |
---|
| 403 | * @return boolean |
---|
| 404 | */ |
---|
| 405 | private function _validateLocalPart() |
---|
| 406 | { |
---|
| 407 | // First try to match the local part on the common dot-atom format |
---|
| 408 | $result = false; |
---|
| 409 | |
---|
| 410 | // Dot-atom characters are: 1*atext *("." 1*atext) |
---|
| 411 | // atext: ALPHA / DIGIT / and "!", "#", "$", "%", "&", "'", "*", |
---|
| 412 | // "+", "-", "/", "=", "?", "^", "_", "`", "{", "|", "}", "~" |
---|
| 413 | $atext = 'a-zA-Z0-9\x21\x23\x24\x25\x26\x27\x2a\x2b\x2d\x2f\x3d\x3f\x5e\x5f\x60\x7b\x7c\x7d\x7e'; |
---|
| 414 | if (preg_match('/^[' . $atext . ']+(\x2e+[' . $atext . ']+)*$/', $this->_localPart)) { |
---|
| 415 | $result = true; |
---|
| 416 | } else { |
---|
| 417 | // Try quoted string format |
---|
| 418 | |
---|
| 419 | // Quoted-string characters are: DQUOTE *([FWS] qtext/quoted-pair) [FWS] DQUOTE |
---|
| 420 | // qtext: Non white space controls, and the rest of the US-ASCII characters not |
---|
| 421 | // including "\" or the quote character |
---|
| 422 | $noWsCtl = '\x01-\x08\x0b\x0c\x0e-\x1f\x7f'; |
---|
| 423 | $qtext = $noWsCtl . '\x21\x23-\x5b\x5d-\x7e'; |
---|
| 424 | $ws = '\x20\x09'; |
---|
| 425 | if (preg_match('/^\x22([' . $ws . $qtext . '])*[$ws]?\x22$/', $this->_localPart)) { |
---|
| 426 | $result = true; |
---|
| 427 | } else { |
---|
| 428 | $this->_error(self::DOT_ATOM); |
---|
| 429 | $this->_error(self::QUOTED_STRING); |
---|
| 430 | $this->_error(self::INVALID_LOCAL_PART); |
---|
| 431 | } |
---|
| 432 | } |
---|
| 433 | |
---|
| 434 | return $result; |
---|
| 435 | } |
---|
| 436 | |
---|
| 437 | /** |
---|
| 438 | * Internal method to validate the servers MX records |
---|
| 439 | * |
---|
| 440 | * @return boolean |
---|
| 441 | */ |
---|
| 442 | private function _validateMXRecords() |
---|
| 443 | { |
---|
| 444 | $mxHosts = array(); |
---|
| 445 | $result = getmxrr($this->_hostname, $mxHosts); |
---|
| 446 | if (!$result) { |
---|
| 447 | $this->_error(self::INVALID_MX_RECORD); |
---|
| 448 | } else if ($this->_options['deep'] && function_exists('checkdnsrr')) { |
---|
| 449 | $validAddress = false; |
---|
| 450 | $reserved = true; |
---|
| 451 | foreach ($mxHosts as $hostname) { |
---|
| 452 | $res = $this->_isReserved($hostname); |
---|
| 453 | if (!$res) { |
---|
| 454 | $reserved = false; |
---|
| 455 | } |
---|
| 456 | |
---|
| 457 | if (!$res |
---|
| 458 | && (checkdnsrr($hostname, "A") |
---|
| 459 | || checkdnsrr($hostname, "AAAA") |
---|
| 460 | || checkdnsrr($hostname, "A6"))) { |
---|
| 461 | $validAddress = true; |
---|
| 462 | break; |
---|
| 463 | } |
---|
| 464 | } |
---|
| 465 | |
---|
| 466 | if (!$validAddress) { |
---|
| 467 | $result = false; |
---|
| 468 | if ($reserved) { |
---|
| 469 | $this->_error(self::INVALID_SEGMENT); |
---|
| 470 | } else { |
---|
| 471 | $this->_error(self::INVALID_MX_RECORD); |
---|
| 472 | } |
---|
| 473 | } |
---|
| 474 | } |
---|
| 475 | |
---|
| 476 | return $result; |
---|
| 477 | } |
---|
| 478 | |
---|
| 479 | /** |
---|
| 480 | * Internal method to validate the hostname part of the email address |
---|
| 481 | * |
---|
| 482 | * @return boolean |
---|
| 483 | */ |
---|
| 484 | private function _validateHostnamePart() |
---|
| 485 | { |
---|
| 486 | $hostname = $this->_options['hostname']->setTranslator($this->getTranslator()) |
---|
| 487 | ->isValid($this->_hostname); |
---|
| 488 | if (!$hostname) { |
---|
| 489 | $this->_error(self::INVALID_HOSTNAME); |
---|
| 490 | |
---|
| 491 | // Get messages and errors from hostnameValidator |
---|
| 492 | foreach ($this->_options['hostname']->getMessages() as $code => $message) { |
---|
| 493 | $this->_messages[$code] = $message; |
---|
| 494 | } |
---|
| 495 | |
---|
| 496 | foreach ($this->_options['hostname']->getErrors() as $error) { |
---|
| 497 | $this->_errors[] = $error; |
---|
| 498 | } |
---|
| 499 | } else if ($this->_options['mx']) { |
---|
| 500 | // MX check on hostname |
---|
| 501 | $hostname = $this->_validateMXRecords(); |
---|
| 502 | } |
---|
| 503 | |
---|
| 504 | return $hostname; |
---|
| 505 | } |
---|
| 506 | |
---|
| 507 | /** |
---|
| 508 | * Defined by Zend_Validate_Interface |
---|
| 509 | * |
---|
| 510 | * Returns true if and only if $value is a valid email address |
---|
| 511 | * according to RFC2822 |
---|
| 512 | * |
---|
| 513 | * @link http://www.ietf.org/rfc/rfc2822.txt RFC2822 |
---|
| 514 | * @link http://www.columbia.edu/kermit/ascii.html US-ASCII characters |
---|
| 515 | * @param string $value |
---|
| 516 | * @return boolean |
---|
| 517 | */ |
---|
| 518 | public function isValid($value) |
---|
| 519 | { |
---|
| 520 | if (!is_string($value)) { |
---|
| 521 | $this->_error(self::INVALID); |
---|
| 522 | return false; |
---|
| 523 | } |
---|
| 524 | |
---|
| 525 | $matches = array(); |
---|
| 526 | $length = true; |
---|
| 527 | $this->_setValue($value); |
---|
| 528 | |
---|
| 529 | // Split email address up and disallow '..' |
---|
| 530 | if ((strpos($value, '..') !== false) or |
---|
| 531 | (!preg_match('/^(.+)@([^@]+)$/', $value, $matches))) { |
---|
| 532 | $this->_error(self::INVALID_FORMAT); |
---|
| 533 | return false; |
---|
| 534 | } |
---|
| 535 | |
---|
| 536 | $this->_localPart = $matches[1]; |
---|
| 537 | $this->_hostname = $matches[2]; |
---|
| 538 | |
---|
| 539 | if ((strlen($this->_localPart) > 64) || (strlen($this->_hostname) > 255)) { |
---|
| 540 | $length = false; |
---|
| 541 | $this->_error(self::LENGTH_EXCEEDED); |
---|
| 542 | } |
---|
| 543 | |
---|
| 544 | // Match hostname part |
---|
| 545 | if ($this->_options['domain']) { |
---|
| 546 | $hostname = $this->_validateHostnamePart(); |
---|
| 547 | } |
---|
| 548 | |
---|
| 549 | $local = $this->_validateLocalPart(); |
---|
| 550 | |
---|
| 551 | // If both parts valid, return true |
---|
| 552 | if ($local && $length) { |
---|
| 553 | if (($this->_options['domain'] && $hostname) || !$this->_options['domain']) { |
---|
| 554 | return true; |
---|
| 555 | } |
---|
| 556 | } |
---|
| 557 | |
---|
| 558 | return false; |
---|
| 559 | } |
---|
| 560 | } |
---|