/**
* parse ip use http://www.cz88.net database
*/
class QQIp
{
protected $fp;
function __construct($file)
{
if (! is_file($file)) {
user_error('file is not found, file=' . $file, E_USER_ERROR);
}
$this->fp = fopen($file, 'rb');
if (! is_resource($this->fp)) {
user_error('can not open file, file=' . $file, E_USER_ERROR);
}
}
/**
*
* @param string $ip
*/
function parse($ip)
{
$fp = $this->fp;
$ip = explode('.', $ip);
$ipNum = $ip[0] * 16777216 + $ip[1] * 65536 + $ip[2] * 256 + $ip[3];
// get start position and end position from db
$DataBegin = fread($fp, 4);
$DataEnd = fread($fp, 4);
$ipbegin = implode('', unpack('L', $DataBegin));
if ($ipbegin < 0)
$ipbegin += pow(2, 32);
$ipend = implode('', unpack('L', $DataEnd));
if ($ipend < 0)
$ipend += pow(2, 32);
$ipAllNum = ($ipend - $ipbegin) / 7 + 1;
$BeginNum = 0;
$EndNum = $ipAllNum;
$ip1num = null;
$ip2num = null;
// find ip from index use dichotomy
while ($ip1num > $ipNum || $ip2num < $ipNum) {
$Middle = intval(($EndNum + $BeginNum) / 2);
// set the pointer to index position and read 4 byte
fseek($fp, $ipbegin + 7 * $Middle);
$ipData1 = fread($fp, 4);
if (strlen($ipData1) < 4) {
fclose($fp);
return '- System Error';
}
// convert value to long.Add 2^32 if value is negative
$ip1num = implode('', unpack('L', $ipData1));
if ($ip1num < 0)
$ip1num += pow(2, 32);
// change end position if value greate than ip address
if ($ip1num > $ipNum) {
$EndNum = $Middle;
continue;
}
// get next index
$DataSeek = fread($fp, 3);
if (strlen($DataSeek) < 3) {
fclose($fp);
return '- System Error';
}
$DataSeek = implode('', unpack('L', $DataSeek . chr(0)));
fseek($fp, $DataSeek);
$ipData2 = fread($fp, 4);
if (strlen($ipData2) < 4) {
fclose($fp);
return '- System Error';
}
$ip2num = implode('', unpack('L', $ipData2));
if ($ip2num < 0)
$ip2num += pow(2, 32);
// not found
if ($ip2num < $ipNum) {
if ($Middle == $BeginNum) {
fclose($fp);
return '- Unknown';
}
$BeginNum = $Middle;
}
}
$ipFlag = fread($fp, 1);
if ($ipFlag == chr(1)) {
$ipSeek = fread($fp, 3);
if (strlen($ipSeek) < 3) {
fclose($fp);
return '- System Error';
}
$ipSeek = implode('', unpack('L', $ipSeek . chr(0)));
fseek($fp, $ipSeek);
$ipFlag = fread($fp, 1);
}
if ($ipFlag == chr(2)) {
$AddrSeek = fread($fp, 3);
if (strlen($AddrSeek) < 3) {
fclose($fp);
return '- System Error';
}
$ipFlag = fread($fp, 1);
if ($ipFlag == chr(2)) {
$AddrSeek2 = fread($fp, 3);
if (strlen($AddrSeek2) < 3) {
fclose($fp);
return '- System Error';
}
$AddrSeek2 = implode('', unpack('L', $AddrSeek2 . chr(0)));
fseek($fp, $AddrSeek2);
} else {
fseek($fp, - 1, SEEK_CUR);
}
while (($char = fread($fp, 1)) != chr(0))
$ipAddr2 .= $char;
$AddrSeek = implode('', unpack('L', $AddrSeek . chr(0)));
fseek($fp, $AddrSeek);
while (($char = fread($fp, 1)) != chr(0))
$ipAddr1 .= $char;
} else {
fseek($fp, - 1, SEEK_CUR);
while (($char = fread($fp, 1)) != chr(0))
$ipAddr1 .= $char;
$ipFlag = fread($fp, 1);
if ($ipFlag == chr(2)) {
$AddrSeek2 = fread($fp, 3);
if (strlen($AddrSeek2) < 3) {
fclose($fp);
return '- System Error';
}
$AddrSeek2 = implode('', unpack('L', $AddrSeek2 . chr(0)));
fseek($fp, $AddrSeek2);
} else {
fseek($fp, - 1, SEEK_CUR);
}
while (($char = fread($fp, 1)) != chr(0))
$ipAddr2 .= $char;
}
fclose($fp);
if (preg_match('/http/i', $ipAddr2)) {
$ipAddr2 = '';
}
$ipaddr = "$ipAddr1 $ipAddr2";
$ipaddr = preg_replace('/CZ88\.NET/is', '', $ipaddr);
$ipaddr = preg_replace('/^\s*/is', '', $ipaddr);
$ipaddr = preg_replace('/\s*$/is', '', $ipaddr);
if (preg_match('/http/i', $ipaddr) || $ipaddr == '') {
$ipaddr = '- Unknown';
}
$ipaddr = mb_convert_encoding($ipaddr, 'utf-8', 'GBK');
return $ipaddr;
}
function __destruct()
{
fclose($this->fp);
}
}