Procházet zdrojové kódy

Fix for #ZF-8253 . Zend_Validate_Ip now validates IPv6 addresses even more correctly.

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@18906 44c647ce-9c0f-0410-b52a-842ac1e357ba
freak před 16 roky
rodič
revize
922462468d
2 změnil soubory, kde provedl 98 přidání a 5 odebrání
  1. 56 5
      library/Zend/Validate/Ip.php
  2. 42 0
      tests/Zend/Validate/IpTest.php

+ 56 - 5
library/Zend/Validate/Ip.php

@@ -60,17 +60,68 @@ class Zend_Validate_Ip extends Zend_Validate_Abstract
 
         $this->_setValue($value);
 
-        if ((ip2long($value) === false) || (long2ip(ip2long($value)) !== $value)) {
-            if (!function_exists('inet_pton')) {
+        if (!$this->_validateIPv4($value) && !$this->_validateIPv6($value)) {
                 $this->_error(self::NOT_IP_ADDRESS);
                 return false;
-            } else if ((@inet_pton($value) === false) ||(inet_ntop(@inet_pton($value)) !== $value)) {
-                $this->_error(self::NOT_IP_ADDRESS);
+        }
+
+        return true;
+    }
+    
+    /**
+     * Validates an IPv4 address
+     * 
+     * @param string $value
+     */
+    protected function _validateIPv4($value) {
+        $ip2long = ip2long($value);
+        if($ip2long === false) {
+            return false;
+        }
+        
+        return $value == long2ip($ip2long); 
+    }
+    
+    /**
+     * Validates an IPv6 address
+     * 
+     * @param string $value Value to check against
+     * @return boolean True when $value is a valid ipv6 address
+     *                 False otherwise
+     */
+    protected function _validateIPv6($value) {
+        if (strlen($value) < 3) {
+            return $value == '::';
+        }
+
+        if (strpos($value, '.'))
+        {
+            $lastcolon = strrpos($value, ':');
+            if (!($lastcolon && $this->_validateIPv4(substr($value, $lastcolon + 1)))) {
                 return false;
             }
+
+            $value = substr($value, 0, $lastcolon) . ':0:0';
         }
 
-        return true;
+        if (strpos($value, '::') === false)
+        {
+            return preg_match('/\A(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}\Z/i', $value);
+        }
+
+        $colonCount = substr_count($value, ':');
+        if ($colonCount < 8)
+        {
+            return preg_match('/\A(?::|(?:[a-f0-9]{1,4}:)+):(?:(?:[a-f0-9]{1,4}:)*[a-f0-9]{1,4})?\Z/i', $value);
+        }
+
+        // special case with ending or starting double colon 
+        if ($colonCount == 8)
+        {
+            return preg_match('/\A(?:::)?(?:[a-f0-9]{1,4}:){6}[a-f0-9]{1,4}(?:::)?\Z/i', $value);
+        }
+
+        return false; 
     }
 
 }

+ 42 - 0
tests/Zend/Validate/IpTest.php

@@ -108,6 +108,48 @@ class Zend_Validate_IpTest extends PHPUnit_Framework_TestCase
 
         $this->assertTrue($this->_validator->isValid('::127.0.0.1'));
     }
+    
+    /**
+     * @see ZF-8253
+     */
+    public function testMoreIPv6Addresses()
+    {
+        $ips = array(
+                     '2001:0db8:0000:0000:0000:0000:1428:57ab',
+                     '2001:0DB8:0000:0000:0000:0000:1428:57AB',
+                     'a:b:c::1.2.3.4',
+                     'a:b:c:d::1.2.3.4',
+                     'a:b:c:d:e:f:1.2.3.4',
+                     'a::c:d:e:f:0:1',
+                     'a::0:1',
+                     '::e:f',
+                     'a:b:c:d:e:f::0');
+        foreach($ips as $ip) {
+            $this->assertTrue($this->_validator->isValid($ip));
+        }
+    }
+    
+    /**
+     * @see ZF-8253
+     * @see http://bugs.php.net/bug.php?id=50117
+     */
+    public function testMoreIPv6AddressesPHPdidWrong()
+    {
+        $validIps = array('a:b:c:d:e::1.2.3.4',
+                          '::0:a:b:c:d:e:f',
+                          '0:a:b:c:d:e:f::');
+        $invalidIps = array('::01.02.03.04',
+                            '0:0:0:255.255.255.255');
+        
+        foreach($validIps as $ip) {
+            $this->assertTrue($this->_validator->isValid($ip));
+        }
+        
+        foreach($invalidIps as $ip) {
+            $this->assertFalse($this->_validator->isValid($ip));
+        }
+    }
+    
 
     /**
      * @ZF-4352