Bladeren bron

[HttpFoundation] IPv6 support for RequestMatcher

Igor Wiedler 14 jaren geleden
bovenliggende
commit
9ae5023a70

+ 33 - 0
src/Symfony/Component/HttpFoundation/RequestMatcher.php

@@ -121,6 +121,16 @@ class RequestMatcher implements RequestMatcherInterface
     }
 
     protected function checkIp($ip)
+    {
+        // IPv6 address
+        if (false !== strpos($ip, ':')) {
+            return $this->checkIp6($ip);
+        } else {
+            return $this->checkIp4($ip);
+        }
+    }
+
+    protected function checkIp4($ip)
     {
         if (false !== strpos($this->ip, '/')) {
             list($address, $netmask) = explode('/', $this->ip);
@@ -135,4 +145,27 @@ class RequestMatcher implements RequestMatcherInterface
 
         return 0 === substr_compare(sprintf('%032b', ip2long($ip)), sprintf('%032b', ip2long($address)), 0, $netmask);
     }
+
+    /**
+     * @author David Soria Parra <dsp at php dot net>
+     * @see https://github.com/dsp/v6tools
+     */
+    protected function checkIp6($ip)
+    {
+        list($address, $netmask) = explode('/', $this->ip);
+
+        $bytes_addr = unpack("n*", inet_pton($address));
+        $bytes_test = unpack("n*", inet_pton($ip));
+
+        for ($i = 1; $i <= ceil($netmask / 16); $i++) {
+            $left = $netmask - 16 * ($i-1);
+            $left = ($left <= 16) ?: 16;
+            $mask = ~(0xffff >> $left) & 0xffff;
+            if (($bytes_addr[$i] & $mask) != ($bytes_test[$i] & $mask)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
 }

+ 2 - 0
tests/Symfony/Tests/Component/HttpFoundation/RequestMatcherTest.php

@@ -35,6 +35,8 @@ class RequestMatcherTest extends \PHPUnit_Framework_TestCase
             array(true, '192.168.1.1', '192.168.1.1/1'),
             array(true, '192.168.1.1', '192.168.1.0/24'),
             array(false, '192.168.1.1', '1.2.3.4/1'),
+            array(true, '2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'),
+            array(false, '2a00:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'),
         );
     }