File: /var/www/html/wp-content/plugins/wp-fail2ban/lib/ip-range-list.php
<?php declare(strict_types=1);
/**
* IPv4/IPv6 Ranges Class
*
* @package wp-fail2ban
* @since 5.0.0
*/
namespace org\lecklider\charles\wordpress\wp_fail2ban;
use org\lecklider\charles\wordpress\wp_fail2ban\premium\WPf2b;
/**
* List of IP ranges.
*
* @since 5.0.0
*/
class IpRangeList implements \ArrayAccess, \Countable, \Iterator {
/**
* @var int Iterator position.
* @since 5.0.0
*/
protected int $position = 0;
/**
* @var array|bool IP Ranges.
* @since 5.0.0
*/
protected $ranges = false;
/**
* Constructor.
*
* @since 5.0.0
*
* @param array $ranges
* @param string|null $cacheTag
*/
public function __construct( array $ranges, string $cacheTag = null ) {
$canCache = ( ! is_null( $cacheTag ) &&
class_exists( __NAMESPACE__ . '\\premium\\WPf2b' ) &&
WPf2b::can_use_premium_code() );
if ( $canCache ) {
$this->ranges = wp_cache_get( $cacheTag, WP_FAIL2BAN_CACHE );
}
if ( false === $this->ranges ) {
$this->ranges = array();
foreach ( $ranges as $range ) {
$range = trim( $range );
if ( empty( $range ) || '#' == $range[0] ) {
continue;
} else {
$this->ranges[] = new IP( $range );
}
}
if ( $canCache ) {
wp_cache_set( $cacheTag, $this->ranges, WP_FAIL2BAN_CACHE );
}
}
}
/**
* Does the range contain the IP?
*
* @since 5.0.0
*
* @param string|IP $ip
*
* @throws \InvalidArgumentException
*
* @return bool
*/
public function containsIP( $ip ): bool {
if ( is_string( $ip ) ) {
$bin = inet_pton( $ip );
$ver = null;
} elseif ( is_a( $ip, __NAMESPACE__ . '\IP' ) ) {
$bin = $ip->getIpN();
$ver = $ip->getVersion();
} else {
throw new \InvalidArgumentException( 'Must be string or IP.' );
}
return self::containsBinaryIP( $bin, $ver );
}
/**
* Does the range contain the IP? (Binary)
*
* @since 5.0.0
*
* @param string $binIP
* @param int|null $version
*
* @return bool
*/
public function containsBinaryIP( $binIP, ?int $version = null ): bool {
if ( is_null( $version ) ) {
$version = ( 4 == strlen( $binIP ) ) ? 4 : 6;
}
foreach ( $this->ranges as $ipRange ) {
if ( $version == $ipRange->getVersion() &&
$ipRange->getIpN() == ( $binIP & $ipRange->getNetmaskN() ) ) {
return true;
}
}
return false;
}
//
// ArrayAccess
//
/**
* ArrayAccess: offsetSet.
*
* @since 5.0.0
*
* @param mixed $offset Key.
* @param mixed $value Value.
*
* @throw \RuntimeException
*
* @codeCoverageIgnore
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function offsetSet( $offset, $value ): void {
throw new \RuntimeException( 'Lists are read-only' );
}
/**
* ArrayAccess: offsetExists.
*
* @since 5.0.0
*
* @param mixed $offset Key.
* @return bool
*
* @codeCoverageIgnore
*/
public function offsetExists( $offset ): bool {
return isset( $this->ranges[ $offset ] );
}
/**
* ArrayAccess: offsetUnset.
*
* @since 5.0.0
*
* @param mixed $offset Key.
*
* @throw \RuntimeException
*
* @codeCoverageIgnore
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function offsetUnset( $offset ): void {
throw new \RuntimeException( 'Lists are read-only' );
}
/**
* ArrayAccess: offsetGet.
*
* @since 5.0.0
*
* @param mixed $offset Key.
* @return bool
*
* @codeCoverageIgnore
*/
#[\ReturnTypeWillChange]
public function offsetGet( $offset ): bool {
return isset( $this->ranges[ $offset ] ) ? $this->ranges[ $offset ] : null;
}
//
// Countable
//
/**
* Countable: count.
*
* @since 5.0.0
*
* @return int
*
* @codeCoverageIgnore
*/
public function count(): int {
return count( $this->ranges );
}
//
// Iterator
//
/**
* Iterator: rewind.
*
* @since 5.0.0
*
* @codeCoverageIgnore
*/
public function rewind(): void {
$this->position = 0;
}
/**
* Iterator: current.
*
* @since 5.0.0
*
* @return mixed
*
* @codeCoverageIgnore
*/
#[\ReturnTypeWillChange]
public function current() {
return $this->ranges[ $this->position ];
}
/**
* Iterator: key.
*
* @since 5.0.0
*
* @return int
*
* @codeCoverageIgnore
*/
#[\ReturnTypeWillChange]
public function key() {
return $this->position;
}
/**
* Iterator: next.
*
* @since 5.0.0
*
* @codeCoverageIgnore
*/
public function next(): void {
++$this->position;
}
/**
* Iterator: valid.
*
* @since 5.0.0
*
* @return bool
*
* @codeCoverageIgnore
*/
public function valid(): bool {
return isset( $this->ranges[ $this->position ] );
}
}