<?php
class IpSearch {
private $firstStartIpOffset; private $lastStartIpOffset; private $prefixStartOffset; private $prefixEndOffset; private $ipCount; private $prefixCount; private $fp;
private $prefix_array = array();
function __construct($database) {
$this->fp = @fopen($database, 'rb');
$buf = $this->read($this->fp, 0, 16);
$this->firstStartIpOffset = $this->BytesToLong($buf[0], $buf[1], $buf[2], $buf[3]);
$this->lastStartIpOffset = $this->BytesToLong($buf[4], $buf[5], $buf[6], $buf[7]);
$this->prefixStartOffset = $this->BytesToLong($buf[8], $buf[9], $buf[10], $buf[11]);
$this->prefixEndOffset = $this->BytesToLong($buf[12], $buf[13], $buf[14], $buf[15]);
$this->ipCount = floor(($this->lastStartIpOffset - $this->firstStartIpOffset) / 12) + 1;
$this->prefixCount = floor(($this->prefixEndOffset - $this->prefixStartOffset) / 9) + 1;
$pref_buf = $this->read($this->fp, $this->prefixStartOffset, $this->prefixCount * 9);
for ($k = 0; $k < $this->prefixCount; $k++) {
$i = $k * 9;
$start_index = $this->BytesToLong($pref_buf[1 + $i], $pref_buf[2 + $i], $pref_buf[3 + $i], $pref_buf[4 + $i]);
$end_index = $this->BytesToLong($pref_buf[5 + $i], $pref_buf[6 + $i], $pref_buf[7 + $i], $pref_buf[8 + $i]);
$this->prefix_array[ord($pref_buf[$i]) ] = array('start_index' => $start_index,
'end_index' => $end_index
);
}
}
function __destruct() {
if ($this->fp !== null) {
fclose($this->fp);
}
}
function get($ip_address) {
if ($ip_address == '') return;
$high = 0;
$low = 0;
$startIp = 0;
$endIp = 0;
$local_offset = 0;
$local_length = 0;
$prefix = explode('.', $ip_address) [0];
$ipNum = $this->ip2uint($ip_address);
if (array_key_exists($prefix, $this->prefix_array)) {
$index = $this->prefix_array[$prefix];
$low = $index['start_index'];
$high = $index['end_index'];
} else {
return "";
}
$left = $low == $high ? $low : $this->BinarySearch($low, $high, $ipNum);
$this->GetIndex($left, $startIp, $endIp, $local_offset, $local_length);
if (($startIp <= $ipNum) && ($endIp >= $ipNum)) {
return $this->GetLocal($local_offset, $local_length);
} else {
return "";
}
}
function BinarySearch($low, $high, $k) {
$M = 0;
while ($low <= $high) {
$mid = floor(($low + $high) / 2);
$endipNum = $this->GetEndIp($mid);
if ($endipNum >= $k) {
$M = $mid;
if ($mid == 0) {
break;
}
$high = $mid - 1;
} else $low = $mid + 1;
}
return $M;
}
function GetIndex($left, &$startip, &$endip, &$local_offset, &$local_length) {
$left_offset = $this->firstStartIpOffset + ($left * 12);
$buf = $this->read($this->fp, $left_offset, 12);
$startip = $this->BytesToLong($buf[0], $buf[1], $buf[2], $buf[3]);
$endip = $this->BytesToLong($buf[4], $buf[5], $buf[6], $buf[7]);
$r3 = (ord($buf[8]) << 0 | ord($buf[9]) << 8 | ord($buf[10]) << 16);
if ($r3 < 0) $r3 += 4294967296; $local_offset = $r3;
$local_length = ord($buf[11]);
}
function getEndIp($left) {
$left_offset = $this->firstStartIpOffset + ($left * 12) + 4;
$buf = $this->read($this->fp, $left_offset, 4);
return $this->BytesToLong($buf[0], $buf[1], $buf[2], $buf[3]);
}
function GetLocal($local_offset, $local_length) {
return $this->read($this->fp, $local_offset, $local_length);
}
function read($stream, $offset, $numberOfBytes) {
if (fseek($stream, $offset) == 0) {
$value = fread($stream, $numberOfBytes);
return $value;
}
}
function ip2uint($strIP) {
$lngIP = ip2long($strIP);
if ($lngIP < 0) {
$lngIP += 4294967296; }
return $lngIP;
}
function BytesToLong($a, $b, $c, $d) {
$iplong = (ord($a) << 0) | (ord($b) << 8) | (ord($c) << 16) | (ord($d) << 24);
if ($iplong < 0) {
$iplong += 4294967296; } ;
return $iplong;
}
}
header("Content-type: text/json; charset=utf-8");
$ip = $_GET['ip'];
$reader = new IpSearch('qqzeng.dat');
$r = $reader->get($ip);
list($area, $country, $province, $city, $district, $isp, $areacode, $en, $cc, $lng, $lat) = explode("|", $r);
$obj = (Object)null;
$region = $province;
if ($province == '' && $city == '') {
$region = $country;
}
if ($province == $city) {
$region = $country;
}
if (empty($province)) {
$region = $area;
$city = $country;
}
if (empty($city)) {
$region = $country;
$city = $province;
}
if (empty($isp)) {
$region = $area;
$city = '';
$isp = $country;
}
if ($isp=='保留') {
$region = '本地';
$city = '';
$isp = '内网';
}
$obj->region = $region;
$obj->city = $city . ',' ;
$obj->isp = $isp;
$json['data'] = $obj;
echo json_encode($json, JSON_UNESCAPED_UNICODE);
?>