28093be43403fb6c566088981fddecfc3556d40d
[yaffs-website] / vendor / symfony / http-foundation / IpUtils.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\HttpFoundation;
13
14 /**
15  * Http utility functions.
16  *
17  * @author Fabien Potencier <fabien@symfony.com>
18  */
19 class IpUtils
20 {
21     /**
22      * This class should not be instantiated.
23      */
24     private function __construct()
25     {
26     }
27
28     /**
29      * Checks if an IPv4 or IPv6 address is contained in the list of given IPs or subnets.
30      *
31      * @param string       $requestIp IP to check
32      * @param string|array $ips       List of IPs or subnets (can be a string if only a single one)
33      *
34      * @return bool Whether the IP is valid
35      */
36     public static function checkIp($requestIp, $ips)
37     {
38         if (!is_array($ips)) {
39             $ips = array($ips);
40         }
41
42         $method = substr_count($requestIp, ':') > 1 ? 'checkIp6' : 'checkIp4';
43
44         foreach ($ips as $ip) {
45             if (self::$method($requestIp, $ip)) {
46                 return true;
47             }
48         }
49
50         return false;
51     }
52
53     /**
54      * Compares two IPv4 addresses.
55      * In case a subnet is given, it checks if it contains the request IP.
56      *
57      * @param string $requestIp IPv4 address to check
58      * @param string $ip        IPv4 address or subnet in CIDR notation
59      *
60      * @return bool Whether the request IP matches the IP, or whether the request IP is within the CIDR subnet
61      */
62     public static function checkIp4($requestIp, $ip)
63     {
64         if (!filter_var($requestIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
65             return false;
66         }
67
68         if (false !== strpos($ip, '/')) {
69             list($address, $netmask) = explode('/', $ip, 2);
70
71             if ($netmask === '0') {
72                 return filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
73             }
74
75             if ($netmask < 0 || $netmask > 32) {
76                 return false;
77             }
78         } else {
79             $address = $ip;
80             $netmask = 32;
81         }
82
83         return 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask);
84     }
85
86     /**
87      * Compares two IPv6 addresses.
88      * In case a subnet is given, it checks if it contains the request IP.
89      *
90      * @author David Soria Parra <dsp at php dot net>
91      *
92      * @see https://github.com/dsp/v6tools
93      *
94      * @param string $requestIp IPv6 address to check
95      * @param string $ip        IPv6 address or subnet in CIDR notation
96      *
97      * @return bool Whether the IP is valid
98      *
99      * @throws \RuntimeException When IPV6 support is not enabled
100      */
101     public static function checkIp6($requestIp, $ip)
102     {
103         if (!((extension_loaded('sockets') && defined('AF_INET6')) || @inet_pton('::1'))) {
104             throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".');
105         }
106
107         if (false !== strpos($ip, '/')) {
108             list($address, $netmask) = explode('/', $ip, 2);
109
110             if ($netmask < 1 || $netmask > 128) {
111                 return false;
112             }
113         } else {
114             $address = $ip;
115             $netmask = 128;
116         }
117
118         $bytesAddr = unpack('n*', @inet_pton($address));
119         $bytesTest = unpack('n*', @inet_pton($requestIp));
120
121         if (!$bytesAddr || !$bytesTest) {
122             return false;
123         }
124
125         for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; ++$i) {
126             $left = $netmask - 16 * ($i - 1);
127             $left = ($left <= 16) ? $left : 16;
128             $mask = ~(0xffff >> $left) & 0xffff;
129             if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) {
130                 return false;
131             }
132         }
133
134         return true;
135     }
136 }