annotate vendor/symfony/http-foundation/IpUtils.php @ 12:7a779792577d

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