Now, 19 Apr 2011, CentOS still only brings PHP 5.1 with it, while PHP 5.3 is already there.

Today I want to use the filter extension which exists from PHP 5.2

To filter IP, there is lots of regular expressions (although they may not be tidy). But with the requirement of "filter private or reserved IP", only using regular expressions seems to be difficult.

 

So I downloaded the source code of PHP 5.3.6 and transformed the functions of filtering IP addresses into PHP (from C).
I pasted them here and hope someone will find it useful when they have to use PHP 5.1 also.

 

validateIP($addr, $filters = 0) returns input if validated, false otherwise.

validateIPv4($str, &$ip, $filters = 0) returns true if validated, false otherwise. It will try store parsed IP parts into the $ip parameter.
validateIPv6($str, $filters = 0) returns true if validated, false otherwise.
The optional $filters parameter in each of the 3 functions can be FILTER_FLAG_NO_PRIV_RANGE and/or FILTER_FLAG_NO_RES_RANGE.

Usage Example:

filter_var($str, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) (In PHP 5.3)

will be used as

validateIP($str, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) (In my translated code)

 

PHP Code:

if (!defined('FILTER_FLAG_NO_PRIV_RANGE')) {
    define
('FILTER_FLAG_NO_PRIV_RANGE', 0x800000);
}
if (!defined('FILTER_FLAG_NO_RES_RANGE')) {
    define
('FILTER_FLAG_NO_RES_RANGE', 0x400000);
}
function validateIPv4($str, &$ip, $filters = 0) {
    $n
= 0;
   
for ($i = 0, $iMax = strlen($str); $i < $iMax; $i++) {
        $c
= ord($str{$i});
       
if ($c < 48 || $c > 57) {
           
return false;
       
}
        $leading_zero
= $c == 48;
        $m
= 1;
        $num
= $c - 48; $i++;
       
while (1) {
           
if ($i >= $iMax) {
               
break;
           
}
            $c
= ord($str{$i});
           
if ($c >= 48 && $c <= 57) {
                $num
= $num * 10 + $c - 48; $i++;
               
if ($num > 255 || (++$m) > 3) {
                   
return false;
               
}
           
} else {
               
break;
           
}
       
}
       
if ($leading_zero && ($num != 0 || $m > 1)) {
           
return false;
       
}
        $ip
[$n++] = $num;
       
if ($n == 4) {
           
if ($i != $iMax) {
               
return false;
           
} else {
               
if ($filters & FILTER_FLAG_NO_PRIV_RANGE) {
                   
if (($ip[0] == 10) ||
                       
($ip[0] == 172 && ($ip[1] >= 16 && $ip[1] <= 31)) ||
                       
($ip[0] == 192 && $ip[1] == 168)) {
                       
return false;
                   
}
               
}
               
if ($filters & FILTER_FLAG_NO_RES_RANGE) {
                   
if (($ip[0] == 0) ||
                       
($ip[0] == 128 && $ip[1] == 0) ||
                       
($ip[0] == 191 && $ip[1] == 255) ||
                       
($ip[0] == 169 && $ip[1] == 254) ||
                       
($ip[0] == 192 && $ip[1] == 0 && $ip[2] == 2) ||
                       
($ip[0] == 127 && $ip[1] == 0 && $ip[2] == 0 && $ip[3] == 1) ||
                       
($ip[0] >= 224 && $ip[0] <= 255)) {
                       
return false;
                   
}
               
}
               
return true;
           
}
       
} else if ($i >= $iMax) {
           
return false;
       
} if (($c = ord($str{$i})) != 46) {
           
return false;
       
}
   
}
   
return false;
}
function validateIPv6($str, $filters = 0) {
   
if (!_validateIPv6($str)) {
       
return false;
   
}
    $len
= strlen($str);
   
if ($filters & FILTER_FLAG_NO_PRIV_RANGE) {
       
if ($len >= 2 && (!strncasecmp("FC", $str, 2) || !strncasecmp("FD", $str, 2))) {
           
return false;
       
}
   
}
   
if ($filters & FILTER_FLAG_NO_RES_RANGE) {
       
switch ($len) {
           
case 0:
           
case 1:
               
break;
           
case 2:
               
if (!strcmp("::", $str)) {
                   
return false;
               
}
               
break;
           
case 3:
               
if (!strcmp("::1", $str) || !strcmp("5f:", $str)) {
                   
return false;
               
}
               
break;
           
default:
               
if ($len >= 5) {
                   
if (!strncasecmp("fe8", $str, 3) ||
                       
!strncasecmp("fe9", $str, 3) ||
                       
!strncasecmp("fea", $str, 3) ||
                       
!strncasecmp("feb", $str, 3)) {
                       
return false;
                   
}
               
}
               
if (($len >= 9 &&  !strncasecmp("2001:0db8", $str, 9)) ||
                   
($len >= 2 &&  !strncasecmp("5f", $str, 2)) ||
                   
($len >= 4 &&  !strncasecmp("3ff3", $str, 4)) ||
                   
($len >= 8 &&  !strncasecmp("2001:001", $str, 8))) {
                   
return false;
               
}
       
}
   
}
   
return true;
}
function _validateIPv6($str) {
    $strlen
= strlen($str);
    $compressed
= 0;
    $blocks
= 0;
    $ip4elm
= array();
   
if (false === strpos($str, ':')) {
       
return false;
   
}
    $ipv4
= strpos($str, '.');
   
if (false !== $ipv4) {
       
while ($ipv4 > 0 && ord($str{$ipv4 - 1}) != 58) {
            $ipv4
--;
       
}
       
if (!validateIPv4(substr($str, $ipv4), $ip4elm)) {
           
return false;
       
}
        $strlen
= $ipv4;
       
if ($strlen < 2) {
           
return false;
       
}
       
if (ord($str{$ipv4 - 2}) != 58) {
            $strlen
--;
       
}
        $blocks
= 2;
   
}
    $end
= $strlen;
    $i
= 0;
   
while ($i < $end) {
       
if (ord($str{$i}) == 58) {
           
if (++$i >= $end) {
               
return false;
           
}
           
if (ord($str{$i}) == 58) {
               
if ($compressed) {
                   
return false;
               
}
                $blocks
++;
                $compressed
= 1;
               
if (++$i == $end) {
                   
return ($blocks <= 8);
               
}
           
} else if ($i == 1) {
               
return false;
           
}
       
}
        $n
= 0;
       
while (($i < $end) &&
               
((($c = ord($str{$i})) >= 48 && $c <= 57) ||
               
($c >= 97 && $c <= 102) ||
               
($c >= 65 && $c <= 70))) {
            $n
++;
            $i
++;
       
}
       
if ($n < 1 || $n > 4) {
           
return false;
       
}
       
if (++$blocks > 8) {
           
return false;
       
}
   
}
   
return (($compressed && $blocks <= 8) || $blocks == 8);
}
function validateIP($addr, $filters = 0) {
   
if (false !== strpos($addr, ":")) {
       
if (!validateIPv6($addr, $filters)) {
           
return false;
       
}
       
return $addr;
   
} else if (false !== strpos($addr, ".")) {
        $ip
= array();
       
if (!validateIPv4($addr, $ip, $filters)) {
           
return false;
       
}
       
return $addr;
   
} else {
       
return false;
   
}
}