Files
DomFramework/ipaddresses.php

243 lines
6.9 KiB
PHP

<?php
/** DomFramework
@package domframework
@author Dominique Fournier <dominique@fournier38.fr> */
/** Manage the IP addresses conversions */
class ipaddresses
{
/** Return true if the provided IP address is valid (IPv4 or IPv6) */
public function validIPAddress ($ip)
{
if (!is_string ($ip) || $ip === "")
throw new \Exception (dgettext("domframework", "Invalid IP address"), 500);
$rc = $this->validIPv4Address ($ip);
if ($rc === TRUE)
return TRUE;
$rc = $this->validIPv6Address ($ip);
return $rc;
}
/** Return true if the provided IP address is valid and is IPv4 */
public function validIPv4Address ($ip)
{
if (!is_string ($ip) || $ip === "")
throw new \Exception (dgettext("domframework", "Invalid IPv4 address"), 500);
$rc = filter_var ($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
if ($rc ===FALSE)
return FALSE;
return TRUE;
}
/** Return true if the provided IP address is valid and is IPv6 */
public function validIPv6Address ($ip)
{
if (!is_string ($ip) || $ip === "")
throw new \Exception (dgettext("domframework", "Invalid IPv6 address"), 500);
$rc = filter_var ($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
if ($rc ===FALSE)
return FALSE;
return TRUE;
}
/** Return the IPv6 uncompressed (all the fields exists). They are not filled by
zeros
If the provided IP is IPv4, there is no change applied
Return False if the parameter is invalid
Based on http://www.weberdev.com/get_example.php3?ExampleID=3921 */
public function uncompressIPv6 ($ip)
{
if (! is_string ($ip) || $ip === "")
throw new \Exception (dgettext("domframework", "Invalid IP address"), 500);
if (strstr ($ip,"::"))
{
$e = explode (":", $ip);
// Case where :: is in start
if ($e[0] === "")
$e[0] = "0";
// Case where :: is in end
if ($e[count ($e)-1] === "")
$e[count ($e)-1] = "0";
$s = 8 - count ($e);
foreach ($e as $key=>$val)
{
if ($val === "")
{
for ($i=0 ; $i<=$s ; $i++)
$newipv6[] = 0;
}
else
{
$newipv6[] = $val;
}
}
$ip = implode (":", $newipv6);
}
return $ip;
}
/* Get an IPv6 address with the format
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x
and return it with format
xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
Return false if the IP provided is not complete */
public function groupIPv6 ($ipv6)
{
if (! is_string ($ipv6) || $ipv6 === "")
throw new \Exception (dgettext("domframework", "Invalid IPv6 address"), 500);
if (substr_count ($ipv6, ".") !== 31)
throw new \Exception (dgettext("domframework", "Invalid IPv6 address"), 500);
$ipv6 = str_replace (".", "", $ipv6);
$new = "";
for ($i = 0 ; $i < 32 ; $i++)
{
if ($i % 4 === 0 && $i !== 0)
{
$new .= ":";
}
$new .= $ipv6[$i];
}
return $new;
}
/* Return the IP adddress with filling the fields with the missing zeros.
Valid only on IPv6 (but don't change anything if the provided address is IPv4) */
public function completeAddressWithZero ($ip)
{
if (! is_string ($ip) || $ip === "")
throw new \Exception (dgettext("domframework", "Invalid IP address"), 500);
$ip = $this->uncompressIPv6 ($ip);
if (substr_count ($ip, ":") === 7)
{
// IPv6
$ips = explode (":", $ip);
$ipnew = array();
foreach ($ips as $iptmp)
{
$ipnew[] = sprintf ("%04x", hexdec ($iptmp));
}
return implode (":", $ipnew);
}
elseif (substr_count ($ip, ".") === 31)
{
// Full IPv6 with dots
return $ip;
}
elseif (substr_count ($ip, ".") === 3)
{
// IPv4
return $ip;
}
throw new \Exception (dgettext("domframework", "Invalid IP address"), 500);
}
/* Return the provided CIDR in binary. Length must be in bytes.
Return FALSE if the parameters are invalid */
public function cidrToBin ($cidr, $length)
{
if (! is_numeric ($cidr) || $cidr < 0 || $cidr > 128)
throw new \Exception (dgettext("domframework", "Invalid CIDR"), 500);
if (! is_numeric ($length) || $length < 1 || $length > 16)
throw new \Exception (dgettext("domframework", "Invalid length"), 500);
$val="";
for ( $i=0 ; $i<$length*8 ; $i++ )
{
if ($i < $cidr) $val.="1";
else $val.="0";
}
return pack ('H*', $this->str_base_convert ($val, 2, 16));
}
/* Base conversion with 128 bits support for IPv6
Based on http://fr2.php.net/manual/en/function.base-convert.php#109660 */
public function str_base_convert($str, $frombase=10, $tobase=36)
{
$str = trim ($str);
if (intval ($frombase) != 10)
{
$len = strlen ($str);
$q = 0;
for ($i=0; $i<$len; $i++)
{
$r = base_convert ($str[$i], $frombase, 10);
$q = bcadd (bcmul ($q, $frombase), $r);
}
}
else
{
$q = $str;
}
if (intval ($tobase) != 10)
{
$s = '';
while (bccomp ($q, '0', 0) > 0)
{
$r = intval (bcmod($q, $tobase));
$s = base_convert ($r, 10, $tobase) . $s;
$q = bcdiv ($q, $tobase, 0);
}
}
else
{
$s = $q;
}
return $s;
}
/* Reverse the provided IP address
The IPv6 are returned in format :
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x */
function reverseIPAddress ($ipReverse)
{
if (!is_string ($ipReverse) || $ipReverse === "")
throw new \Exception (dgettext("domframework", "Invalid IP address"), 500);
$ipReverse = $this->completeAddressWithZero ($ipReverse);
if (substr_count ($ipReverse, ":") === 7 && strlen ($ipReverse) == 39)
{
// Complete IPv6 with quadruplets and colon
$ip = str_replace (":", "", $ipReverse);
$tmp2 = array_reverse (str_split ($ip));
return implode (".", $tmp2);
}
elseif (substr_count ($ipReverse, ".") === 31)
{
// IPv6 with dots
$tmp2 = explode (".", $ipReverse);
$tmp2 = array_reverse ($tmp2);
$ipnew = implode (".", $tmp2);
return $ipnew;
}
elseif (substr_count ($ipReverse, ".") === 3)
{
// IPv4
$tmp2 = explode (".", $ipReverse);
$tmp2 = array_reverse ($tmp2);
$ipnew = implode (".", $tmp2);
return $ipnew;
}
throw new \Exception (dgettext("domframework", "Invalid IP address"), 500);
}
/* This function return the CIDR associated to the provided netmask
Ex. Return 24 for a mask 255.255.255.0
Work only in IPv4
Return FALSE if the provided IP is invalid */
public function netmask2cidr ($netmask)
{
$netmask = ip2long ($netmask);
if ($netmask === FALSE)
throw new \Exception (dgettext("domframework", "Invalid netmask"), 500);
$netmask = decbin ($netmask);
for ($i=0 ; $i<32 ; $i++)
{
if ($netmask{$i} == 0)
{
break;
}
}
return $i;
}
}