awstats:纯真IP数据库查询脚本ip_geo_qqwry.pl

这几天正好研究了一下纯真IP数据库的格式,看着qqwry.pl的代码实在是太乱,所以完全重写了一个perl查询脚本ip_geo_qqwry.pl,配合qqhostinfo插件来查询IP地理位置,看着顺眼多了 :)

代码如下:
20 #/*
21 # *  Jun 14,2009
22 # /
23
24 use Encode;
25
26 sub ipwhere{
27     my $ip      = shift;
28     my @ip      = split(/\./, $ip);
29     my $ip_num  = $ip[0]256
3 + $ip[1]256**2 + $ip[2]256 + $ip[3];
30
31     #my $qqwry_dat
=“${DIR}/plugins/QQWry.Dat”;
32     my $qqwry_dat **=
 “/usr/local/share/ip_geo/QQWry.Dat”;
33     open(INFILE, “$qqwry_dat”);
34     binmode(INFILE);
35
36     my $first_index_of_begin_ip, $last_index_of_begin_ip;
37     sysread(INFILE, $first_index_of_begin_ip, 4);
38     sysread(INFILE, $last_index_of_begin_ip, 4);
39
40     $first_index_of_begin_ip    = unpack(“L”,$first_index_of_begin_ip);
41     $last_index_of_begin_ip     = unpack(“L”,$last_index_of_begin_ip);
42     my $total_index_of_begin_ip = ($last_index_of_begin_ip - $first_index_of_begin_ip)/7 + 1;
43
44     #binary search the begin ip
45     my $begin_index, $end_index = $total_index_of_begin_ip;
46     my $middle_index, $middle_ip, $middle_ip_num;
47
48 #    while(1){
49 #        if($begin_index >= $end_index-1){
50 #            last;
51 #        }
52 #        $middle_index = int(($end_index + $begin_index)/2); 
53 #        seek(INFILE, $first_index_of_begin_ip + $middle_index*7, 0);
54 #        read(INFILE, $middle_ip, 4);
55 #        $middle_ip_num = unpack(“L”, $middle_ip);
56 #        if($ip_num <** $middle_ip_num){
57 #            $end_index **=** $middle_index ;
58 #        } else {
59 #            $begin_index **=** $middle_index ;
60 #        }
61 #    }
62
63     while($begin_index **<** ($end_index -1) ){
64
65         $middle_index **=** int (($end_index + $begin_index)/2); 
66         seek(INFILE, $first_index_of_begin_ip + 7*$middle_index, 0);
67         **read**(INFILE, $middle_ip, 4);
68         $middle_ip_num **=** unpack(“L”, $middle_ip);
69
70         if($ip_num **==** $middle_ip_num){
71             $begin_index **=** $middle_index;
72             last;
73         } elsif ($ip_num **<** $middle_ip_num){
74             $end_index **=** $middle_index;
75         } else {
76             $begin_index **=** $middle_index;
77         }
78     }
79
80     my $end_ip_index_offset, $end_ip, $end_ip_num, $end_ip_offset;
81     $end_ip_index_offset **=** $first_index_of_begin_ip + 7*($begin_index) + 4;
82     seek(INFILE, $end_ip_index_offset, 0);
83     **read**(INFILE, $end_ip_offset, 3);
84     
85     $end_ip_offset **=** unpack(“L”, $end_ip_offset.”\0”);
86     seek(INFILE, $end_ip_offset, 0);
87     **read**(INFILE, $end_ip, 4);
88     $end_ip_num **=** unpack(“L”, $end_ip);
89
90     if($ip_num <= $end_ip_num){
91         my $offset, $position_mode, $geo_country_mode_2_pos**=**0;
92
93         $/**=**”\0”;
94         **read**(INFILE,$position_mode,1);
95
96         #position mode 1  
97         if ($position_mode eq “\1”) {
98             **read**(INFILE,$offset,3);
99             $offset **=** unpack(“L”,$offset.”\0”);
100             seek(INFILE,$offset,0);
101             **read**(INFILE,$position_mode,1);
102         }
103         #position mode 2
104         if ($position_mode eq “\2”) {
105             **read**(INFILE,$offset,3);
106             $geo_country_mode_2_pos **=** tell(INFILE);
107             $offset **=** unpack(“L”,$offset.”\0”);
108             seek(INFILE,$offset,0);
109         } else {
110             seek(INFILE,-1,1);
111         }
112         $ip_geo_country**=<**INFILE**>
;
113
114         if($geo_country_mode_2_pos != 0){
115             seek(INFILE, $geo_country_mode_2_pos, 0);
116         }
117
118         #geo local, geo local only position mode 2
119         read(INFILE,$position_mode,1);
120         if($position_mode eq “\2”) {
121             read(INFILE,$offset,3);
122             $offset = unpack(“L”,$offset.”\0”);
123             seek(INFILE,$offset,0);
124         } else {
125             seek(INFILE,-1,1);
126         }
127         $ip_geo_local=<**INFILE**>;
128     } else{
129         $ip_geo_country = “未知数据”;
130     }
131
132     chomp($ip_geo_country, $ip_geo_local);
133     $/=“\n”;
134     close(INFILE);
135     
136     my $ip_geo_addr=“$ip_geo_country $ip_geo_local”;
137     $ip_geo_addr =~ s/CZ88\.NET//isg;
138     $ip_geo_addr**=**decode(“gbk”,$ip_geo_addr);
139
140     return $ip_geo_addr;
141 }
142
143 1;

将下载的QQWry.Dat拷贝到/usr/local/share/ip_geo/目录下,然后将qqhostinfo.pm需要的IP地址位置查询程序修改为ip_geo_qqwry.pl,我的是这下面这句:
require “/usr/share/awstats/plugins/ip_geo_qqwry.pl”
根据你的具体情况修改一下就可以了。

代码下载

===
[erq]