From 413df054ad3235c59c24e897b616c569adc4f67b Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Sun, 12 Aug 2012 11:47:45 +0200 Subject: CS fixes (mostly tab -> spaces) --- program/include/rcube_utils.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'program/include/rcube_utils.php') diff --git a/program/include/rcube_utils.php b/program/include/rcube_utils.php index 9344a929b..d1a8315ec 100644 --- a/program/include/rcube_utils.php +++ b/program/include/rcube_utils.php @@ -84,9 +84,9 @@ class rcube_utils // from PEAR::Validate $regexp = '&^(?: - ("\s*(?:[^"\f\n\r\t\v\b\s]+\s*)+")| #1 quoted name - ([-\w!\#\$%\&\'*+~/^`|{}=]+(?:\.[-\w!\#\$%\&\'*+~/^`|{}=]+)*)) #2 OR dot-atom (RFC5322) - $&xi'; + ("\s*(?:[^"\f\n\r\t\v\b\s]+\s*)+")| #1 quoted name + ([-\w!\#\$%\&\'*+~/^`|{}=]+(?:\.[-\w!\#\$%\&\'*+~/^`|{}=]+)*)) #2 OR dot-atom (RFC5322) + $&xi'; if (!preg_match($regexp, $local_part)) { return false; @@ -617,8 +617,8 @@ class rcube_utils // %n - host $n = preg_replace('/:\d+$/', '', $_SERVER['SERVER_NAME']); // %t - host name without first part, e.g. %n=mail.domain.tld, %t=domain.tld - $t = preg_replace('/^[^\.]+\./', '', $n); - // %d - domain name without first part + $t = preg_replace('/^[^\.]+\./', '', $n); + // %d - domain name without first part $d = preg_replace('/^[^\.]+\./', '', $_SERVER['HTTP_HOST']); // %h - IMAP host $h = $_SESSION['storage_host'] ? $_SESSION['storage_host'] : $host; -- cgit v1.2.3 From c83b83eeae9806cb60ea3f41f2cff055b0c6ed7e Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Fri, 17 Aug 2012 15:37:04 +0200 Subject: Fix domain part check in email address validation function. Added test cases. --- program/include/rcube_utils.php | 5 +++ tests/Utils.php | 74 +++++++++++++++++++++++++++++++++++++++++ tests/phpunit.xml | 1 + 3 files changed, 80 insertions(+) create mode 100644 tests/Utils.php (limited to 'program/include/rcube_utils.php') diff --git a/program/include/rcube_utils.php b/program/include/rcube_utils.php index d1a8315ec..9f18b79c4 100644 --- a/program/include/rcube_utils.php +++ b/program/include/rcube_utils.php @@ -110,6 +110,11 @@ class rcube_utils } } + // last domain part + if (preg_match('/[^a-zA-Z]/', array_pop($domain_array))) { + return false; + } + $rcube = rcube::get_instance(); if (!$dns_check || !$rcube->config->get('email_dns_check')) { diff --git a/tests/Utils.php b/tests/Utils.php new file mode 100644 index 000000000..648b39989 --- /dev/null +++ b/tests/Utils.php @@ -0,0 +1,74 @@ +', 'Encoded html within email is invalid'), + array('email.domain.com', 'Missing @'), + array('email@domain@domain.com', 'Two @ sign'), + array('.email@domain.com', 'Leading dot in address is not allowed'), + array('email.@domain.com', 'Trailing dot in address is not allowed'), + array('email..email@domain.com', 'Multiple dots'), + array('あいうえお@domain.com', 'Unicode char as address'), + array('email@domain.com (Joe Smith)', 'Text followed email is not allowed'), + array('email@domain', 'Missing top level domain (.com/.net/.org/etc)'), + array('email@-domain.com', 'Leading dash in front of domain is invalid'), +// array('email@domain.web', '.web is not a valid top level domain'), + array('email@111.222.333.44444', 'Invalid IP format'), + array('email@domain..com', 'Multiple dot in the domain portion is invalid'), + ); + } + + /** + * @dataProvider data_valid_email + */ + function test_valid_email($email, $title) + { + $this->assertTrue(rcube_utils::check_email($email, false), $title); + } + + /** + * @dataProvider data_invalid_email + */ + function test_invalid_email($email, $title) + { + $this->assertFalse(rcube_utils::check_email($email, false), $title); + } + +} diff --git a/tests/phpunit.xml b/tests/phpunit.xml index 4a3b883cf..cfd066e29 100644 --- a/tests/phpunit.xml +++ b/tests/phpunit.xml @@ -7,6 +7,7 @@ MailDecode.php MailFunc.php ModCss.php + Utils.php VCards.php -- cgit v1.2.3 From da28121dcd160045c468b7028ee835b24f0cb965 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Fri, 24 Aug 2012 10:10:25 +0200 Subject: Improved email address validation with IPv6 support --- program/include/rcube_utils.php | 52 ++++++++++++++++++++++++++++++++++++++--- program/js/common.js | 4 +++- tests/Utils.php | 17 +++++++++++--- 3 files changed, 66 insertions(+), 7 deletions(-) (limited to 'program/include/rcube_utils.php') diff --git a/program/include/rcube_utils.php b/program/include/rcube_utils.php index 9f18b79c4..defb2aed1 100644 --- a/program/include/rcube_utils.php +++ b/program/include/rcube_utils.php @@ -92,9 +92,9 @@ class rcube_utils return false; } - // Check domain part - 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}\]*$/', $domain_part)) { - return true; // IP address + // Validate domain part + if (preg_match('/^\[((IPv6:[0-9a-f:.]+)|([0-9.]+))\]$/i', $domain_part, $matches)) { + return self::ip_check(preg_replace('/^IPv6:/i', '', $matches[1])); // valid IPv4 or IPv6 address } else { // If not an IP address @@ -146,6 +146,52 @@ class rcube_utils return false; } + + /** + * Validates IPv4 or IPv6 address + * + * @param string $ip IP address in v4 or v6 format + * + * @return bool True if the address is valid + */ + public static function ip_check($ip) + { + // IPv6, but there's no build-in IPv6 support + if (strpos($ip, ':') !== false && !defined('AF_INET6')) { + $parts = explode(':', $domain_part); + $count = count($parts); + + if ($count > 8 || $count < 2) { + return false; + } + + foreach ($parts as $idx => $part) { + $length = strlen($part); + if (!$length) { + // there can be only one :: + if ($found_empty) { + return false; + } + $found_empty = true; + } + // last part can be an IPv4 address + else if ($idx == $count - 1) { + if (!preg_match('/^[0-9a-f]{1,4}$/i', $part)) { + return @inet_pton($part) !== false; + } + } + else if (!preg_match('/^[0-9a-f]{1,4}$/i', $part)) { + return false; + } + } + + return true; + } + + return @inet_pton($ip) !== false; + } + + /** * Check whether the HTTP referer matches the current request * diff --git a/program/js/common.js b/program/js/common.js index 2d8d9e176..f9e945c05 100644 --- a/program/js/common.js +++ b/program/js/common.js @@ -494,7 +494,9 @@ function rcube_check_email(input, inline) atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+', quoted_pair = '\\x5c[\\x00-\\x7f]', quoted_string = '\\x22('+qtext+'|'+quoted_pair+')*\\x22', - ip_addr = '\\[*(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}\\]*', + ipv4 = '\\[(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}\\]', + ipv6 = '\\[IPv6:[0-9a-f:.]+\\]', + ip_addr = '(' + ipv4 + ')|(' + ipv6 + ')', // Use simplified domain matching, because we need to allow Unicode characters here // So, e-mail address should be validated also on server side after idn_to_ascii() use //domain_literal = '\\x5b('+dtext+'|'+quoted_pair+')*\\x5d', diff --git a/tests/Utils.php b/tests/Utils.php index 648b39989..ad0aa1dde 100644 --- a/tests/Utils.php +++ b/tests/Utils.php @@ -18,8 +18,10 @@ class Utils extends PHPUnit_Framework_TestCase array('firstname.lastname@domain.com', 'Email contains dot in the address field'), array('email@subdomain.domain.com', 'Email contains dot with subdomain'), array('firstname+lastname@domain.com', 'Plus sign is considered valid character'), - array('email@123.123.123.123', 'Domain is valid IP address'), - array('email@[123.123.123.123]', 'Square bracket around IP address is considered valid'), + array('email@[123.123.123.123]', 'Square bracket around IP address'), + array('email@[IPv6:::1]', 'Square bracket around IPv6 address (1)'), + array('email@[IPv6:::1.2.3.4]', 'Square bracket around IPv6 address (2)'), + array('email@[IPv6:2001:2d12:c4fe:5afe::1]', 'Square bracket around IPv6 address (3)'), array('"email"@domain.com', 'Quotes around email is considered valid'), array('1234567890@domain.com', 'Digits in address are valid'), array('email@domain-one.com', 'Dash in domain name is valid'), @@ -50,7 +52,16 @@ class Utils extends PHPUnit_Framework_TestCase array('email@domain', 'Missing top level domain (.com/.net/.org/etc)'), array('email@-domain.com', 'Leading dash in front of domain is invalid'), // array('email@domain.web', '.web is not a valid top level domain'), - array('email@111.222.333.44444', 'Invalid IP format'), + array('email@123.123.123.123', 'IP address without brackets'), + array('email@2001:2d12:c4fe:5afe::1', 'IPv6 address without brackets'), + array('email@IPv6:2001:2d12:c4fe:5afe::1', 'IPv6 address without brackets (2)'), + array('email@[111.222.333.44444]', 'Invalid IP format'), + array('email@[111.222.255.257]', 'Invalid IP format (2)'), + array('email@[.222.255.257]', 'Invalid IP format (3)'), + array('email@[::1]', 'Invalid IPv6 format (1)'), + array('email@[IPv6:2001:23x2:1]', 'Invalid IPv6 format (2)'), + array('email@[IPv6:1111:2222:33333::4444:5555]', 'Invalid IPv6 format (3)'), + array('email@[IPv6:1111::3333::4444:5555]', 'Invalid IPv6 format (4)'), array('email@domain..com', 'Multiple dot in the domain portion is invalid'), ); } -- cgit v1.2.3 From a65ce5d3b07deb578cc4c4aba5695bcea8c07a87 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Mon, 27 Aug 2012 12:23:30 +0200 Subject: Rename ip_check to check_ip, add IP checking tests --- program/include/rcube_utils.php | 4 ++-- tests/Framework/Utils.php | 47 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) (limited to 'program/include/rcube_utils.php') diff --git a/program/include/rcube_utils.php b/program/include/rcube_utils.php index defb2aed1..aa748dc7f 100644 --- a/program/include/rcube_utils.php +++ b/program/include/rcube_utils.php @@ -94,7 +94,7 @@ class rcube_utils // Validate domain part if (preg_match('/^\[((IPv6:[0-9a-f:.]+)|([0-9.]+))\]$/i', $domain_part, $matches)) { - return self::ip_check(preg_replace('/^IPv6:/i', '', $matches[1])); // valid IPv4 or IPv6 address + return self::check_ip(preg_replace('/^IPv6:/i', '', $matches[1])); // valid IPv4 or IPv6 address } else { // If not an IP address @@ -154,7 +154,7 @@ class rcube_utils * * @return bool True if the address is valid */ - public static function ip_check($ip) + public static function check_ip($ip) { // IPv6, but there's no build-in IPv6 support if (strpos($ip, ':') !== false && !defined('AF_INET6')) { diff --git a/tests/Framework/Utils.php b/tests/Framework/Utils.php index b6cc5d577..503b69a4a 100644 --- a/tests/Framework/Utils.php +++ b/tests/Framework/Utils.php @@ -82,6 +82,53 @@ class Framework_Utils extends PHPUnit_Framework_TestCase $this->assertFalse(rcube_utils::check_email($email, false), $title); } + /** + * Valid IP addresses for test_valid_ip() + */ + function data_valid_ip() + { + return array( + array('0.0.0.0'), + array('123.123.123.123'), + array('::'), + array('::1'), + array('::1.2.3.4'), + array('2001:2d12:c4fe:5afe::1'), + ); + } + + /** + * Valid IP addresses for test_invalid_ip() + */ + function data_invalid_ip() + { + return array( + array(''), + array(0), + array('123.123.123.1234'), + array('1.1.1.1.1'), + array('::1.2.3.260'), + array('::1.0'), + array('2001::c4fe:5afe::1'), + ); + } + + /** + * @dataProvider data_valid_ip + */ + function test_valid_ip($ip) + { + $this->assertTrue(rcube_utils::check_ip($ip)); + } + + /** + * @dataProvider data_invalid_ip + */ + function test_invalid_ip($ip) + { + $this->assertFalse(rcube_utils::check_ip($ip)); + } + /** * rcube_utils::mod_css_styles() */ -- cgit v1.2.3 From be71abeff913611086e4f36f6888bf57666042c5 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Mon, 27 Aug 2012 12:25:55 +0200 Subject: Fix deprecated function usage --- program/include/rcube_utils.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'program/include/rcube_utils.php') diff --git a/program/include/rcube_utils.php b/program/include/rcube_utils.php index aa748dc7f..23bf556e4 100644 --- a/program/include/rcube_utils.php +++ b/program/include/rcube_utils.php @@ -200,8 +200,8 @@ class rcube_utils public static function check_referer() { $uri = parse_url($_SERVER['REQUEST_URI']); - $referer = parse_url(rcube_request_header('Referer')); - return $referer['host'] == rcube_request_header('Host') && $referer['path'] == $uri['path']; + $referer = parse_url(self::request_header('Referer')); + return $referer['host'] == self::request_header('Host') && $referer['path'] == $uri['path']; } -- cgit v1.2.3