diff options
author | Andreas Gohr <andi@splitbrain.org> | 2008-10-11 19:32:45 +0200 |
---|---|---|
committer | Andreas Gohr <andi@splitbrain.org> | 2008-10-11 19:32:45 +0200 |
commit | e8f8d645be4a431ee7114859b9aedae042f52ead (patch) | |
tree | 9c503985f76b2d75a779854502e1cd6387ee0ec8 | |
parent | abe88ecbb1016580584d00091f6de364d509933f (diff) | |
download | rpg-e8f8d645be4a431ee7114859b9aedae042f52ead.tar.gz rpg-e8f8d645be4a431ee7114859b9aedae042f52ead.tar.bz2 |
use EmailAddressValidator class for email validation FS#1503
darcs-hash:20081011173245-7ad00-578e03ca701fc4443ba91329be6ac1ca9344c7a7.gz
-rw-r--r-- | _test/cases/inc/mail_isvalid.test.php | 2 | ||||
-rw-r--r-- | inc/EmailAddressValidator.php | 146 | ||||
-rw-r--r-- | inc/mail.php | 19 |
3 files changed, 151 insertions, 16 deletions
diff --git a/_test/cases/inc/mail_isvalid.test.php b/_test/cases/inc/mail_isvalid.test.php index 120764e08..374204679 100644 --- a/_test/cases/inc/mail_isvalid.test.php +++ b/_test/cases/inc/mail_isvalid.test.php @@ -15,7 +15,7 @@ class mail_isvalid extends UnitTestCase { $tests[] = array('username+tag@domain.com',true); // FS#1447 $tests[] = array("rfc2822+allthesechars_#*!'`/-={}are.legal@somewhere.com.au",true); $tests[] = array('_foo@test.com',true); // FS#1049 - $tests[] = array('bugs@php.net1',false); + $tests[] = array('bugs@php.net1',true); // new ICAN rulez seem to allow this $tests[] = array('.bugs@php.net1',false); $tests[] = array('bu..gs@php.net',false); $tests[] = array('bugs@php..net',false); diff --git a/inc/EmailAddressValidator.php b/inc/EmailAddressValidator.php new file mode 100644 index 000000000..2ce2093e2 --- /dev/null +++ b/inc/EmailAddressValidator.php @@ -0,0 +1,146 @@ +<?php +/** + * EmailAddressValidator Class + * + * @author Dave Child <dave@addedbytes.com> + * @link http://code.google.com/p/php-email-address-validation/ + * @license http://www.opensource.org/licenses/bsd-license.php + */ +class EmailAddressValidator { + + /** + * Check email address validity + * @param strEmailAddress Email address to be checked + * @return True if email is valid, false if not + */ + function check_email_address($strEmailAddress) { + + // Control characters are not allowed + if (preg_match('/[\x00-\x1F\x7F-\xFF]/', $strEmailAddress)) { + return false; + } + + // Split it into sections using last instance of "@" + $intAtSymbol = strrpos($strEmailAddress, '@'); + if ($intAtSymbol === false) { + // No "@" symbol in email. + return false; + } + $arrEmailAddress[0] = substr($strEmailAddress, 0, $intAtSymbol); + $arrEmailAddress[1] = substr($strEmailAddress, $intAtSymbol + 1); + + // Count the "@" symbols. Only one is allowed, except where + // contained in quote marks in the local part. Quickest way to + // check this is to remove anything in quotes. + $arrTempAddress[0] = preg_replace('/"[^"]+"/' + ,'' + ,$arrEmailAddress[0]); + $arrTempAddress[1] = $arrEmailAddress[1]; + $strTempAddress = $arrTempAddress[0] . $arrTempAddress[1]; + // Then check - should be no "@" symbols. + if (strrpos($strTempAddress, '@') !== false) { + // "@" symbol found + return false; + } + + // Check local portion + if (!$this->check_local_portion($arrEmailAddress[0])) { + return false; + } + + // Check domain portion + if (!$this->check_domain_portion($arrEmailAddress[1])) { + return false; + } + + // If we're still here, all checks above passed. Email is valid. + return true; + + } + + /** + * Checks email section before "@" symbol for validity + * @param strLocalPortion Text to be checked + * @return True if local portion is valid, false if not + */ + function check_local_portion($strLocalPortion) { + // Local portion can only be from 1 to 64 characters, inclusive. + // Please note that servers are encouraged to accept longer local + // parts than 64 characters. + if (!$this->check_text_length($strLocalPortion, 1, 64)) { + return false; + } + // Local portion must be: + // 1) a dot-atom (strings separated by periods) + // 2) a quoted string + // 3) an obsolete format string (combination of the above) + $arrLocalPortion = explode('.', $strLocalPortion); + for ($i = 0, $max = sizeof($arrLocalPortion); $i < $max; $i++) { + if (!preg_match('.^(' + . '([A-Za-z0-9!#$%&\'*+/=?^_`{|}~-]' + . '[A-Za-z0-9!#$%&\'*+/=?^_`{|}~-]{0,63})' + .'|' + . '("[^\\\"]{0,62}")' + .')$.' + ,$arrLocalPortion[$i])) { + return false; + } + } + return true; + } + + /** + * Checks email section after "@" symbol for validity + * @param strDomainPortion Text to be checked + * @return True if domain portion is valid, false if not + */ + function check_domain_portion($strDomainPortion) { + // Total domain can only be from 1 to 255 characters, inclusive + if (!$this->check_text_length($strDomainPortion, 1, 255)) { + return false; + } + // Check if domain is IP, possibly enclosed in square brackets. + if (preg_match('/^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])' + .'(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}$/' + ,$strDomainPortion) || + preg_match('/^\[(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])' + .'(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\]$/' + ,$strDomainPortion)) { + return true; + } else { + $arrDomainPortion = explode('.', $strDomainPortion); + if (sizeof($arrDomainPortion) < 2) { + return false; // Not enough parts to domain + } + for ($i = 0, $max = sizeof($arrDomainPortion); $i < $max; $i++) { + // Each portion must be between 1 and 63 characters, inclusive + if (!$this->check_text_length($arrDomainPortion[$i], 1, 63)) { + return false; + } + if (!preg_match('/^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|' + .'([A-Za-z0-9]+))$/', $arrDomainPortion[$i])) { + return false; + } + } + } + return true; + } + + /** + * Check given text length is between defined bounds + * @param strText Text to be checked + * @param intMinimum Minimum acceptable length + * @param intMaximum Maximum acceptable length + * @return True if string is within bounds (inclusive), false if not + */ + function check_text_length($strText, $intMinimum, $intMaximum) { + // Minimum and maximum are both inclusive + $intTextLength = strlen($strText); + if (($intTextLength < $intMinimum) || ($intTextLength > $intMaximum)) { + return false; + } else { + return true; + } + } +} + diff --git a/inc/mail.php b/inc/mail.php index 4b27963ee..a7a878c2d 100644 --- a/inc/mail.php +++ b/inc/mail.php @@ -8,6 +8,7 @@ if(!defined('DOKU_INC')) define('DOKU_INC',fullpath(dirname(__FILE__).'/../').'/'); require_once(DOKU_INC.'inc/utf8.php'); + require_once(DOKU_INC.'inc/EmailAddressValidator.php'); // end of line for mail lines - RFC822 says CRLF but postfix (and other MTAs?) // think different @@ -174,26 +175,14 @@ function mail_encode_address($string,$header='',$names=true){ } /** - * Uses a regular expresion to check if a given mail address is valid - * - * May not be completly RFC conform! - * @link http://www.faqs.org/rfcs/rfc2822.html (paras 3.4.1 & 3.2.4) - * - * @author Chris Smith <chris@jalakai.co.uk> + * Check if a given mail address is valid * * @param string $email the address to check * @return bool true if address is valid */ - -// patterns for use in email detection and validation -// NOTE: there is an unquoted '/' in RFC2822_ATEXT, it must remain unquoted to be used in the parser -// the pattern uses non-capturing groups as captured groups aren't allowed in the parser -// select pattern delimiters with care! -if (!defined('RFC2822_ATEXT')) define('RFC2822_ATEXT',"0-9a-zA-Z!#$%&'*+/=?^_`{|}~-"); -if (!defined('PREG_PATTERN_VALID_EMAIL')) define('PREG_PATTERN_VALID_EMAIL', '['.RFC2822_ATEXT.']+(?:\.['.RFC2822_ATEXT.']+)*@(?i:[0-9a-z][0-9a-z-]*\.)+(?i:[a-z]{2,4}|museum|travel)'); - function mail_isvalid($email){ - return preg_match('<^'.PREG_PATTERN_VALID_EMAIL.'$>i', $email); + $validator = new EmailAddressValidator; + return $validator->check_email_address($email); } /** |