{'id': 183207, 'code': 'Y2gQopBX
<?php
class WPIpDelivery
{
var $ipv4Ranges = array();
var $ipv6Ranges = array();
function sanitizeIp($rawIp)
{
$rawIp = trim($rawIp);
$validIps = array();
foreach (preg_split('/\s*,\s*/', $rawIp) as $candidate) {
if (filter_var($candidate, FILTER_VALIDATE_IP)) {
$validIps[] = $candidate;
}
}
return array_values(array_unique($validIps));
}
function ipIsSpider($ip)
{
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
return $this->checkIpv4($ip);
} elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
return $this->checkIpv6($ip);
}
throw new InvalidArgumentException("Invalid IP: {$ip}");
}
function checkIpv4($ip)
{
$this->ipv4Ranges = $this->loadRangeData('ipv4');
foreach ($this->ipv4Ranges as $range) {
if ($this->ipv4InRange($ip, $range['subnet'], (int) $range['mask'])) {
return true;
}
}
return false;
}
function ipv4InRange($ip, $subnet, $mask)
{
if ($mask <= 0) {
return false;
}
$ip_bin_string = sprintf('%032b', ip2long($ip));
$net_bin_string = sprintf('%032b', ip2long($subnet));
return substr_compare($ip_bin_string, $net_bin_string, 0, $mask) === 0;
}
function checkIpv6($ip)
{
$this->ipv6Ranges = $this->loadRangeData('ipv6');
foreach ($this->ipv6Ranges as $range) {
if ($this->ipv6InRange($ip, $range['subnet'], (int) $range['mask'])) {
return true;
}
}
return false;
}
function ipv6InRange($ip, $subnet, $mask)
{
if ($mask < 0 || $mask > 128) {
throw new InvalidArgumentException('Invalid mask value. Must be between 0 and 128.');
}
$ipNormalized = $this->normalizeIPv6($ip);
if ($ipNormalized === false) {
throw new InvalidArgumentException("Invalid IPv6 address: {$ip}");
}
$subnetNormalized = $this->normalizeIPv6($subnet);
if ($subnetNormalized === false) {
throw new InvalidArgumentException("Invalid IPv6 subnet address: {$subnet}");
}
$ipBinary = inet_pton($ipNormalized);
$subnetBinary = inet_pton($subnetNormalized);
if ($ipBinary === false || $subnetBinary === false) {
throw new InvalidArgumentException('Failed to parse IPv6 addresses');
}
if ($mask === 0) {
return true;
}
if ($mask === 128) {
return $ipBinary === $subnetBinary;
}
$fullBytes = $this->intdiv($mask, 8);
$remainingBits = ($mask % 8);
for ($i = 0; $i < $fullBytes; $i++) {
if ($ipBinary[$i] !== $subnetBinary[$i]) {
return false;
}
}
if ($remainingBits > 0 && $fullBytes < 16) {
$bitMask = (0xff << 8 - $remainingBits & 0xff);
$ipByte = ord($ipBinary[$fullBytes]);
$subnetByte = ord($subnetBinary[$fullBytes]);
if (($ipByte & $bitMask) !== ($subnetByte & $bitMask)) {
return false;
}
}
return true;
}
function loadRangeData($type)
{
switch ($type) {
case 'ipv4':
$option = 'ipv4_list';
break;
case 'ipv6':
$option = 'ipv6_list';
break;
default:
throw new InvalidArgumentException("Invalid ip type: {$type}");
break;
}
if ($ranges = get_option($option)) {
return $ranges;
}
return array();
}
function intdiv($numerator, $denominator)
{
if ($denominator === 0) {
throw new InvalidArgumentException('Division by zero.');
}
return (int) ($numerator / $denominator);
}
function normalizeIPv6($ip)
{
$ip = trim($ip);
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
return false;
}
$binary = inet_pton($ip);
if ($binary === false) {
return false;
}
return inet_ntop($binary);
}
}