25 #require_once 'Zend/Validate/Abstract.php'; 30 #require_once 'Zend/Validate/Hostname.php'; 54 self::INVALID =>
"Invalid type given. String expected",
55 self::INVALID_FORMAT =>
"'%value%' is not a valid email address in the basic format local-part@hostname",
56 self::INVALID_HOSTNAME =>
"'%hostname%' is not a 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 not a valid local part for email address '%value%'",
62 self::LENGTH_EXCEEDED =>
"'%value%' exceeds the allowed length",
82 '100' =>
'100.64.0.0/10',
83 '127' =>
'127.0.0.0/8',
84 '169' =>
'169.254.0.0/16',
85 '172' =>
'172.16.0.0/12',
92 '198' =>
'198.18.0.0/15',
93 '224' =>
'224.0.0.0/4',
94 '240' =>
'240.0.0.0/4' 101 'hostname' =>
'_hostname',
102 'localPart' =>
'_localPart' 143 $temp[
'allow'] = array_shift(
$options);
145 $temp[
'mx'] = array_shift(
$options);
149 $temp[
'hostname'] = array_shift(
$options);
177 if (array_key_exists(
'messages',
$options)) {
181 if (array_key_exists(
'hostname',
$options)) {
182 if (array_key_exists(
'allow',
$options)) {
187 }
elseif ($this->_options[
'hostname'] ==
null) {
191 if (array_key_exists(
'mx',
$options)) {
195 if (array_key_exists(
'deep',
$options)) {
199 if (array_key_exists(
'domain',
$options)) {
215 public function setMessage($messageString, $messageKey =
null)
217 if ($messageKey ===
null) {
218 $this->_options[
'hostname']->setMessage($messageString);
219 parent::setMessage($messageString);
223 if (!isset($this->_messageTemplates[$messageKey])) {
224 $this->_options[
'hostname']->setMessage($messageString, $messageKey);
227 $this->_messageTemplates[$messageKey] = $messageString;
238 return $this->_options[
'hostname'];
248 if (!$hostnameValidator) {
252 $this->_options[
'hostname'] = $hostnameValidator;
253 $this->_options[
'allow'] = $allow;
276 return $this->_options[
'mx'];
291 #require_once 'Zend/Validate/Exception.php'; 295 $this->_options[
'mx'] = (bool) $mx;
306 return $this->_options[
'deep'];
317 $this->_options[
'deep'] = (bool) $deep;
328 return $this->_options[
'domain'];
340 $this->_options[
'domain'] = (boolean) $domain;
350 private function _isReserved($host){
351 if (!preg_match(
'/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $host)) {
352 $host = gethostbyname($host);
355 $octet = explode(
'.',$host);
356 if ((
int)$octet[0] >= 224) {
358 }
else if (array_key_exists($octet[0], $this->_invalidIp)) {
359 foreach ((array)$this->_invalidIp[$octet[0]] as $subnetData) {
361 for (
$i = 1;
$i < 4;
$i++) {
362 if (strpos($subnetData, $octet[
$i]) !==
$i * 4) {
367 $host = explode(
"/", $subnetData);
369 $tmp = explode(
".", $host[0]);
370 for (
$i = 0;
$i < 4 ;
$i++) {
371 $binaryHost .= str_pad(decbin($tmp[
$i]), 8,
"0", STR_PAD_LEFT);
374 $segmentData = array(
375 'network' => (
int)$this->_toIp(str_pad(substr($binaryHost, 0, $host[1]), 32, 0)),
376 'broadcast' => (
int)$this->_toIp(str_pad(substr($binaryHost, 0, $host[1]), 32, 1))
379 for ($j =
$i; $j < 4; $j++) {
380 if ((
int)$octet[$j] < $segmentData[
'network'][$j] ||
381 (
int)$octet[$j] > $segmentData[
'broadcast'][$j]) {
399 private function _toIp($binary)
402 $tmp = explode(
".", chunk_split($binary, 8,
"."));
403 for (
$i = 0;
$i < 4 ;
$i++) {
404 $ip[
$i] = bindec($tmp[
$i]);
415 private function _validateLocalPart()
423 $atext =
'a-zA-Z0-9\x21\x23\x24\x25\x26\x27\x2a\x2b\x2d\x2f\x3d\x3f\x5e\x5f\x60\x7b\x7c\x7d\x7e';
424 if (preg_match(
'/^[' . $atext .
']+(\x2e+[' . $atext .
']+)*$/', $this->_localPart)) {
430 $qtext =
'\x20-\x21\x23-\x5b\x5d-\x7e';
431 $quotedPair =
'\x20-\x7e';
432 if (preg_match(
'/^"(['. $qtext .
']|\x5c[' . $quotedPair .
'])*"$/', $this->localPart)) {
435 $this->
_error(self::DOT_ATOM);
436 $this->
_error(self::QUOTED_STRING);
437 $this->
_error(self::INVALID_LOCAL_PART);
449 private function _validateMXRecords()
456 $hostname = idn_to_ascii($this->_hostname);
459 $result = getmxrr($hostname, $mxHosts);
461 $this->
_error(self::INVALID_MX_RECORD);
463 $validAddress =
false;
465 foreach ($mxHosts as $hostname) {
466 $res = $this->_isReserved($hostname);
472 && (checkdnsrr($hostname,
"A")
473 || checkdnsrr($hostname,
"AAAA")
474 || checkdnsrr($hostname,
"A6"))) {
475 $validAddress =
true;
480 if (!$validAddress) {
483 $this->
_error(self::INVALID_SEGMENT);
485 $this->
_error(self::INVALID_MX_RECORD);
498 private function _validateHostnamePart()
500 $hostname = $this->_options[
'hostname']->setTranslator($this->
getTranslator())
501 ->isValid($this->_hostname);
503 $this->
_error(self::INVALID_HOSTNAME);
510 foreach ($this->_options[
'hostname']->
getErrors() as $error) {
511 $this->_errors[] = $error;
513 }
else if ($this->_options[
'mx']) {
515 $hostname = $this->_validateMXRecords();
535 $this->
_error(self::INVALID);
544 if ((strpos(
$value,
'..') !==
false) or
545 (!preg_match(
'/^(.+)@([^@]+)$/',
$value, $matches))) {
546 $this->
_error(self::INVALID_FORMAT);
550 $this->_localPart = $matches[1];
551 $this->_hostname = $matches[2];
553 if ((strlen($this->_localPart) > 64) || (strlen($this->_hostname) > 255)) {
555 $this->
_error(self::LENGTH_EXCEEDED);
559 if ($this->_options[
'domain']) {
560 $hostname = $this->_validateHostnamePart();
563 $local = $this->_validateLocalPart();
566 if ($local && $length) {
567 if (($this->_options[
'domain'] && $hostname) || !$this->_options[
'domain']) {
elseif(isset( $params[ 'redirect_parent']))
__construct($options=array())
_error($messageKey, $value=null)
setHostnameValidator(Zend_Validate_Hostname $hostnameValidator=null, $allow=Zend_Validate_Hostname::ALLOW_DNS)
setDomainCheck($domain=true)
setMessages(array $messages)
setOptions(array $options=array())
setMessage($messageString, $messageKey=null)