: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Returns the human-readable representation of a packed binary IP address.
public static function inet_ntop($ip) {
if (Model_Crypto::strlen($ip) == 16 && Model_Crypto::substr($ip, 0, 12) == "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff") {
$ip = Model_Crypto::substr($ip, 12, 4);
if (Model_Crypto::strlen($ip) === 4) {
return ord($ip[0]) . '.' . ord($ip[1]) . '.' . ord($ip[2]) . '.' . ord($ip[3]);
if (Model_Crypto::strlen($ip) === 16) {
if (Model_Crypto::substr($ip, 0, 12) == "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff") {
return "::ffff:" . ord($ip[12]) . '.' . ord($ip[13]) . '.' . ord($ip[14]) . '.' . ord($ip[15]);
$groups = str_split($hex, 4);
foreach ($groups as $index => $group) {
if ($group == '0000' && !$done_collapse) {
$groups[$index] = ltrim($groups[$index], '0');
if (strlen($groups[$index]) === 0) {
$ip = join(':', array_filter($groups, 'strlen'));
$ip = str_replace(':::', '::', $ip);
return $ip == ':' ? '::' : $ip;
* Returns the packed binary representation of an IP address from the human readable version.
public static function inet_pton($ip) {
if (preg_match('/^(?:\d{1,3}(?:\.|$)){4}/', $ip)) { // IPv4
$octets = explode('.', $ip);
$pton = chr($octets[0]) . chr($octets[1]) . chr($octets[2]) . chr($octets[3]);
else if (preg_match('/^((?:[\da-f]{1,4}(?::|)){0,8})(::)?((?:[\da-f]{1,4}(?::|)){0,8})$/i', $ip)) { // IPv6
$pton = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
$colon_count = substr_count($ip, ':');
$dbl_colon_pos = strpos($ip, '::');
if ($dbl_colon_pos !== false) {
$ip = str_replace('::', str_repeat(':0000', (($dbl_colon_pos === 0 || $dbl_colon_pos === strlen($ip) - 2) ? 9 : 8) - $colon_count) . ':', $ip);
$ip_groups = explode(':', $ip);
foreach ($ip_groups as $ip_group) {
$ipv6_bin .= pack('H*', str_pad($ip_group, 4, '0', STR_PAD_LEFT));
if (Model_Crypto::strlen($ipv6_bin) == 16) {
else if (preg_match('/^(?:\:(?:\:0{1,4}){0,4}\:|(?:0{1,4}\:){5})ffff\:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/i', $ip, $matches)) { // IPv4 mapped IPv6
$octets = explode('.', $matches[1]);
$pton = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" . chr($octets[0]) . chr($octets[1]) . chr($octets[2]) . chr($octets[3]);
$pton = str_pad($pton, 16, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00", STR_PAD_LEFT);
* Verify PHP was compiled with IPv6 support.
* Some hosts appear to not have inet_ntop, and others appear to have inet_ntop but are unable to process IPv6 addresses.
public static function has_ipv6() {
return defined('AF_INET6');
* Expands a compressed printable representation of an IPv6 address.
public static function expand_ipv6_address($ip) {
$hex = bin2hex(self::inet_pton($ip));
$ip = substr(preg_replace("/([a-f0-9]{4})/i", "$1:", $hex), 0, -1);
* Returns whether or not the IP is a valid format.
public static function is_valid_ip($ip) {
return filter_var($ip, FILTER_VALIDATE_IP) !== false;
* Returns whether or not the range is a valid CIDR range.
public static function is_valid_cidr_range($range) {
$components = explode('/', $range);
if (count($components) != 2) { return false; }
list($ip, $prefix) = $components;
if (!self::is_valid_ip($ip)) { return false; }
if (!preg_match('/^\d+$/', $prefix)) { return false; }
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
if ($prefix < 0 || $prefix > 32) { return false; }
if ($prefix < 1 || $prefix > 128) { return false; }
* Returns whether or not the IP is in the IPv6-mapped-IPv4 format.
public static function is_ipv6_mapped_ipv4($ip) {
return preg_match('/^(?:\:(?:\:0{1,4}){0,4}\:|(?:0{1,4}\:){5})ffff\:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/i', $ip) > 0;