download this file: mkmerge-from-geoip.php view text/plain: mkmerge-from-geoip.php file encoding: UTF-8 [goback]
<?php
##
## san2@2015.07.29: add inet_cidrtonetmask()
## san2@2013.07.xx : new build
##
function inet_aton($ipaddr)
{
  return 
sprintf('%u',ip2long($ipaddr));
}

function 
inet_ntoa($base)
{
  return 
long2ip($base);
}

function 
inet_ntocidr($netmask)
{
  
$netmask trim($netmask);

  
$bits decbin(abs(sprintf('%u',ip2long($netmask))));
  
$cidr strpos($bits,'0') + 0;

  return (
$cidr 0) ? $cidr 32;
}

function 
inet_cidrtonetmask($cidr)
{
  
$cidr = (int)preg_replace('/[^\d]+/','',$cidr);

  if(
$cidr 32) return FALSE;

  
$n floor($cidr/8);
  
$p $cidr 8;
  
$m '';

  for(
$i=1$i<=$n$i++) $m .= '255.';
  if(
$p 0) { $m .= (256-pow(2,8-$p)).'.'$n++; }
  for(
$i=$n$i<4$i++) $m .= '0.';

  
$m preg_replace('/\.$/','',$m);

  return 
$m;
}

## network to pow of bit
##
function inet_ntopow($start$end$nn=0)
{
  static 
$_class_b 2147483648// inet_aton('128.0.0.0') == start of B class
  
static $_class_c 3221225472// inet_aton('192.0.0.0') == start of C class
  
static $_all_bit 4294967295// inet_aton('255.255.255.255')

  
if($start $_class_b$pow 1// is an A class
  
else if($start $_class_c$pow 8// is a B class
  
else
  {
    if(!
$nn)
    {
        
$nn $start $_all_bit $end// network to int
        //$ln = strlen(preg_replace('/^([1]+).*$/','\1',decbin($nn)));
    
}
    
$pow strpos(decbin($nn),"0");
  }

  return 
$pow// integer, pow of bit
}

function 
_find_subnet($start$end$np=0$nn=0)
{
  if(!
$np$np inet_ntopow($start,$end,$nn);

  for(
$l=$np$l<=32$l++)
  {
    
$hbit 32 $l;
    
$host pow(2,$hbit);
    
$tbit str_repeat(1,$l).str_repeat(0,$hbit);
    
$tnet bindec($tbit);
    
$tend $start $host 1;

    
//echo $l."\n";
    
if($tend $end) continue;

    
$tand bindec($tbit sprintf('%032b',$tend));

    if(
$start == $tand)
    {
        
//$nstart = $tend + 1; // change
        
break;
    }
  }

  return array(
$tend,$tnet);
}

function 
mksubnet($start$end)
{
  
$r = array();
  
$np inet_ntopow($start,$end);

  while(
$start <= $end)
  {
    list(
$tend,$mask) = _find_subnet($start,$end,$np);
    
$ps inet_ntoa($start);
    
$pe inet_ntoa($tend);
    
$netmask inet_ntoa($mask);
    
$cidr inet_ntocidr($netmask);
    
$r[] = array($ps,$pe,$netmask,$cidr);
    
$start $tend 1// change
  
}

  return 
$r// array
}

## GeoIP-103_20130618-KR.txt
## file format
## 1.11.0.0        1.11.255.255    16      17498112        17563647        KR      Korea    Republic of
## 1.16.0.0        1.19.255.255    14      17825792        18087935        KR      Korea    Republic of

$file $_SERVER['argv'][1];
if(!
file_exists($file)) exit(1);

$f file($file);
$size sizeof($f);
$netblock = array();

for(
$i=0$i<$size$i++)
{
  
$tmp preg_split('/\s+/',$f[$i]);
  
$netblock[] = array_slice($tmp,0,5);
}

## merge and mksubnet
##
$size sizeof($netblock);
$start NULL;

for(
$i=0$i<$size$i++)
{
  list(,
$endip,,$s,$end) = $netblock[$i];
  
$start $start $start $s;

  if((
$end 1) == $netblock[$i+1][3])
  {
    continue; 
// not next skip
  
}

  
$nn $start inet_aton('255.255.255.255') - $end;
  
$nu $end $start 1// number of host
  
$nnbit decbin($nn);

  if(
preg_match('/^[1]+[0]*$/',$nnbit)) // is subnet
  
{
    
$startip inet_ntoa($start);
    
$endip inet_ntoa($end);
    
$netmask inet_ntoa($nn);
    
$cidr inet_ntocidr($netmask);
    echo 
"$startip\t$endip\t$netmask\t$cidr\n";
  } else
  {
    
$np inet_ntopow($start,$end,$nn);
    
$tmp mksubnet($start,$end,$np,$nn);
    foreach(
$tmp AS $arr)
    {
        list(
$startip,$endip,$netmask,$cidr) = $arr;
        echo 
"$startip\t$endip\t$netmask\t$cidr\n";
    }
  }

  
flush();
  unset(
$start);
}


exit(
0);
?>