プログラム
QQwry.dat 形式の分析と IP ロケーションのクエリ PHP プログラム
Strongc 著 http://strongc.51.net/d2x/
転載する際は私の名前とホームページのリンクを削除しないでください。ありがとうございます!
以前のハント データベースは大きすぎて、長い間更新されていませんでした。
そこで、QQwry.dat ファイルを使用して IP アドレスを照会することを考えました。QQwry.dat は多くの場所 (通常は IP アドレスの QQ 圧縮パッケージ内) にあります。
しかし、関連する形式情報はありません。
このファイルの形式を分析したところ、現在の結論は次のとおりです:
形式は次のとおりです:
A.ファイルヘッダー、合計 8 バイト
B.複数のレコードの最終住所 + 国と地域
C.小さいものから大きいものへと配列された複数の開始アドレス + 終了アドレス オフセット、固定長、7 バイト
D。すべての IP は 4 バイトの整数で記録され、Intel の順序に従い、上位バイトが最後、下位バイトが最初になります。
E。すべてのオフセットは絶対オフセットであり、ファイルの先頭から計算されます。
F.ファイル ヘッダーで使用される 2 つの 4 バイト オフセットを除き、残りのオフセットは 3 バイトを使用します。
G.すべてのオフセットも、最初に低ビット、最後に高ビットです
H。いくつかの文字列圧縮技術が使用されています
1.ファイルヘッダー、合計 8 バイト
FirstStartIpOffset:4 最初の開始 IP の絶対オフセット
LastStartIpOffset:4 最後の開始 IP の絶対オフセット
2。開始アドレス + 終了アドレスのオフセット レコード領域
各レコードは 7 バイトで、開始アドレスに従って昇順に配置されます
StartIp:4 開始アドレス、整数形式の IP
EndIpOffset:3 終了アドレスの絶対オフセット
3.終了住所+国+地域レコード領域
EndIP:4
国+地域レコード:不定長
4.国 + 地域のレコード、いくつかの形式で利用可能
4.1.
国文字列、0x0 で終了
地域文字列、0x0 で終了
4.2。
Flag:1 フラグ値: 0x1、その後にローカル レコードがありません
0x2、その後にローカル レコードがあります
s CountryOffset:3 実際の文字列はこのオフセット位置で見つかる必要があります
LocalRec: 固定長ではなく、オプションの値に基づいていますフラグに応じて。このレコードも Country に似ており、圧縮されている可能性があります
4.3 LocalRec 構造体 1
flag:1 このフラグの意味はよくわかりませんが、値は 0x1 または 0x2 です
sLocalOffset:3
4.4 LocalRec 構造体2 つの
sLocal: 可変長のスタイル文字列を持つ通常の C
注: s CountryOffset が指す場所はまだ 4.2 形式のままである可能性があります。なぜこのように設計されているのかはわかりません。
Flagが0x1の場合、s CountryOffsetが指す位置はFlagが0x2になる可能性があります。このとき、LocalRecもここを参照します。
記録されたローカルの場所が 0x2 フラグに遭遇したときの意味がわかりません。
qqwry.datにいくつかのエラーがあるようです。
個別レコード Local は、
0x2,0x0,0x0,0x0 のように記述されます。
ルールに従って、ファイルの先頭から検索する必要がありますが、これらは明らかにファイルの先頭には記録されません。
私はつい最近 PHP を学んだばかりです。笑わないでください。もちろん改善することはできます。忘れずにコピーを私に渡してください。
ネット上にあるコードを参考にしたので、いちいちソースは書きません。
正直、PHPでは変数の型を明示的に指定できないのが頭の痛いところです。
たとえば、ある数値を符号なしの整数にしたいのですが、それが負の符号を持たなければならない場合は、さまざまな記述方法を試さなければなりません...
皆さんはどう思いますか?似たような?
define('QQWRY' , $qqwry_root_path . 'QQwry.dat' ) ;
function IpToInt($Ip) {
$array=explode('.',$Ip);
$Int=($ array[0] * 256*256*256) + ($array[1]*256*256) + ($array[2]*256) + $array[3];
return $Int;
}
function IntToIp($Int) {
$b1=($Int & 0xff000000)>gt;>24;
if ($b1 $b2=($Int & 0x00ff0000)>gt;>16 ;
if ($b2 $b3=($Int & 0x0000ff00)>>8;
if ($b3 $b4= $Int & 0x000000ff;
if ($b4 $Ip=$b1.'.'.$b2.'.'.$b3.'.'.$b4;
return $Ip;
} QClass tqwry {var $ 0 = 0;// 0x02、後続の 3 バイトは国ごとに連絡され、その後にローカル
// その他、国、ローカル、ローカル、同様の圧縮が続きます。複数の参照の可能性があります。
var $fp;
var $FirstStartIp = 0;
var $LastStartIp = 0;
var $EndIpOff = 0;
function getStartIp ($RecNo) {
$offset = $this-> ;FirstStartIp + $RecNo * 7 ;
@fseek ( $this->fp, $offset, SEEK_SET ) ;
$buf = fread ( $this->fp, 7) ) + (ord($buf[5])*256) + (ord($buf[6])* 256*256);
$this->StartIp = ord($buf[0]) + (ord( $buf[1])*256) + (ord($buf) [2])*256*256) + (ord($buf[3])*256*256*256);
return $this->StartIp ;
}
function getEndIp ( ) {
@fseek ( $ this->fp , $this->EndIpOff , SEEK_SET ) ;
$buf = fread ( $this->fp , 5 ) ;
$this ->EndIp = ord($buf[0]) + ( ord($buf[1])*256) + (ord($buf[2])*256*256) + (ord($buf[3] :) this ->国フラグ ) {
//エコー sprintf( 'EndIpOffset=(% x) ', $ This-& GT;
$ this-& gt; (1 == $ This- & GT; Endipoff+8 );
-> ローカル= $this->getFlagStr ( ftell ( $this->fp )) @fseek ( $this->fp , $ offset , SEEK_SET ) ;
}
; $offset = ord($buf[0]) + (ord($buf[1])*256) + (ord($buf[2])* 256*256);
}else{
break ;
}
}
if ( $offset < 12 )
return '';
@fseek($this->fp , $offset , SEEK_SET ) ;
return $this->getStr( );
}
関数 getStr ( )
{
$str = '' ;
while ( 1 ) {
$c = fgetc ( $this->fp ) ;
if ( ord ( $c[0] ) == 0 )
休憩 ;
$ str .= $c ;
}
return $str ;
}
function qqwry ($dotip) {
$nRet;
$ip = IpToInt ( $dotip );
$this->fp= @ fopen(QQWRY, "rb");
if ($this->fp == NULL) {
$szLocal= "OpenFileError";
return 1;
}
@fseek ( $this->fp , 0 , SEEK_SET ) ;
$buf = fread ( $this->fp , 8 ) ;
$this->FirstStartIp = ord($buf[0]) + (ord($buf[1])*256) + (ord($buf[2])*256*256) + (ord($buf[3])*256*256*256);
$this->LastStartIp = ord($buf[4]) + ( ord($buf[5])*256) + (ord($buf[6])*256*256) + (ord($buf[7])*256*256*256);
$RecordCount= フロア( ( $this->LastStartIp - $this->FirstStartIp ) / 7);
if ($RecordCount $this-> Country = "FileDataError";
fclose ( $this-> ;fp ) ;
return 2 ;
}
$RangB= 0;
$RangE= $RecordCount;
// ...
while ($Rang B< $RangE-1)
{
$RecNo= Floor(($RangB + $RangE) / 2);
$this->getStartIp ( $RecNo ) ;
if ( $ip == t;スタートIp )
{
$RangB = $RecNo ;
break ;
}
if ( $ip > $this->StartIp )
$RangB= $RecNo;
else
$RangE= $RecNo;
}
$this->getStartIp ( $RangB ) ; ) ){
..
$this->Local = str_replace("(台湾を解放しなければなりません!!!)", "", $this->Local) ; -> Country = 'Unknown';
function ip2location ( $ip )
{
$wry = new TQQwry ;
$nRet = $wry->qqwry ( $ip );
//$nRet を使用すると、私は彼に、未知の IP をテーブルに自動的に記録するように依頼しました。これ以上コードを書く必要はありません。
$wry->国.$wry->ローカルを返します ;
}