public static function IPinList($ip, $ipTable = '')
{
// No point proceeding with an empty IP list
if (empty($ipTable)) {
return false;
}
// If the IP list is not an array, convert it to an array
if (!is_array($ipTable)) {
if (strpos($ipTable, ',') !== false) {
$ipTable = explode(',', $ipTable);
$ipTable = array_map(function ($x) {
return trim($x);
}, $ipTable);
} else {
$ipTable = trim($ipTable);
$ipTable = array($ipTable);
}
}
// If no IP address is found, return false
if ($ip == '0.0.0.0') {
return false;
}
// If no IP is given, return false
if (empty($ip)) {
return false;
}
// Sanity check
if (!function_exists('inet_pton')) {
return false;
}
// Get the IP's in_adds representation
$myIP = @inet_pton($ip);
// If the IP is in an unrecognisable format, quite
if ($myIP === false) {
return false;
}
$ipv6 = self::isIPv6($ip);
foreach ($ipTable as $ipExpression) {
$ipExpression = trim($ipExpression);
// Inclusive IP range, i.e. 123.123.123.123-124.125.126.127
if (strstr($ipExpression, '-')) {
list($from, $to) = explode('-', $ipExpression, 2);
if ($ipv6 && (!self::isIPv6($from) || !self::isIPv6($to))) {
// Do not apply IPv4 filtering on an IPv6 address
continue;
} elseif (!$ipv6 && (self::isIPv6($from) || self::isIPv6($to))) {
// Do not apply IPv6 filtering on an IPv4 address
continue;
}
$from = @inet_pton(trim($from));
$to = @inet_pton(trim($to));
// Sanity check
if ($from === false || $to === false) {
continue;
}
// Swap from/to if they're in the wrong order
if ($from > $to) {
list($from, $to) = array($to, $from);
}
if ($myIP >= $from && $myIP <= $to) {
return true;
}
} elseif (strstr($ipExpression, '/')) {
$binaryip = self::inet_to_bits($myIP);
list($net, $maskbits) = explode('/', $ipExpression, 2);
if ($ipv6 && !self::isIPv6($net)) {
// Do not apply IPv4 filtering on an IPv6 address
continue;
} elseif (!$ipv6 && self::isIPv6($net)) {
// Do not apply IPv6 filtering on an IPv4 address
continue;
} elseif ($ipv6 && strstr($maskbits, ':')) {
// Perform an IPv6 CIDR check
if (self::checkIPv6CIDR($myIP, $ipExpression)) {
return true;
}
// If we didn't match it proceed to the next expression
continue;
} elseif (!$ipv6 && strstr($maskbits, '.')) {
// Convert IPv4 netmask to CIDR
$long = ip2long($maskbits);
$base = ip2long('255.255.255.255');
$maskbits = 32 - log(($long ^ $base) + 1, 2);
}
// Convert network IP to in_addr representation
$net = @inet_pton($net);
// Sanity check
if ($net === false) {
continue;
}
// Get the network's binary representation
$binarynet = self::inet_to_bits($net);
$expectedNumberOfBits = $ipv6 ? 128 : 24;
$binarynet = str_pad($binarynet, $expectedNumberOfBits, '0', STR_PAD_RIGHT);
// Check the corresponding bits of the IP and the network
$ip_net_bits = substr($binaryip, 0, $maskbits);
$net_bits = substr($binarynet, 0, $maskbits);
if ($ip_net_bits == $net_bits) {
return true;
}
} else {
// IPv6: Only single IPs are supported
if ($ipv6) {
$ipExpression = trim($ipExpression);
if (!self::isIPv6($ipExpression)) {
continue;
}
$ipCheck = @inet_pton($ipExpression);
if ($ipCheck === false) {
continue;
}
if ($ipCheck == $myIP) {
return true;
}
} else {
// Standard IPv4 address, i.e. 123.123.123.123 or partial IP address, i.e. 123.[123.][123.][123]
$dots = 0;
if (substr($ipExpression, -1) == '.') {
// Partial IP address. Convert to CIDR and re-match
foreach (count_chars($ipExpression, 1) as $i => $val) {
if ($i == 46) {
$dots = $val;
}
}
$netmask = '255.255.255.255';
switch ($dots) {
case 1:
$netmask = '255.0.0.0';
$ipExpression .= '0.0.0';
break;
case 2:
$netmask = '255.255.0.0';
$ipExpression .= '0.0';
break;
case 3:
$netmask = '255.255.255.0';
$ipExpression .= '0';
break;
default:
$dots = 0;
}
if ($dots) {
$binaryip = self::inet_to_bits($myIP);
// Convert netmask to CIDR
$long = ip2long($netmask);
$base = ip2long('255.255.255.255');
$maskbits = 32 - log(($long ^ $base) + 1, 2);
$net = @inet_pton($ipExpression);
// Sanity check
if ($net === false) {
continue;
}
// Get the network's binary representation
$binarynet = self::inet_to_bits($net);
$expectedNumberOfBits = $ipv6 ? 128 : 24;
$binarynet = str_pad($binarynet, $expectedNumberOfBits, '0', STR_PAD_RIGHT);
// Check the corresponding bits of the IP and the network
$ip_net_bits = substr($binaryip, 0, $maskbits);
$net_bits = substr($binarynet, 0, $maskbits);
if ($ip_net_bits == $net_bits) {
return true;
}
}
}
if (!$dots) {
$ip = @inet_pton(trim($ipExpression));
if ($ip == $myIP) {
return true;
}
}
}
}
}
return false;
}