ok, so it's not one giant regex.. after some thinking, that'd just be too crazy and probably eat the processor.. so here's a more simple subset of regex that get it done.
Code: Select all
<?php
class DNAUnitTest extends UnitTestCase
{
public function __construct($aName = null)
{
if ($aName === null)
{
$name = preg_split('#([^A-Za-z]+|[A-Z]?[a-z]+)#', get_class($this), -1, PREG_SPLIT_DELIM_CAPTURE);
$name = array_map('trim', $name);
$name = array_filter($name);
$name = implode(' ', $name);
}
else
{
$name = strval($aName);
}
parent::UnitTestCase($name);
}
}
function isValidIP($aIP)
{
$hex = '[0-9a-fA-F]';
$blk = '(?:' . $hex . '{1,4})';
$pre = '(?:/(?:12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))'; // /0 - /128
$oct = '(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])'; // 0-255
$ip4 = "(?:{$oct}\\.{$oct}\\.{$oct}\\.{$oct})";
// standard IPv4 quick check.
if (preg_match('#^' . $ip4 . '$#s', $aIP))
{
return true;
}
// prefix check
if (strpos($aIP, '/') !== false)
{
if (preg_match('#' . $pre . '$#s', $aIP, $find))
{
$aIP = substr($aIP, 0, 0-strlen($find[0]));
unset($find);
}
else
{
return false;
}
}
// IPv4-compatiblity check
if (preg_match('#(?<=:'.')' . $ip4 . '$#s', $aIP, $find))
{
$aIP = substr($aIP, 0, 0-strlen($find[0]));
$ip = explode('.', $find[0]);
$ip = array_map('dechex', $ip);
$aIP .= $ip[0] . $ip[1] . ':' . $ip[2] . $ip[3];
unset($find, $ip);
}
// compression check
$aIP = explode('::', $aIP);
$c = count($aIP);
if ($c > 2)
{
return false;
}
elseif ($c == 2)
{
list($first, $second) = $aIP;
$first = explode(':', $first);
$second = explode(':', $second);
if (count($first) + count($second) >
{
return false;
}
while(count($first) <
{
array_push($first, '0');
}
array_splice($first, 8 - count($second), 8, $second);
$aIP = $first;
unset($first,$second);
}
else
{
$aIP = explode(':', $aIP[0]);
}
$c = count($aIP);
if ($c !=
{
return false;
}
// All the pieces should be 16-bit hex strings. Are they?
foreach ($aIP as $piece)
{
if (!preg_match('#^[0-9a-fA-F]{4}$#s', sprintf('%04s', $piece)))
{
return false;
}
}
return true;
}
class TestIPAddress extends DNAUnitTest
{
public function testIsValidIP()
{
$this->AssertTrue( isValidIP('2001:DB8:0:0:8:800:200C:417A')); // unicast, full
$this->AssertTrue( isValidIP('FF01:0:0:0:0:0:0:101')); // multicast, full
$this->AssertTrue( isValidIP('0:0:0:0:0:0:0:1')); // loopback, full
$this->AssertTrue( isValidIP('0:0:0:0:0:0:0:0')); // unspecified, full
$this->AssertTrue( isValidIP('2001:DB8::8:800:200C:417A')); // unicast, compressed
$this->AssertTrue( isValidIP('FF01::101')); // multicast, compressed
$this->AssertTrue( isValidIP('::1')); // loopback, compressed, non-routable
$this->AssertTrue( isValidIP('::')); // unspecified, compressed, non-routable
$this->AssertTrue( isValidIP('0:0:0:0:0:0:13.1.68.3')); // IPv4-compatible IPv6 address, full, deprecated
$this->AssertTrue( isValidIP('0:0:0:0:0:FFFF:129.144.52.38')); // IPv4-mapped IPv6 address, full
$this->AssertTrue( isValidIP('::13.1.68.3')); // IPv4-compatible IPv6 address, compressed, deprecated
$this->AssertTrue( isValidIP('::FFFF:129.144.52.38')); // IPv4-mapped IPv6 address, compressed
$this->AssertTrue( isValidIP('2001:0DB8:0000:CD30:0000:0000:0000:0000/60')); // full, with prefix
$this->AssertTrue( isValidIP('2001:0DB8::CD30:0:0:0:0/60')); // compressed, with prefix
$this->AssertTrue( isValidIP('2001:0DB8:0:CD30::/60')); // compressed, with prefix #2
$this->AssertTrue( isValidIP('::/128')); // compressed, unspecified address type, non-routable
$this->AssertTrue( isValidIP('::1/128')); // compressed, loopback address type, non-routable
$this->AssertTrue( isValidIP('FF00::/8')); // compressed, multicast address type
$this->AssertTrue( isValidIP('FE80::/10')); // compressed, link-local unicast, non-routable
$this->AssertTrue( isValidIP('FEC0::/10')); // compressed, site-local unicast, deprecated
$this->AssertTrue( isValidIP('127.0.0.1')); // standard IPv4, loopback, non-routable
$this->AssertTrue( isValidIP('0.0.0.0')); // standard IPv4, unspecified, non-routable
$this->AssertTrue( isValidIP('255.255.255.255')); // standard IPv4
$this->AssertFalse(isValidIP('300.0.0.0')); // standard IPv4, out of range
$this->AssertFalse(isValidIP('124.15.6.89/60')); // standard IPv4, prefix not allowed
$this->AssertFalse(isValidIP('2001:DB8:0:0:8:800:200C:417A:221')); // unicast, full
$this->AssertFalse(isValidIP('FF01::101::2')); // multicast, compressed
$this->AssertFalse(isValidIP('')); // nothing
}
}
include '../3rdParty/SimpleTest/unit_tester.php';
include '../3rdParty/SimpleTest/reporter.php';
$test = new TestIPAddress();
$test->run(new HTMLReporter());
?>