<?php 
  
  
if( !function_exists('ftok') ) 
{ 
   function ftok($filename = "", $proj = "") 
   { 
       if( empty($filename) ││ !file_exists($filename) ) 
       { 
           return -1; 
       } 
       else
       { 
           $filename = $filename . (string) $proj; 
           for($key = array(); sizeof($key) < strlen($filename); $key[] = ord(substr($filename, sizeof($key), 1))); 
           return array_sum($key); 
       } 
   } 
} 
  
  
class IpLocation { 
     
     
     
     
     
     var $shm_id; 
     
     
     
     
     
     var $firstip; 
  
     
     
     
     
     
     var $lastip; 
  
     
     
     
     
     
     var $totalip; 
  
     
     
     
     
     
     var $pos; 
  
     
     
     
     
     
     
     function getlong() { 
         
         $result = unpack('Vlong', shmop_read($this->shm_id, $this->pos, 4)); 
         $this->pos += 4; 
         return $result['long']; 
     } 
  
     
     
     
     
     
     
     function getlong3() { 
         
         $result = unpack('Vlong', shmop_read($this->shm_id, $this->pos, 3).chr(0)); 
         $this->pos += 3; 
         return $result['long']; 
     } 
  
     
     
     
     
     
     
     
     function packip($ip) { 
         
         
         return pack('N', intval(ip2long($ip))); 
     } 
  
     
     
     
     
     
     
     
     function getstring($data = "") { 
         $char = shmop_read($this->shm_id, $this->pos++, 1); 
         while (ord($char) > 0) {         
             $data .= $char;             
             $char = shmop_read($this->shm_id, $this->pos++, 1); 
         } 
         return $data; 
     } 
  
     
     
     
     
     
     
     function getarea() { 
         $byte = shmop_read($this->shm_id, $this->pos++, 1); 
         switch (ord($byte)) { 
             case 0:                     
                 $area = ""; 
                 break; 
             case 1: 
             case 2:                     
                 $this->pos = $this->getlong3($this->pos); 
                 $area = $this->getstring(); 
                 break; 
             default:                     
                 $area = $this->getstring($byte); 
                 break; 
         } 
         return $area; 
     } 
  
     
     
     
     
     
     
     
     function getlocation($ip) { 
         if (!$this->shm_id) return null;     
         $location['ip'] = gethostbyname($ip);   
         $ip = $this->packip($location['ip']);   
                                                 
         
         $l = 0;                             
         $u = $this->totalip;                 
         $findip = $this->lastip;             
         while ($l <= $u) {                   
             $i = floor(($l + $u) / 2);       
             $this->pos = $this->firstip + $i * 7; 
             $beginip = strrev(shmop_read($this->shm_id, $this->pos, 4));         
             
             
             if ($ip < $beginip) {       
                 $u = $i - 1;             
             } 
             else { 
                 $this->pos += 4; 
                 $this->pos = $this->getlong3(); 
                 $endip = strrev(shmop_read($this->shm_id, $this->pos, 4));   
                 if ($ip > $endip) {     
                     $l = $i + 1;         
                 } 
                 else {                   
                     $findip = $this->firstip + $i * 7; 
                     break;               
                 } 
             } 
         } 
  
         
         $this->pos = $findip; 
         $location['beginip'] = long2ip($this->getlong());   
         $this->pos = $offset = $this->getlong3(); 
         $location['endip'] = long2ip($this->getlong());     
         $byte = shmop_read($this->shm_id, $this->pos++, 1); 
         switch (ord($byte)) { 
             case 1:                     
                 $this->pos = $countryOffset = $this->getlong3();             
                 $byte = shmop_read($this->shm_id, $this->pos++, 1);         
                 switch (ord($byte)) { 
                     case 2:             
                         $this->pos = $this->getlong3(); 
                         $location['country'] = $this->getstring(); 
                         $this->pos = $countryOffset + 4; 
                         $location['area'] = $this->getarea(); 
                         break; 
                     default:             
                         $location['country'] = $this->getstring($byte); 
                         $location['area'] = $this->getarea(); 
                         break; 
                 } 
                 break; 
             case 2:                     
                 $this->pos = $this->getlong3(); 
                 $location['country'] = $this->getstring(); 
                 $this->pos = $offset + 8; 
                 $location['area'] = $this->getarea(); 
                 break; 
             default:                     
                 $location['country'] = $this->getstring($byte); 
                 $location['area'] = $this->getarea(); 
                 break; 
         } 
         if ($location['country'] == " CZ88.NET") {   
             $location['country'] = "未知"; 
         } 
         if ($location['area'] == " CZ88.NET") { 
             $location['area'] = ""; 
         } 
         return $location; 
     } 
  
     
     
     
     
     
     
     function IpLocation($filename) { 
         $shm_key = ftok($filename, 'R'); 
         if (!($this->shm_id = @shmop_open($shm_key, "a", 0, 0))) {   
             $content = file_get_contents($filename);                 
             $this->shm_id = shmop_open($shm_key, "c", 0644, strlen($content)); 
             shmop_write($this->shm_id, $content, 0);                 
         } 
         $this->pos = 0; 
         $this->firstip = $this->getlong(); 
         $this->lastip = $this->getlong(); 
         $this->totalip = ($this->lastip - $this->firstip) / 7; 
         
         register_shutdown_function(array(&$this, '_IpLocation')); 
     } 
  
     
     
     
     
     function _IpLocation() { 
         shmop_close($this->shm_id); 
     } 
  
     
     
     
     
     
     
     function &getInstance($filename = "QQWry.Dat") { 
         static $instance = null; 
         if (is_null($instance)) { 
             $instance = new IpLocation($filename); 
         } 
         return $instance; 
     } 
} 
?>