note 119277 added to function.filter-var
| From: | alice at deviant dot email | Date: | Mon, 02 May 2016 12:19:42 +0000 |
| Subject: | note 119277 added to function.filter-var | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-205413@lists.php.net to get a copy of this message | ||
Many people, myself included, have found that the FILTER_VALIDATE_EMAIL does not actually properly
work.
Below is a wrapper that I believe validates every legal routable address.
<?php
/*******************************************
*
* These are the function
*
* check_username is called by check_email
* - it compensates for bugs in the php
* filter_var function.
* - returns boolean
*
* check_email is the function to use.
* First argument is string, address to
* check
* Second argument is optional boolean,
* whether or not to use DNS to validate
* the domain name. Defaults to true
* Returns boolean
*
*/
function check_username($uname) {
//Only UTF-8 addresses are legal
if (iconv('UTF-8', 'UTF-8', $input) != $input) {
return FALSE;
}
//replace all characters above U+007F with letter U for simplicity of checking
$uname = preg_replace('/[\x{007F}-\x{FFFF}]/u', 'U', $uname);
//remove comments - only legal in format (comment) at beginning or end of username
$s[] = '/^\([^\)]*\)/'; $s[] = '/\([^\)]*\)$/';
$uname = preg_replace($s, '', $uname);
//make sure we have something left
if(strlen(trim($uname)) == 0) {
return FALSE;
}
// check for legal dot usage
if(substr_count($uname, '..') > 0) {
return FALSE;
}
// convert \\ and \" to an A for simplicity
$s[] = '/[\\\][\\\]/';
$s[] = '/\\\"/';
$uname = preg_replace($s, 'A', $uname);
// check for illegal use of quotes
if(preg_match('/[^.]+"[^.]+/', $uname)) {
return FALSE;
}
// compensate for characters legal when in quotes
$uname = preg_replace_callback('/"(.*)"/', function ($m) {
$s[]="/[ \(\),\:;<>@\[\] ]/";
return preg_replace($s,'Q',$m[1]);
}, $uname);
// check what we have left with filter_var
return filter_var($uname . '@example.org', FILTER_VALIDATE_EMAIL);
}
function check_email($email, $dns_check=true) {
$array = explode('@', $email);
if(count($array) < 2) {
return FALSE;
}
$domain = end($array);
array_pop($array);
if(function_exists('idn_to_ascii')) {
//php filter no workie with unicode characters
$domain = idn_to_ascii($domain);
}
$ipcheck = preg_replace(array('/^\[ipv6\:/i', '/^\[/', '/\]$/'),
'', $domain);
if(filter_var($ipcheck, FILTER_VALIDATE_IP)) {
// it's an IP address
if(! filter_var($ipcheck, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE |
FILTER_FLAG_NO_RES_RANGE)) {
return FALSE;
}
} else {
// it's a domain name
// php bug - FILTER_VALIDATE_EMAIL doesn't like naked TLD
if(! filter_var('user@a.' . $domain, FILTER_VALIDATE_EMAIL)) {
return FALSE;
}
if($dns_check) {
if(! dns_get_record($domain)) {
return FALSE;
}
}
}
//now check legal username
return check_username(implode('@', $array));
}
?>
It evaluates the address in two parts, first evaluating the host and if that legal it then evaluates
the user name.
If there is a DNS problem *and* the default $dns_check value of true is used, valid will fail. If it
is an international domain name, you have to have the php-intl package installed.
Enjoy.
----
Server IP: 72.52.91.14
Probable Submitter: 71.9.134.226
----
Manual Page -- http://php.net/manual/en/function.filter-var.php
Edit -- https://master.php.net/note/edit/119277
Del: integrated -- https://master.php.net/note/delete/119277/integrated
Del: useless -- https://master.php.net/note/delete/119277/useless
Del: bad code -- https://master.php.net/note/delete/119277/bad+code
Del: spam -- https://master.php.net/note/delete/119277/spam
Del: non-english -- https://master.php.net/note/delete/119277/non-english
Del: in docs -- https://master.php.net/note/delete/119277/in+docs
Del: other reasons-- https://master.php.net/note/delete/119277
Reject -- https://master.php.net/note/reject/119277
Search -- https://master.php.net/manage/user-notes.php