ipaddresses : Add support to calculations on IP addresses

git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@2542 bf3deb0d-5f1a-0410-827f-c0cc1f45334c
This commit is contained in:
2016-02-23 11:55:59 +00:00
parent 01efb53dfa
commit 9dbd64d6a2
2 changed files with 492 additions and 0 deletions

255
Tests/ipaddressesTest.php Normal file
View File

@@ -0,0 +1,255 @@
<?php
/** DomFramework - Tests
@package domframework
@author Dominique Fournier <dominique@fournier38.fr> */
/** Test the ipaddresses.php file */
class test_ipaddresses extends PHPUnit_Framework_TestCase
{
public function test_validIPAddress1 ()
{
$i = new ipaddresses ();
$res = $i->validIPAddress ("::");
$this->assertSame (true, $res);
}
public function test_validIPAddress2 ()
{
$i = new ipaddresses ();
$res = $i->validIPAddress ("1::");
$this->assertSame (true, $res);
}
public function test_validIPAddress3 ()
{
$i = new ipaddresses ();
$res = $i->validIPAddress ("::1");
$this->assertSame (true, $res);
}
public function test_validIPAddress4 ()
{
$i = new ipaddresses ();
$res = $i->validIPAddress ("2001::1");
$this->assertSame (true, $res);
}
public function test_validIPAddress5 ()
{
$i = new ipaddresses ();
$res = $i->validIPAddress ("1.2.3.4");
$this->assertSame (true, $res);
}
public function test_validIPAddress6 ()
{
$this->setExpectedException ("Exception");
$i = new ipaddresses ();
$res = $i->validIPAddress ("");
}
public function test_validIPAddress7 ()
{
$this->setExpectedException ("Exception");
$i = new ipaddresses ();
$res = $i->validIPAddress (array ());
}
public function test_validIPv4Address1 ()
{
$i = new ipaddresses ();
$res = $i->validIPv4Address ("::");
$this->assertSame (false, $res);
}
public function test_validIPv4Address2 ()
{
$i = new ipaddresses ();
$res = $i->validIPv4Address ("1.2.3.4");
$this->assertSame (true, $res);
}
public function test_validIPv6Address1 ()
{
$i = new ipaddresses ();
$res = $i->validIPv6Address ("1.2.3.4");
$this->assertSame (false, $res);
}
public function test_validIPv6Address2 ()
{
$i = new ipaddresses ();
$res = $i->validIPv6Address ("::");
$this->assertSame (true, $res);
}
public function test_validIPv6Address3 ()
{
$i = new ipaddresses ();
$res = $i->validIPv6Address ("1::");
$this->assertSame (true, $res);
}
public function test_validIPv6Address4 ()
{
$i = new ipaddresses ();
$res = $i->validIPv6Address ("::1");
$this->assertSame (true, $res);
}
public function test_validIPv6Address5 ()
{
$i = new ipaddresses ();
$res = $i->validIPv6Address ("1::1");
$this->assertSame (true, $res);
}
public function test_validIPv6Address6 ()
{
$i = new ipaddresses ();
$res = $i->validIPv6Address ("1:1:1");
$this->assertSame (false, $res);
}
public function test_uncompressIPv6a ()
{
$i = new ipaddresses ();
$res = $i->uncompressIPv6 ("1::1");
$this->assertSame ("1:0:0:0:0:0:0:1", $res);
}
public function test_uncompressIPv6b ()
{
$i = new ipaddresses ();
$res = $i->uncompressIPv6 ("1::");
$this->assertSame ("1:0:0:0:0:0:0:0", $res);
}
public function test_uncompressIPv6c ()
{
$i = new ipaddresses ();
$res = $i->uncompressIPv6 ("::");
$this->assertSame ("0:0:0:0:0:0:0:0", $res);
}
public function test_uncompressIPv6d ()
{
$i = new ipaddresses ();
$res = $i->uncompressIPv6 ("1.2.3.4");
$this->assertSame ("1.2.3.4", $res);
}
public function test_groupIPv6a ()
{
$this->setExpectedException ("Exception");
$i = new ipaddresses ();
$res = $i->groupIPv6 ("1.2.3.4");
}
public function test_groupIPv6b ()
{
$i = new ipaddresses ();
$res = $i->groupIPv6 ("0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.".
"0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f");
$this->assertSame ("0123:4567:89ab:cdef:0123:4567:89ab:cdef", $res);
}
public function test_completeAddressWithZero1 ()
{
$i = new ipaddresses ();
$res = $i->completeAddressWithZero ("::");
$this->assertSame ("0000:0000:0000:0000:0000:0000:0000:0000", $res);
}
public function test_completeAddressWithZero2 ()
{
$i = new ipaddresses ();
$res = $i->completeAddressWithZero ("::1");
$this->assertSame ("0000:0000:0000:0000:0000:0000:0000:0001", $res);
}
public function test_completeAddressWithZero3 ()
{
$i = new ipaddresses ();
$res = $i->completeAddressWithZero ("1::");
$this->assertSame ("0001:0000:0000:0000:0000:0000:0000:0000", $res);
}
public function test_completeAddressWithZero4 ()
{
$i = new ipaddresses ();
$res = $i->completeAddressWithZero ("1::1");
$this->assertSame ("0001:0000:0000:0000:0000:0000:0000:0001", $res);
}
public function test_completeAddressWithZero5 ()
{
$i = new ipaddresses ();
$res = $i->completeAddressWithZero ("1:222::1");
$this->assertSame ("0001:0222:0000:0000:0000:0000:0000:0001", $res);
}
public function test_completeAddressWithZero6 ()
{
$i = new ipaddresses ();
$res = $i->completeAddressWithZero ("1.2.3.4");
$this->assertSame ("1.2.3.4", $res);
}
// TODO : cidrToBin
// TODO : str_base_convert
public function test_reverseIPAddress1 ()
{
$i = new ipaddresses ();
$res = $i->reverseIPAddress ("1.2.3.4");
$this->assertSame ("4.3.2.1", $res);
}
public function test_reverseIPAddress2 ()
{
$i = new ipaddresses ();
$res = $i->reverseIPAddress ("::");
$this->assertSame ("0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0", $res);
}
public function test_reverseIPAddress3 ()
{
$i = new ipaddresses ();
$res = $i->reverseIPAddress ("::1");
$this->assertSame ("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0", $res);
}
public function test_reverseIPAddress4 ()
{
$i = new ipaddresses ();
$res = $i->reverseIPAddress ("2::1");
$this->assertSame ("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0", $res);
}
public function test_reverseIPAddress5 ()
{
$i = new ipaddresses ();
$res = $i->reverseIPAddress ("2::abcd:1");
$this->assertSame ("1.0.0.0.d.c.b.a.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0", $res);
}
public function test_netmask2cidr1 ()
{
$this->setExpectedException ("Exception");
$i = new ipaddresses ();
$res = $i->netmask2cidr (0);
}
public function test_netmask2cidr2 ()
{
$i = new ipaddresses ();
$res = $i->netmask2cidr ("255.255.255.0");
$this->assertSame (24, $res);
}
public function test_netmask2cidr3 ()
{
$i = new ipaddresses ();
$res = $i->netmask2cidr ("255.255.255.255");
$this->assertSame (32, $res);
}
public function test_netmask2cidr4 ()
{
$i = new ipaddresses ();
$res = $i->netmask2cidr ("255.255.255.255");
$this->assertSame (32, $res);
}
public function test_netmask2cidr5 ()
{
$i = new ipaddresses ();
$res = $i->netmask2cidr ("255.0.0.0");
$this->assertSame (8, $res);
}
public function test_netmask2cidr6 ()
{
$i = new ipaddresses ();
$res = $i->netmask2cidr ("127.0.0.0");
$this->assertSame (7, $res);
}
public function test_netmask2cidr7 ()
{
$i = new ipaddresses ();
$res = $i->netmask2cidr ("63.0.0.0");
$this->assertSame (6, $res);
}
}

237
ipaddresses.php Normal file
View File

@@ -0,0 +1,237 @@
<?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 IP 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 IP 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, ".") === 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;
}
}