-
-
/*--------------------------- -----------------------
- ip2address [qqwry.dat]
- --------------- -----------------------------------*/
- class ip {
- var $fh; //IP資料庫檔案句柄
- var $first; //第一個索引
- var $last; //最後一條索引
- var $total; //索引總數
- //建構子
- function __construct() {
- $this->fh = fopen('qqwry.dat', 'rb'); //qqwry.dat檔案
- $this->first = $this->getLong4( );
- $this->last = $this->getLong4();
- $this->total = ($this->last - $this->first) / 7; //每個索引7位元組
- }
- //檢查IP合法性
- function checkIp($ip) {
- $arr = explode('.',$ip);
- if(count($arr ) !=4 ) {
- return false;
- } else {
- for ($i=0; $i if ($arr[$i] '255') {
- return false;
- }
- }
- }
- return true;
- }
- function getLong4( ) {
- //讀取little-endian編碼的4個位元組轉換為長整數數
- $result = unpack('Vlong', fread($this->fh, 4));
- return $result['long'];
- }
- function getLong3() {
- //讀取little-endian編碼的3個位元組轉換為長整數型數
- $result = unpack('Vlong', fread($this->fh, 3).chr(0));
- return $result['long'];
- }
- //查詢資訊
- function getInfo($data = "") {
- $char = fread($this->fh, 1);
- while (ord($char) != 0) { //國家地區資訊以0結束
- $data .= $char;
- $char = fread($this->fh, 1);
- }
- return $data;
- } bbs.it-home.org
- //查詢地區資訊
- function getArea() {
- $byte = fread($this->fh, 1); //標誌位元組
- switch (ord($byte)) {
- case 0: $area = ''; break; //沒有地區資訊
- case 1: //地區被重定向
- fseek($this->fh, $this->getLong3());
- $area = $this->getInfo(); break;
- case 2: //地區被重定向
- fseek($this->fh, $this->getLong3());
- $area = $this->getInfo(); break;
- default: $area = $this->getInfo($byte); break; //地區沒有被重新導向
- }
- return $area ;
- }
- function ip2addr($ip) {
- if(!$this -> checkIp($ip)){
- return false;
- }
- $ip = pack( 'N', intval(ip2long($ip)));
- //二分查找
- $l = 0;
- $r = $this->total;
- while($l $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 $r = $m - 1;
- } else {
- if ($ip > $endip) { //使用者的IP大於中間索引的結束IP位址時
- $l = $m 1;
- } else { //使用者IP在中間索引的IP範圍內時
- $findip = $this->first $m * 7;
- break;
- }
- }
- }
- //查詢國家地區資訊
- fseek($this->fh, $findip);
- $location['beginip'] = long2ip($this->getLong4()); / /用戶IP所在範圍的開始位址
- $offset = $this->getlong3();
- fseek($this->fh, $offset);
- $location['endip'] = long2ip( $this->getLong4()); //使用者IP所在範圍的結束位址
- $byte = fread($this->fh, 1); //標誌位元組
- switch (ord($byte) ) {
- case 1: //國家和區域資訊都被重定向
- $countryOffset = $this->getLong3(); //重定向位址
- fseek($this->fh, $countryOffset );
- $byte = fread($this->fh, 1); //標誌位元組
- switch (ord($byte)) {
- case 2: //國家資訊被二次重定向
- fseek($this->fh, $this->getLong3());
- $location['country'] = $this->getInfo();
- fseek($this->fh , $countryOffset 4);
- $location['area'] = $this->getArea();
- break;
- default: //國家資訊沒有二次重新導向
- $location ['country'] = $this->getInfo($byte);
- $location['area'] = $this->getArea();
- break;
- }
- break;
- case 2: //國家資訊被重新導向
- fseek($this->fh, $this->getLong3());
- $location['country'] = $this->getInfo() ;
- fseek($this->fh, $offset 8);
- $location['area'] = $this->getArea();
- break;
- default: //國家信息沒有被重新導向
- $location['country'] = $this->getInfo($byte);
- $location['area'] = $this->getArea();
- break;
- }
- //gb2312 to utf-8(去除無訊息時顯示的CZ88.NET)
- foreach ($location as $k => $v) {
- $location[$k] = str_replace(' CZ88.NET','',iconv('gb2312', 'utf-8', $v));
- }
- return $location;
- }
- //析構函數
- function __destruct() {
- fclose($this->fh);
- }
- }
- $ip = new ip();
- $addr = $ip -> ip2addr(' IP位址');
- print_r($addr);
- ?>
複製程式碼
|