This got me to thinking about the way we often forget that the various representations of an IP address are all just ways of writing a decimal value that can be up to 4294967295 (largest unsigned value in 32 bits).
I sometimes like confusing friends by giving them addresses like this to visit
http://1073170174/viewtopic.php?t=40333
(will work in most browsers, but ensure you're not accessing via a proxy that treats is as a DNS name)
Just for the fun of it, here are four functions that test an IP, with decreasing levels of clarity and increasing levels of compactness, and one that returns HTML with a report on the validity of a dotted-quad IP address and highlights any illegal elements.
Its interesting that with dotted-quad theres also the
hex-based validity test:
1. Convert each decimal element to its hex representation
2. If an element has more than 2 hex digits, its illegal (useful to save multiplication)
3. If there are not exactly 4 elements, its illegal
In the code below, its called isValidIpv4_Hex().
Code: Select all
<?php
function isValidIPv4_Hex($dottedQuad) {
preg_match('/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/', $dottedQuad, $quads = array());
foreach($quads as $element) if (strlen(dechex($element)) > 2) return false;
return (count($quads)==5);
}
function isValidIPv4_A($dottedQuad) {
$ret = true; // try to disprove this
$regexp = '/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/';
$quads = array();
$count = preg_match($regexp, $dottedQuad, $quads);
$maxVal = 0;
$decVal = 0;
if (count($quads)==5) {
for($i=1;$i<=4;$i++) {
$multiplier = pow(2,8*(5-$i)-8);
$decVal = $multiplier * $quads[$i];
$maxVal = $multiplier * 255;
$ret = ($decVal > $maxVal ? false : $ret);
}
}
else $ret = false;
return $ret;
}
function isValidIPv4_B($dottedQuad) {
$regexp = '/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/';
$quads = array();
$count = preg_match($regexp, $dottedQuad, $quads);
return (($count==0 || ($quads[1]>255 || $quads[2]>255 || $quads[3]>255 || $quads[4]>255) || ($quads[1]*16777216 + $quads[2]*65536 + $quads[3]*256 + $quads[4]*1 >= 4294967296)) ? false : true);
}
function isValidIPv4_C($dottedQuad) {
$count = preg_match('/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/', $dottedQuad, $quads = array());
return (($count==0 || ($quads[1]>255 || $quads[2]>255 || $quads[3]>255 || $quads[4]>255) || ($quads[1]*16777216 + $quads[2]*65536 + $quads[3]*256 + $quads[4] >= 4294967296)) ? false : true);
}
function isValidIPv4HTML($dottedQuad) {
$ret = '<style type="text/css">.error{color:red;font-weight:bold;}</style>';
$regexp = '/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/';
$quads = array();
$count = preg_match($regexp, $dottedQuad, $quads);
$validFlag = true; // assume ok unles proved otherwise
$maxVal = 0;
$decVal = 0;
if (count($quads)==5) {
for($i=1;$i<=4;$i++) {
$multiplier = (8*(5-$i)-8)+1;
$decVal = pow(2,$multiplier) * $quads[$i];
$maxVal = pow(2,$multiplier) * 255;
$validFlag = ($decVal > $maxVal ? false : $validFlag);
$ret .= '<span class="'.($decVal <= $maxVal ? '' : 'error').'">'.$quads[$i].'</span>'.($i<4 ? '.' : '');
}
$ret .= " (".(count($quads)-1)." quads) is ". (($count!=0 && $validFlag) ? 'valid' : 'invalid');
}
else $ret .= $dottedQuad.'<span class="error"> has illegal format';
return $ret;
}
$ip = "63.247.70.256";
echo "isValidIPv4_A($ip)=".sprintf('%d',isValidIPv4_A($ip))."<br/>\r\n";
echo "isValidIPv4_B($ip)=".sprintf('%d',isValidIPv4_B($ip))."<br/>\r\n";
echo "isValidIPv4_C($ip)=".sprintf('%d',isValidIPv4_C($ip))."<br/>\r\n";
echo "isValidIPv4_Hex($ip)=".sprintf('%d',isValidIPv4_Hex($ip))."<br/>\r\n";
echo "isValidIPv4HTML($ip) ".isValidIPv4HTML($ip)."<br/>\r\n";
?>