Permalink
Browse files

Implenting IPv6 validation using filter_var(), with a regex-based fal…

…lback if the aforementioned function does not exist (PHP < 5.2). Fixes #38.
  • Loading branch information...
1 parent 850b959 commit 8eb9f9e8fd43551f65da53ae9ffaf737f4b2cb73 @jperras jperras committed Dec 23, 2009
Showing with 82 additions and 7 deletions.
  1. +42 −7 cake/libs/validation.php
  2. +40 −0 cake/tests/cases/libs/validation.test.php
View
@@ -53,7 +53,6 @@ class Validation extends Object {
* @access private
*/
var $__pattern = array(
- 'ip' => '(?:(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])',
'hostname' => '(?:[a-z0-9][-a-z0-9]*\.)*(?:[a-z0-9][-a-z0-9]{0,62})\.(?:(?:[a-z]{2}\.)?[a-z]{2,4}|museum|travel)'
);
@@ -548,10 +547,15 @@ function extension($check, $extensions = array('gif', 'jpeg', 'png', 'jpg')) {
* @return boolean Success
* @access public
*/
- function ip($check) {
+ function ip($check, $type = 'IPv4') {
+ if (function_exists('filter_var')) {
+ return filter_var($check, FILTER_VALIDATE_IP);
+ }
+
$_this =& Validation::getInstance();
$_this->check = $check;
- $_this->regex = '/^' . $_this->__pattern['ip'] . '$/';
+ $_this->__populateIp();
+ $_this->regex = '/^' . $_this->__pattern[$type] . '$/';
return $_this->_check();
}
@@ -604,8 +608,8 @@ function money($check, $symbolPosition = 'left') {
/**
* Validate a multiple select.
*
- * Valid Options
- *
+ * Valid Options
+ *
* - in => provide a list of choices that selections must be made from
* - max => maximun number of non-zero choices that can be made
* - min => minimum number of non-zero choices that can be made
@@ -794,7 +798,7 @@ function ssn($check, $regex = null, $country = null) {
* The regex checks for the following component parts:
*
* - a valid, optional, scheme
- * - a valid ip address OR
+ * - a valid ip address OR
* a valid domain name as defined by section 2.3.1 of http://www.ietf.org/rfc/rfc1035.txt
* with an optional port number
* - an optional valid path
@@ -808,10 +812,11 @@ function ssn($check, $regex = null, $country = null) {
*/
function url($check, $strict = false) {
$_this =& Validation::getInstance();
+ $_this->__populateIp();
$_this->check = $check;
$validChars = '([' . preg_quote('!"$&\'()*+,-.@_:;=~') . '\/0-9a-z]|(%[0-9a-f]{2}))';
$_this->regex = '/^(?:(?:https?|ftps?|file|news|gopher):\/\/)' . (!empty($strict) ? '' : '?') .
- '(?:' . $_this->__pattern['ip'] . '|' . $_this->__pattern['hostname'] . ')(?::[1-9][0-9]{0,3})?' .
+ '(?:' . $_this->__pattern['IPv4'] . '|' . $_this->__pattern['hostname'] . ')(?::[1-9][0-9]{0,3})?' .
'(?:\/?|\/' . $validChars . '*)?' .
'(?:\?' . $validChars . '*)?' .
'(?:#' . $validChars . '*)?$/i';
@@ -945,6 +950,36 @@ function _luhn() {
return ($sum % 10 == 0);
}
+/*
+ * Lazily popualate the IP address patterns used for validations
+ *
+ * @return void
+ */
+ function __populateIp() {
+ if (!isset($this->__pattern['IPv6'])) {
+ $pattern = '((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}';
+ $pattern .= '(:|((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})';
+ $pattern .= '|(:[0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4}:){5}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})';
+ $pattern .= '(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)';
+ $pattern .= '{4}(:[0-9A-Fa-f]{1,4}){0,1}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2}))';
+ $pattern .= '{3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}';
+ $pattern .= '((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|';
+ $pattern .= '((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}';
+ $pattern .= '((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2}))';
+ $pattern .= '{3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)(:[0-9A-Fa-f]{1,4})';
+ $pattern .= '{0,4}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)';
+ $pattern .= '|((:[0-9A-Fa-f]{1,4}){1,2})))|(:(:[0-9A-Fa-f]{1,4}){0,5}((:((25[0-5]|2[0-4]';
+ $pattern .= '\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4})';
+ $pattern .= '{1,2})))|(((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})))(%.+)?';
+
+ $this->__pattern['IPv6'] = $pattern;
+ }
+ if (!isset($this->__pattern['IPv4'])) {
+ $pattern = '(?:(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])';
+ $this->__pattern['IPv4'] = $pattern;
+ }
+ }
+
/**
* Reset internal variables for another validation run.
*
@@ -1735,6 +1735,46 @@ function testIp() {
}
/**
+ * testIp v6
+ *
+ * @access public
+ * @return void
+ */
+ function testIpv6() {
+ $this->assertTrue(Validation::ip('2001:0db8:85a3:0000:0000:8a2e:0370:7334', 'IPv6'));
+ $this->assertTrue(Validation::ip('2001:db8:85a3:0:0:8a2e:370:7334', 'IPv6'));
+ $this->assertTrue(Validation::ip('2001:db8:85a3::8a2e:370:7334', 'IPv6'));
+ $this->assertTrue(Validation::ip('2001:0db8:0000:0000:0000:0000:1428:57ab', 'IPv6'));
+ $this->assertTrue(Validation::ip('2001:0db8:0000:0000:0000::1428:57ab', 'IPv6'));
+ $this->assertTrue(Validation::ip('2001:0db8:0:0:0:0:1428:57ab', 'IPv6'));
+ $this->assertTrue(Validation::ip('2001:0db8:0:0::1428:57ab', 'IPv6'));
+ $this->assertTrue(Validation::ip('2001:0db8::1428:57ab', 'IPv6'));
+ $this->assertTrue(Validation::ip('2001:db8::1428:57ab', 'IPv6'));
+ $this->assertTrue(Validation::ip('0000:0000:0000:0000:0000:0000:0000:0001', 'IPv6'));
+ $this->assertTrue(Validation::ip('::1', 'IPv6'));
+ $this->assertTrue(Validation::ip('::ffff:12.34.56.78', 'IPv6'));
+ $this->assertTrue(Validation::ip('::ffff:0c22:384e', 'IPv6'));
+ $this->assertTrue(Validation::ip('2001:0db8:1234:0000:0000:0000:0000:0000', 'IPv6'));
+ $this->assertTrue(Validation::ip('2001:0db8:1234:ffff:ffff:ffff:ffff:ffff', 'IPv6'));
+ $this->assertTrue(Validation::ip('2001:db8:a::123', 'IPv6'));
+ $this->assertTrue(Validation::ip('fe80::', 'IPv6'));
+ $this->assertTrue(Validation::ip('::ffff:192.0.2.128', 'IPv6'));
+ $this->assertTrue(Validation::ip('::ffff:c000:280', 'IPv6'));
+
+ $this->assertFalse(Validation::ip('123', 'IPv6'));
+ $this->assertFalse(Validation::ip('ldkfj', 'IPv6'));
+ $this->assertFalse(Validation::ip('2001::FFD3::57ab', 'IPv6'));
+ $this->assertFalse(Validation::ip('2001:db8:85a3::8a2e:37023:7334', 'IPv6'));
+ $this->assertFalse(Validation::ip('2001:db8:85a3::8a2e:370k:7334', 'IPv6'));
+ $this->assertFalse(Validation::ip('1:2:3:4:5:6:7:8:9', 'IPv6'));
+ $this->assertFalse(Validation::ip('1::2::3', 'IPv6'));
+ $this->assertFalse(Validation::ip('1:::3:4:5', 'IPv6'));
+ $this->assertFalse(Validation::ip('1:2:3::4:5:6:7:8:9', 'IPv6'));
+ $this->assertFalse(Validation::ip('::ffff:2.3.4', 'IPv6'));
+ $this->assertFalse(Validation::ip('::ffff:257.1.2.3', 'IPv6'));
+ }
+
+/**
* testMaxLength method
*
* @access public

0 comments on commit 8eb9f9e

Please sign in to comment.