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:
255
Tests/ipaddressesTest.php
Normal file
255
Tests/ipaddressesTest.php
Normal 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
237
ipaddresses.php
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user