这几天正好研究了一下纯真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”
根据你的具体情况修改一下就可以了。
===
喜爱孤独者,非神即兽。 —— 亚里士多德