php 本地mysql 代码_基于本地数据库的 IP 地址查询 PHP 源码
* 純真 IP 數(shù)據(jù)庫查詢
*
* 參考資料:
* - 純真 IP 數(shù)據(jù)庫 http://www.cz88.net/ip/
* - PHP 讀取純真IP地址數(shù)據(jù)庫 http://ju.outofmemory.cn/entry/42500
* - 純真 IP 數(shù)據(jù)庫自動更新文件教程 https://www.22vd.com/40035.html
* - IpLocation https://github.com/nauxliu/IpLocation/
* - 基于本地數(shù)據(jù)庫的 IP 地址查詢 PHP 源碼 https://mkblog.cn/?p=1951
*
* 使用示例:
* $ip = new IPQuery();
* $addr = $ip->query('IP地址');
* print_r($addr);*/
classIPQuery {private $fh; //IP數(shù)據(jù)庫文件句柄
private $first; //第一條索引
private $last; //最后一條索引
private $total; //索引總數(shù)
private $dbFile = __DIR__ . DIRECTORY_SEPARATOR . 'qqwry.dat'; //純真 IP 數(shù)據(jù)庫文件存放路徑
private $dbExpires = 86400 * 10; //數(shù)據(jù)庫文件有效期(10天)如無需自動更新 IP 數(shù)據(jù)庫,請將此值改為 0
// 構造函數(shù)
function__construct() {//IP 數(shù)據(jù)庫文件不存在或已過期,則自動獲取
if(!file_exists($this->dbFile) || ($this->dbExpires && ((time() - filemtime($this->dbFile)) > $this->dbExpires))) {$this->update();
}
}//忽略超時
private functionignore_timeout() {
@ignore_user_abort(true);
@ini_set('max_execution_time', 48 * 60 * 60);
@set_time_limit(48 * 60 * 60); //set_time_limit(0) 2day
@ini_set('memory_limit', '4000M');//4G;
}//讀取little-endian編碼的4個字節(jié)轉化為長整型數(shù)
private functiongetLong4() {$result = unpack('Vlong', fread($this->fh, 4));return $result['long'];
}//讀取little-endian編碼的3個字節(jié)轉化為長整型數(shù)
private functiongetLong3() {$result = unpack('Vlong', fread($this->fh, 3).chr(0));return $result['long'];
}//查詢位置信息
private function getPos($data = '') {$char = fread($this->fh, 1);while (ord($char) != 0) { //地區(qū)信息以 0 結束
$data .= $char;$char = fread($this->fh, 1);
}return $data;
}//查詢運營商
private functiongetISP() {$byte = fread($this->fh, 1); //標志字節(jié)
switch (ord($byte)) {case 0: $area = ''; break; //沒有相關信息
case 1: //被重定向
fseek($this->fh, $this->getLong3());$area = $this->getPos(); break;case 2: //被重定向
fseek($this->fh, $this->getLong3());$area = $this->getPos(); break;default: $area = $this->getPos($byte); break; //沒有被重定向
}return $area;
}//檢查 IP 格式是否正確
public function checkIp($ip) {$arr = explode('.', $ip);if(count($arr) != 4) return false;for ($i = 0; $i < 4; $i++) {if ($arr[$i] < '0' || $arr[$i] > '255') {return false;
}
}return true;
}//查詢 IP 地址
public function query($ip) {if(!$this->checkIp($ip)) {return false;
}$this->fh = fopen($this->dbFile, 'rb');$this->first = $this->getLong4();$this->last = $this->getLong4();$this->total = ($this->last - $this->first) / 7; //每條索引7字節(jié)
$ip = pack('N', intval(ip2long($ip)));//二分查找 IP 位置
$l = 0;$r = $this->total;while($l <= $r) {$m = floor(($l + $r) / 2); //計算中間索引
fseek($this->fh, $this->first + $m * 7);$beginip = strrev(fread($this->fh, 4)); //中間索引的開始IP地址
fseek($this->fh, $this->getLong3());$endip = strrev(fread($this->fh, 4)); //中間索引的結束IP地址
if ($ip < $beginip) { //用戶的IP小于中間索引的開始IP地址時
$r = $m - 1;
}else{if ($ip > $endip) { //用戶的IP大于中間索引的結束IP地址時
$l = $m + 1;
}else { //用戶IP在中間索引的IP范圍內時
$findip = $this->first + $m * 7;break;
}
}
}//查找 IP 地址段
fseek($this->fh, $findip);$location['beginip'] = long2ip($this->getLong4()); //用戶IP所在范圍的開始地址
$offset = $this->getlong3();fseek($this->fh, $offset);$location['endip'] = long2ip($this->getLong4()); //用戶IP所在范圍的結束地址
// 查找 IP 信息
$byte = fread($this->fh, 1); //標志字節(jié)
switch (ord($byte)) {case 1: //都被重定向
$countryOffset = $this->getLong3(); //重定向地址
fseek($this->fh, $countryOffset);$byte = fread($this->fh, 1); //標志字節(jié)
switch (ord($byte)) {case 2: //信息被二次重定向
fseek($this->fh, $this->getLong3());$location['pos'] = $this->getPos();fseek($this->fh, $countryOffset + 4);$location['isp'] = $this->getISP();break;default: //信息沒有被二次重定向
$location['pos'] = $this->getPos($byte);$location['isp'] = $this->getISP();break;
}break;case 2: //信息被重定向
fseek($this->fh, $this->getLong3());$location['pos'] = $this->getPos();fseek($this->fh, $offset + 8);$location['isp'] = $this->getISP();break;default: //信息沒有被重定向
$location['pos'] = $this->getPos($byte);$location['isp'] = $this->getISP();break;
}//信息轉碼處理
foreach ($location as $k => $v) {
//$location[$k] = iconv('gb2312','utf-8',$v); //---這里一定要注意字符集$location[$k] = iconv('GBK', 'utf-8', $v);$location[$k] = preg_replace(array('/^.*CZ88\.NET.*$/isU', '/^.*純真.*$/isU', '/^.*日IP數(shù)據(jù)/'), '', $location[$k]);$location[$k] = htmlspecialchars($location[$k]);
}return $location;
}//更新數(shù)據(jù)庫 https://www.22vd.com/40035.html
public functionupdate() {$this->ignore_timeout();$copywrite = file_get_contents('http://update.cz88.net/ip/copywrite.rar');$qqwry = file_get_contents('http://update.cz88.net/ip/qqwry.rar');$key = unpack('V6', $copywrite)[6];for($i = 0; $i < 0x200; $i++) {$key *= 0x805;$key ++;$key = $key & 0xFF;$qqwry[$i] = chr(ord($qqwry[$i]) ^ $key);
}$qqwry = gzuncompress($qqwry);file_put_contents($this->dbFile, $qqwry);
}//析構函數(shù)
function__destruct() {if($this->fh) {fclose($this->fh);
}$this->fp = null;
}
}
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的php 本地mysql 代码_基于本地数据库的 IP 地址查询 PHP 源码的全部內容,希望文章能夠幫你解決所遇到的問題。