| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Geo::IP::PurePerl; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
457
|
use strict; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
24
|
|
|
4
|
1
|
|
|
1
|
|
366
|
use FileHandle; |
|
|
1
|
|
|
|
|
7593
|
|
|
|
1
|
|
|
|
|
5
|
|
|
5
|
1
|
|
|
1
|
|
223
|
use File::Spec; |
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
80
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
BEGIN { |
|
8
|
1
|
50
|
|
1
|
|
78
|
if ( $] >= 5.008 ) { |
|
9
|
1
|
|
|
|
|
467
|
require Encode; |
|
10
|
1
|
|
|
|
|
6535
|
Encode->import(qw/ decode /); |
|
11
|
|
|
|
|
|
|
} |
|
12
|
|
|
|
|
|
|
else { |
|
13
|
|
|
|
|
|
|
*decode = sub { |
|
14
|
0
|
|
|
|
|
0
|
local $_ = $_[1]; |
|
15
|
1
|
|
|
1
|
|
463
|
use bytes; |
|
|
1
|
|
|
|
|
7
|
|
|
|
1
|
|
|
|
|
4
|
|
|
16
|
0
|
|
|
|
|
0
|
s/([\x80-\xff])/my $c = ord($1); |
|
|
0
|
|
|
|
|
0
|
|
|
17
|
0
|
0
|
|
|
|
0
|
my $p = $c >= 192 ? 1 : 0; |
|
18
|
0
|
|
|
|
|
0
|
pack ( 'CC' => 0xc2 + $p , $c & ~0x40 ); /ge; |
|
19
|
0
|
|
|
|
|
0
|
return $_; |
|
20
|
0
|
|
|
|
|
0
|
}; |
|
21
|
|
|
|
|
|
|
} |
|
22
|
|
|
|
|
|
|
}; |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
|
|
25
|
1
|
|
|
1
|
|
6
|
use vars qw( @ISA $VERSION @EXPORT $OPEN_TYPE_PATH ); |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
55
|
|
|
26
|
|
|
|
|
|
|
|
|
27
|
1
|
|
|
1
|
|
3
|
use constant GEOIP_CHARSET_ISO_8859_1 => 0; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
46
|
|
|
28
|
1
|
|
|
1
|
|
3
|
use constant GEOIP_CHARSET_UTF8 => 1; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
33
|
|
|
29
|
|
|
|
|
|
|
|
|
30
|
1
|
|
|
1
|
|
3
|
use constant FULL_RECORD_LENGTH => 50; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
33
|
|
|
31
|
1
|
|
|
1
|
|
3
|
use constant GEOIP_COUNTRY_BEGIN => 16776960; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
36
|
|
|
32
|
1
|
|
|
1
|
|
3
|
use constant RECORD_LENGTH => 3; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
30
|
|
|
33
|
1
|
|
|
1
|
|
3
|
use constant GEOIP_STATE_BEGIN_REV0 => 16700000; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
28
|
|
|
34
|
1
|
|
|
1
|
|
2
|
use constant GEOIP_STATE_BEGIN_REV1 => 16000000; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
31
|
|
|
35
|
1
|
|
|
1
|
|
7
|
use constant STRUCTURE_INFO_MAX_SIZE => 20; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
33
|
|
|
36
|
1
|
|
|
1
|
|
3
|
use constant DATABASE_INFO_MAX_SIZE => 100; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
29
|
|
|
37
|
1
|
|
|
1
|
|
3
|
use constant GEOIP_COUNTRY_EDITION => 1; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
34
|
|
|
38
|
1
|
|
|
1
|
|
3
|
use constant GEOIP_REGION_EDITION_REV0 => 7; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
42
|
|
|
39
|
1
|
|
|
1
|
|
5
|
use constant GEOIP_REGION_EDITION_REV1 => 3; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
57
|
|
|
40
|
1
|
|
|
1
|
|
5
|
use constant GEOIP_CITY_EDITION_REV0 => 6; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
61
|
|
|
41
|
1
|
|
|
1
|
|
6
|
use constant GEOIP_CITY_EDITION_REV1 => 2; |
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
50
|
|
|
42
|
1
|
|
|
1
|
|
5
|
use constant GEOIP_ORG_EDITION => 5; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
55
|
|
|
43
|
1
|
|
|
1
|
|
5
|
use constant GEOIP_ISP_EDITION => 4; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
49
|
|
|
44
|
1
|
|
|
1
|
|
5
|
use constant GEOIP_PROXY_EDITION => 8; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
54
|
|
|
45
|
1
|
|
|
1
|
|
6
|
use constant GEOIP_ASNUM_EDITION => 9; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
59
|
|
|
46
|
1
|
|
|
1
|
|
5
|
use constant GEOIP_NETSPEED_EDITION => 10; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
56
|
|
|
47
|
1
|
|
|
1
|
|
6
|
use constant GEOIP_DOMAIN_EDITION => 11; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
54
|
|
|
48
|
1
|
|
|
1
|
|
5
|
use constant SEGMENT_RECORD_LENGTH => 3; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
54
|
|
|
49
|
1
|
|
|
1
|
|
5
|
use constant STANDARD_RECORD_LENGTH => 3; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
61
|
|
|
50
|
1
|
|
|
1
|
|
6
|
use constant ORG_RECORD_LENGTH => 4; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
50
|
|
|
51
|
1
|
|
|
1
|
|
4
|
use constant MAX_RECORD_LENGTH => 4; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
54
|
|
|
52
|
1
|
|
|
1
|
|
4
|
use constant MAX_ORG_RECORD_LENGTH => 300; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
47
|
|
|
53
|
1
|
|
|
1
|
|
4
|
use constant US_OFFSET => 1; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
51
|
|
|
54
|
1
|
|
|
1
|
|
4
|
use constant CANADA_OFFSET => 677; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
45
|
|
|
55
|
1
|
|
|
1
|
|
5
|
use constant WORLD_OFFSET => 1353; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
72
|
|
|
56
|
1
|
|
|
1
|
|
5
|
use constant FIPS_RANGE => 360; |
|
|
1
|
|
|
|
|
15
|
|
|
|
1
|
|
|
|
|
105
|
|
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
$VERSION = '1.26'; |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
require Exporter; |
|
61
|
|
|
|
|
|
|
@ISA = qw(Exporter); |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
# cheat --- try to load Sys::Mmap |
|
64
|
|
|
|
|
|
|
BEGIN { |
|
65
|
1
|
|
|
1
|
|
2
|
eval { |
|
66
|
|
|
|
|
|
|
# wrap into eval again, as workaround for centos / mod_perl issue |
|
67
|
|
|
|
|
|
|
# seems they use $@ without eval somewhere |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
eval "require Sys::Mmap" |
|
70
|
|
|
|
|
|
|
? Sys::Mmap->import |
|
71
|
1
|
50
|
|
|
|
65
|
: do { |
|
72
|
1
|
|
|
|
|
3
|
for (qw/ PROT_READ MAP_PRIVATE MAP_SHARED /) { |
|
73
|
1
|
|
|
1
|
|
5
|
no strict 'refs'; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
70
|
|
|
74
|
3
|
|
|
|
|
5
|
my $unused_stub = $_; # we must use a copy |
|
75
|
3
|
|
|
0
|
|
22
|
*$unused_stub = sub { die 'Sys::Mmap required for mmap support' }; |
|
|
0
|
|
|
|
|
0
|
|
|
76
|
|
|
|
|
|
|
} # for |
|
77
|
|
|
|
|
|
|
}; # do |
|
78
|
1
|
|
|
|
|
4925
|
1; |
|
79
|
|
|
|
|
|
|
}; # eval |
|
80
|
|
|
|
|
|
|
} # begin |
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
sub GEOIP_STANDARD(){0;} |
|
84
|
|
|
|
|
|
|
sub GEOIP_MEMORY_CACHE(){1;} |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
#sub GEOIP_CHECK_CACHE(){2;} |
|
87
|
|
|
|
|
|
|
#sub GEOIP_INDEX_CACHE(){4;} |
|
88
|
|
|
|
|
|
|
sub GEOIP_MMAP_CACHE(){8;} |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
sub GEOIP_UNKNOWN_SPEED(){0;} |
|
91
|
|
|
|
|
|
|
sub GEOIP_DIALUP_SPEED(){1;} |
|
92
|
|
|
|
|
|
|
sub GEOIP_CABLEDSL_SPEED(){2;} |
|
93
|
|
|
|
|
|
|
sub GEOIP_CORPORATE_SPEED(){3;} |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
@EXPORT = qw( GEOIP_STANDARD GEOIP_MEMORY_CACHE GEOIP_MMAP_CACHE |
|
96
|
|
|
|
|
|
|
GEOIP_UNKNOWN_SPEED GEOIP_DIALUP_SPEED GEOIP_CABLEDSL_SPEED GEOIP_CORPORATE_SPEED ); |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
my @countries = ( |
|
99
|
|
|
|
|
|
|
undef,"AP","EU","AD","AE","AF","AG","AI","AL","AM","CW","AO","AQ","AR", |
|
100
|
|
|
|
|
|
|
"AS","AT","AU","AW","AZ","BA","BB","BD","BE","BF","BG","BH","BI","BJ", |
|
101
|
|
|
|
|
|
|
"BM","BN","BO","BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD","CF", |
|
102
|
|
|
|
|
|
|
"CG","CH","CI","CK","CL","CM","CN","CO","CR","CU","CV","CX","CY","CZ", |
|
103
|
|
|
|
|
|
|
"DE","DJ","DK","DM","DO","DZ","EC","EE","EG","EH","ER","ES","ET","FI", |
|
104
|
|
|
|
|
|
|
"FJ","FK","FM","FO","FR","SX","GA","GB","GD","GE","GF","GH","GI","GL", |
|
105
|
|
|
|
|
|
|
"GM","GN","GP","GQ","GR","GS","GT","GU","GW","GY","HK","HM","HN","HR", |
|
106
|
|
|
|
|
|
|
"HT","HU","ID","IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO","JP", |
|
107
|
|
|
|
|
|
|
"KE","KG","KH","KI","KM","KN","KP","KR","KW","KY","KZ","LA","LB","LC", |
|
108
|
|
|
|
|
|
|
"LI","LK","LR","LS","LT","LU","LV","LY","MA","MC","MD","MG","MH","MK", |
|
109
|
|
|
|
|
|
|
"ML","MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV","MW","MX","MY", |
|
110
|
|
|
|
|
|
|
"MZ","NA","NC","NE","NF","NG","NI","NL","NO","NP","NR","NU","NZ","OM", |
|
111
|
|
|
|
|
|
|
"PA","PE","PF","PG","PH","PK","PL","PM","PN","PR","PS","PT","PW","PY", |
|
112
|
|
|
|
|
|
|
"QA","RE","RO","RU","RW","SA","SB","SC","SD","SE","SG","SH","SI","SJ", |
|
113
|
|
|
|
|
|
|
"SK","SL","SM","SN","SO","SR","ST","SV","SY","SZ","TC","TD","TF","TG", |
|
114
|
|
|
|
|
|
|
"TH","TJ","TK","TM","TN","TO","TL","TR","TT","TV","TW","TZ","UA","UG", |
|
115
|
|
|
|
|
|
|
"UM","US","UY","UZ","VA","VC","VE","VG","VI","VN","VU","WF","WS","YE", |
|
116
|
|
|
|
|
|
|
"YT","RS","ZA","ZM","ME","ZW","A1","A2","O1","AX","GG","IM","JE","BL", |
|
117
|
|
|
|
|
|
|
"MF","BQ"); |
|
118
|
|
|
|
|
|
|
my @code3s = ( |
|
119
|
|
|
|
|
|
|
undef,"AP","EU","AND","ARE","AFG","ATG","AIA","ALB","ARM","CUW","AGO","ATA","ARG", |
|
120
|
|
|
|
|
|
|
"ASM","AUT","AUS","ABW","AZE","BIH","BRB","BGD","BEL","BFA","BGR","BHR","BDI","BEN", |
|
121
|
|
|
|
|
|
|
"BMU","BRN","BOL","BRA","BHS","BTN","BVT","BWA","BLR","BLZ","CAN","CCK","COD","CAF", |
|
122
|
|
|
|
|
|
|
"COG","CHE","CIV","COK","CHL","CMR","CHN","COL","CRI","CUB","CPV","CXR","CYP","CZE", |
|
123
|
|
|
|
|
|
|
"DEU","DJI","DNK","DMA","DOM","DZA","ECU","EST","EGY","ESH","ERI","ESP","ETH","FIN", |
|
124
|
|
|
|
|
|
|
"FJI","FLK","FSM","FRO","FRA","SXM","GAB","GBR","GRD","GEO","GUF","GHA","GIB","GRL", |
|
125
|
|
|
|
|
|
|
"GMB","GIN","GLP","GNQ","GRC","SGS","GTM","GUM","GNB","GUY","HKG","HMD","HND","HRV", |
|
126
|
|
|
|
|
|
|
"HTI","HUN","IDN","IRL","ISR","IND","IOT","IRQ","IRN","ISL","ITA","JAM","JOR","JPN", |
|
127
|
|
|
|
|
|
|
"KEN","KGZ","KHM","KIR","COM","KNA","PRK","KOR","KWT","CYM","KAZ","LAO","LBN","LCA", |
|
128
|
|
|
|
|
|
|
"LIE","LKA","LBR","LSO","LTU","LUX","LVA","LBY","MAR","MCO","MDA","MDG","MHL","MKD", |
|
129
|
|
|
|
|
|
|
"MLI","MMR","MNG","MAC","MNP","MTQ","MRT","MSR","MLT","MUS","MDV","MWI","MEX","MYS", |
|
130
|
|
|
|
|
|
|
"MOZ","NAM","NCL","NER","NFK","NGA","NIC","NLD","NOR","NPL","NRU","NIU","NZL","OMN", |
|
131
|
|
|
|
|
|
|
"PAN","PER","PYF","PNG","PHL","PAK","POL","SPM","PCN","PRI","PSE","PRT","PLW","PRY", |
|
132
|
|
|
|
|
|
|
"QAT","REU","ROU","RUS","RWA","SAU","SLB","SYC","SDN","SWE","SGP","SHN","SVN","SJM", |
|
133
|
|
|
|
|
|
|
"SVK","SLE","SMR","SEN","SOM","SUR","STP","SLV","SYR","SWZ","TCA","TCD","ATF","TGO", |
|
134
|
|
|
|
|
|
|
"THA","TJK","TKL","TKM","TUN","TON","TLS","TUR","TTO","TUV","TWN","TZA","UKR","UGA", |
|
135
|
|
|
|
|
|
|
"UMI","USA","URY","UZB","VAT","VCT","VEN","VGB","VIR","VNM","VUT","WLF","WSM","YEM", |
|
136
|
|
|
|
|
|
|
"MYT","SRB","ZAF","ZMB","MNE","ZWE","A1","A2","O1","ALA","GGY","IMN","JEY","BLM", |
|
137
|
|
|
|
|
|
|
"MAF","BES"); |
|
138
|
|
|
|
|
|
|
my @names = ( |
|
139
|
|
|
|
|
|
|
undef,"Asia/Pacific Region","Europe","Andorra","United Arab Emirates", |
|
140
|
|
|
|
|
|
|
"Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia", |
|
141
|
|
|
|
|
|
|
"Curacao","Angola","Antarctica","Argentina","American Samoa", |
|
142
|
|
|
|
|
|
|
"Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina", |
|
143
|
|
|
|
|
|
|
"Barbados","Bangladesh","Belgium","Burkina Faso","Bulgaria", |
|
144
|
|
|
|
|
|
|
"Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam", |
|
145
|
|
|
|
|
|
|
"Bolivia","Brazil","Bahamas","Bhutan","Bouvet Island", |
|
146
|
|
|
|
|
|
|
"Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands", |
|
147
|
|
|
|
|
|
|
"Congo, The Democratic Republic of the","Central African Republic","Congo","Switzerland","Cote D'Ivoire", |
|
148
|
|
|
|
|
|
|
"Cook Islands","Chile","Cameroon","China","Colombia", |
|
149
|
|
|
|
|
|
|
"Costa Rica","Cuba","Cape Verde","Christmas Island","Cyprus", |
|
150
|
|
|
|
|
|
|
"Czech Republic","Germany","Djibouti","Denmark","Dominica", |
|
151
|
|
|
|
|
|
|
"Dominican Republic","Algeria","Ecuador","Estonia","Egypt", |
|
152
|
|
|
|
|
|
|
"Western Sahara","Eritrea","Spain","Ethiopia","Finland", |
|
153
|
|
|
|
|
|
|
"Fiji","Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France", |
|
154
|
|
|
|
|
|
|
"Sint Maarten (Dutch part)","Gabon","United Kingdom","Grenada","Georgia", |
|
155
|
|
|
|
|
|
|
"French Guiana","Ghana","Gibraltar","Greenland","Gambia", |
|
156
|
|
|
|
|
|
|
"Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands", |
|
157
|
|
|
|
|
|
|
"Guatemala","Guam","Guinea-Bissau","Guyana","Hong Kong", |
|
158
|
|
|
|
|
|
|
"Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary", |
|
159
|
|
|
|
|
|
|
"Indonesia","Ireland","Israel","India","British Indian Ocean Territory", |
|
160
|
|
|
|
|
|
|
"Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica", |
|
161
|
|
|
|
|
|
|
"Jordan","Japan","Kenya","Kyrgyzstan","Cambodia", |
|
162
|
|
|
|
|
|
|
"Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of", |
|
163
|
|
|
|
|
|
|
"Kuwait","Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon", |
|
164
|
|
|
|
|
|
|
"Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho", |
|
165
|
|
|
|
|
|
|
"Lithuania","Luxembourg","Latvia","Libya","Morocco", |
|
166
|
|
|
|
|
|
|
"Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia", |
|
167
|
|
|
|
|
|
|
"Mali","Myanmar","Mongolia","Macau","Northern Mariana Islands", |
|
168
|
|
|
|
|
|
|
"Martinique","Mauritania","Montserrat","Malta","Mauritius", |
|
169
|
|
|
|
|
|
|
"Maldives","Malawi","Mexico","Malaysia","Mozambique", |
|
170
|
|
|
|
|
|
|
"Namibia","New Caledonia","Niger","Norfolk Island","Nigeria", |
|
171
|
|
|
|
|
|
|
"Nicaragua","Netherlands","Norway","Nepal","Nauru", |
|
172
|
|
|
|
|
|
|
"Niue","New Zealand","Oman","Panama","Peru", |
|
173
|
|
|
|
|
|
|
"French Polynesia","Papua New Guinea","Philippines","Pakistan","Poland", |
|
174
|
|
|
|
|
|
|
"Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal", |
|
175
|
|
|
|
|
|
|
"Palau","Paraguay","Qatar","Reunion","Romania", |
|
176
|
|
|
|
|
|
|
"Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles", |
|
177
|
|
|
|
|
|
|
"Sudan","Sweden","Singapore","Saint Helena","Slovenia", |
|
178
|
|
|
|
|
|
|
"Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal", |
|
179
|
|
|
|
|
|
|
"Somalia","Suriname","Sao Tome and Principe","El Salvador","Syrian Arab Republic", |
|
180
|
|
|
|
|
|
|
"Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo", |
|
181
|
|
|
|
|
|
|
"Thailand","Tajikistan","Tokelau","Turkmenistan","Tunisia", |
|
182
|
|
|
|
|
|
|
"Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu", |
|
183
|
|
|
|
|
|
|
"Taiwan","Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands", |
|
184
|
|
|
|
|
|
|
"United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines", |
|
185
|
|
|
|
|
|
|
"Venezuela","Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu", |
|
186
|
|
|
|
|
|
|
"Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia", |
|
187
|
|
|
|
|
|
|
"South Africa","Zambia","Montenegro","Zimbabwe","Anonymous Proxy", |
|
188
|
|
|
|
|
|
|
"Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man", |
|
189
|
|
|
|
|
|
|
"Jersey","Saint Barthelemy","Saint Martin","Bonaire, Saint Eustatius and Saba"); |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
# --- unfortunately we do not know the path so we assume the |
|
192
|
|
|
|
|
|
|
# default path /usr/local/share/GeoIP |
|
193
|
|
|
|
|
|
|
# if thats not true, you can set $Geo::IP::PurePerl::OPEN_TYPE_PATH |
|
194
|
|
|
|
|
|
|
# |
|
195
|
|
|
|
|
|
|
sub open_type { |
|
196
|
0
|
|
|
0
|
0
|
|
my ( $class, $type, $flags ) = @_; |
|
197
|
0
|
|
|
|
|
|
my %type_dat_name_mapper = ( |
|
198
|
|
|
|
|
|
|
GEOIP_COUNTRY_EDITION() => 'GeoIP', |
|
199
|
|
|
|
|
|
|
GEOIP_REGION_EDITION_REV0() => 'GeoIPRegion', |
|
200
|
|
|
|
|
|
|
GEOIP_REGION_EDITION_REV1() => 'GeoIPRegion', |
|
201
|
|
|
|
|
|
|
GEOIP_CITY_EDITION_REV0() => 'GeoIPCity', |
|
202
|
|
|
|
|
|
|
GEOIP_CITY_EDITION_REV1() => 'GeoIPCity', |
|
203
|
|
|
|
|
|
|
GEOIP_ISP_EDITION() => 'GeoIPISP', |
|
204
|
|
|
|
|
|
|
GEOIP_ORG_EDITION() => 'GeoIPOrg', |
|
205
|
|
|
|
|
|
|
GEOIP_PROXY_EDITION() => 'GeoIPProxy', |
|
206
|
|
|
|
|
|
|
GEOIP_ASNUM_EDITION() => 'GeoIPASNum', |
|
207
|
|
|
|
|
|
|
GEOIP_NETSPEED_EDITION() => 'GeoIPNetSpeed', |
|
208
|
|
|
|
|
|
|
GEOIP_DOMAIN_EDITION() => 'GeoIPDomain', |
|
209
|
|
|
|
|
|
|
); |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
# backward compatibility for 2003 databases. |
|
212
|
0
|
0
|
|
|
|
|
$type -= 105 if $type >= 106; |
|
213
|
|
|
|
|
|
|
|
|
214
|
0
|
|
|
|
|
|
my $name = $type_dat_name_mapper{$type}; |
|
215
|
0
|
0
|
|
|
|
|
die("Invalid database type $type\n") unless $name; |
|
216
|
|
|
|
|
|
|
|
|
217
|
0
|
|
|
0
|
|
|
my $mkpath = sub { File::Spec->catfile( File::Spec->rootdir, @_ ) }; |
|
|
0
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
my $path = |
|
220
|
|
|
|
|
|
|
defined $Geo::IP::PurePerl::OPEN_TYPE_PATH |
|
221
|
|
|
|
|
|
|
? $Geo::IP::PurePerl::OPEN_TYPE_PATH |
|
222
|
0
|
0
|
|
|
|
|
: do { |
|
223
|
|
|
|
|
|
|
$^O eq 'NetWare' |
|
224
|
|
|
|
|
|
|
? $mkpath->(qw/ etc GeoIP /) |
|
225
|
0
|
0
|
|
|
|
|
: do { |
|
226
|
0
|
0
|
|
|
|
|
$^O eq 'MSWin32' |
|
227
|
|
|
|
|
|
|
? $mkpath->(qw/ GeoIP /) |
|
228
|
|
|
|
|
|
|
: $mkpath->(qw/ usr local share GeoIP /); |
|
229
|
|
|
|
|
|
|
} |
|
230
|
|
|
|
|
|
|
}; |
|
231
|
|
|
|
|
|
|
|
|
232
|
0
|
|
|
|
|
|
my $filename = File::Spec->catfile( $path, $name . '.dat' ); |
|
233
|
0
|
|
|
|
|
|
return $class->open( $filename, $flags ); |
|
234
|
|
|
|
|
|
|
} |
|
235
|
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
sub open { |
|
238
|
0
|
0
|
0
|
0
|
1
|
|
die "Geo::IP::PurePerl::open() requires a path name" |
|
239
|
|
|
|
|
|
|
unless( @_ > 1 and $_[1] ); |
|
240
|
0
|
|
|
|
|
|
my ($class, $db_file, $flags) = @_; |
|
241
|
0
|
|
|
|
|
|
my $fh = FileHandle->new; |
|
242
|
0
|
|
|
|
|
|
my $gi; |
|
243
|
0
|
0
|
|
|
|
|
CORE::open $fh, $db_file or die "Error opening $db_file"; |
|
244
|
0
|
|
|
|
|
|
binmode($fh); |
|
245
|
0
|
0
|
0
|
|
|
|
if ( $flags && ( $flags & ( GEOIP_MEMORY_CACHE | GEOIP_MMAP_CACHE ) ) ) { |
|
246
|
0
|
|
|
|
|
|
my %self; |
|
247
|
|
|
|
|
|
|
|
|
248
|
0
|
0
|
|
|
|
|
if ( $flags & GEOIP_MMAP_CACHE ) { |
|
249
|
0
|
0
|
|
|
|
|
die "Sys::Mmap required for MMAP support" |
|
250
|
|
|
|
|
|
|
unless defined $Sys::Mmap::VERSION; |
|
251
|
0
|
0
|
|
|
|
|
mmap( $self{buf} = undef, 0, PROT_READ, MAP_PRIVATE, $fh ) |
|
252
|
|
|
|
|
|
|
or die "mmap: $!"; |
|
253
|
|
|
|
|
|
|
} |
|
254
|
|
|
|
|
|
|
else { |
|
255
|
0
|
|
|
|
|
|
local $/ = undef; |
|
256
|
0
|
|
|
|
|
|
$self{buf} = <$fh>; |
|
257
|
|
|
|
|
|
|
} |
|
258
|
0
|
|
|
|
|
|
$self{fh} = $fh; |
|
259
|
0
|
|
|
|
|
|
$gi = bless \%self, $class; |
|
260
|
|
|
|
|
|
|
} |
|
261
|
|
|
|
|
|
|
else { |
|
262
|
0
|
|
|
|
|
|
$gi = bless { fh => $fh }, $class; |
|
263
|
|
|
|
|
|
|
} |
|
264
|
0
|
|
|
|
|
|
$gi->_setup_segments(); |
|
265
|
0
|
|
|
|
|
|
return $gi; |
|
266
|
|
|
|
|
|
|
} |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
sub new { |
|
269
|
0
|
|
|
0
|
1
|
|
my ($class, $db_file, $flags) = @_; |
|
270
|
|
|
|
|
|
|
# this will be less messy once deprecated new( $path, [$flags] ) |
|
271
|
|
|
|
|
|
|
# is no longer supported (that's what open() is for) |
|
272
|
|
|
|
|
|
|
|
|
273
|
0
|
|
|
|
|
|
my $def_db_file = '/usr/local/share/GeoIP/GeoIP.dat'; |
|
274
|
0
|
0
|
|
|
|
|
if ($^O eq 'NetWare') { |
|
|
|
0
|
|
|
|
|
|
|
275
|
0
|
|
|
|
|
|
$def_db_file = 'sys:/etc/GeoIP/GeoIP.dat'; |
|
276
|
|
|
|
|
|
|
} elsif ($^O eq 'MSWin32') { |
|
277
|
0
|
|
|
|
|
|
$def_db_file = 'c:/GeoIP/GeoIP.dat'; |
|
278
|
|
|
|
|
|
|
} |
|
279
|
0
|
0
|
|
|
|
|
if ( !defined $db_file ) { |
|
|
|
0
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
# called as new() |
|
281
|
0
|
|
|
|
|
|
$db_file = $def_db_file; |
|
282
|
|
|
|
|
|
|
} elsif ( $db_file =~ /^\d+$/ ) { |
|
283
|
|
|
|
|
|
|
# db_file is GEOIP_MEMORY_CACHE or GEOIP_STANDARD |
|
284
|
|
|
|
|
|
|
# called as new( $flags ) |
|
285
|
0
|
|
|
|
|
|
$flags = $db_file; |
|
286
|
0
|
|
|
|
|
|
$db_file = $def_db_file; |
|
287
|
|
|
|
|
|
|
} # else called as new( $database_filename, [$flags] ); |
|
288
|
|
|
|
|
|
|
|
|
289
|
0
|
|
|
|
|
|
$class->open( $db_file, $flags ); |
|
290
|
|
|
|
|
|
|
} |
|
291
|
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
#this function setups the database segments |
|
293
|
|
|
|
|
|
|
sub _setup_segments { |
|
294
|
0
|
|
|
0
|
|
|
my ($gi) = @_; |
|
295
|
0
|
|
|
|
|
|
my $a = 0; |
|
296
|
0
|
|
|
|
|
|
my $i = 0; |
|
297
|
0
|
|
|
|
|
|
my $j = 0; |
|
298
|
0
|
|
|
|
|
|
my $delim; |
|
299
|
|
|
|
|
|
|
my $buf; |
|
300
|
0
|
|
|
|
|
|
$gi->{_charset} = GEOIP_CHARSET_ISO_8859_1; |
|
301
|
0
|
|
|
|
|
|
$gi->{"databaseType"} = GEOIP_COUNTRY_EDITION; |
|
302
|
0
|
|
|
|
|
|
$gi->{"record_length"} = STANDARD_RECORD_LENGTH; |
|
303
|
|
|
|
|
|
|
|
|
304
|
0
|
|
|
|
|
|
my $filepos = tell($gi->{fh}); |
|
305
|
0
|
|
|
|
|
|
seek($gi->{fh}, -3, 2); |
|
306
|
0
|
|
|
|
|
|
for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) { |
|
307
|
0
|
|
|
|
|
|
read($gi->{fh},$delim,3); |
|
308
|
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
#find the delim |
|
310
|
0
|
0
|
|
|
|
|
if ($delim eq (chr(255).chr(255).chr(255))) { |
|
311
|
0
|
|
|
|
|
|
read($gi->{fh},$a,1); |
|
312
|
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
#read the databasetype |
|
314
|
0
|
|
|
|
|
|
$gi->{"databaseType"} = ord($a); |
|
315
|
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
# backward compatibility for 2003 databases. |
|
317
|
0
|
0
|
|
|
|
|
$gi->{databaseType} -= 105 if $gi->{databaseType} >= 106; |
|
318
|
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
#chose the database segment for the database type |
|
320
|
|
|
|
|
|
|
#if database Type is GEOIP_REGION_EDITION then use database segment GEOIP_STATE_BEGIN |
|
321
|
0
|
0
|
0
|
|
|
|
if ($gi->{"databaseType"} == GEOIP_REGION_EDITION_REV0) { |
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
322
|
0
|
|
|
|
|
|
$gi->{"databaseSegments"} = GEOIP_STATE_BEGIN_REV0; |
|
323
|
|
|
|
|
|
|
} elsif ($gi->{"databaseType"} == GEOIP_REGION_EDITION_REV1) { |
|
324
|
0
|
|
|
|
|
|
$gi->{"databaseSegments"} = GEOIP_STATE_BEGIN_REV1; |
|
325
|
|
|
|
|
|
|
} |
|
326
|
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
#if database Type is GEOIP_CITY_EDITION, GEOIP_ISP_EDITION or GEOIP_ORG_EDITION then |
|
328
|
|
|
|
|
|
|
#read in the database segment |
|
329
|
|
|
|
|
|
|
elsif (($gi->{"databaseType"} == GEOIP_CITY_EDITION_REV0) || |
|
330
|
|
|
|
|
|
|
($gi->{"databaseType"} == GEOIP_CITY_EDITION_REV1) || |
|
331
|
|
|
|
|
|
|
($gi->{"databaseType"} == GEOIP_ORG_EDITION) || |
|
332
|
|
|
|
|
|
|
($gi->{"databaseType"} == GEOIP_ASNUM_EDITION) || |
|
333
|
|
|
|
|
|
|
($gi->{"databaseType"} == GEOIP_DOMAIN_EDITION) || |
|
334
|
|
|
|
|
|
|
($gi->{"databaseType"} == GEOIP_ISP_EDITION)) { |
|
335
|
0
|
|
|
|
|
|
$gi->{"databaseSegments"} = 0; |
|
336
|
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
#read in the database segment for the database type |
|
338
|
0
|
|
|
|
|
|
read($gi->{fh},$buf,SEGMENT_RECORD_LENGTH); |
|
339
|
0
|
|
|
|
|
|
for ($j = 0;$j < SEGMENT_RECORD_LENGTH;$j++) { |
|
340
|
0
|
|
|
|
|
|
$gi->{"databaseSegments"} += (ord(substr($buf,$j,1)) << ($j * 8)); |
|
341
|
|
|
|
|
|
|
} |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
#record length is four for ISP databases and ORG databases |
|
344
|
|
|
|
|
|
|
#record length is three for country databases, region database and city databases |
|
345
|
0
|
0
|
0
|
|
|
|
if ($gi->{"databaseType"} == GEOIP_ORG_EDITION || |
|
|
|
|
0
|
|
|
|
|
|
346
|
|
|
|
|
|
|
$gi->{"databaseType"} == GEOIP_ISP_EDITION || |
|
347
|
|
|
|
|
|
|
$gi->{"databaseType"} == GEOIP_DOMAIN_EDITION) { |
|
348
|
0
|
|
|
|
|
|
$gi->{"record_length"} = ORG_RECORD_LENGTH; |
|
349
|
|
|
|
|
|
|
} |
|
350
|
|
|
|
|
|
|
} |
|
351
|
0
|
|
|
|
|
|
last; |
|
352
|
|
|
|
|
|
|
} else { |
|
353
|
0
|
|
|
|
|
|
seek($gi->{fh}, -4 , 1); |
|
354
|
|
|
|
|
|
|
} |
|
355
|
|
|
|
|
|
|
} |
|
356
|
|
|
|
|
|
|
#if database Type is GEOIP_COUNTY_EDITION then use database segment GEOIP_COUNTRY_BEGIN |
|
357
|
0
|
0
|
0
|
|
|
|
if ($gi->{"databaseType"} == GEOIP_COUNTRY_EDITION || |
|
358
|
|
|
|
|
|
|
$gi->{"databaseType"} == GEOIP_NETSPEED_EDITION) { |
|
359
|
0
|
|
|
|
|
|
$gi->{"databaseSegments"} = GEOIP_COUNTRY_BEGIN; |
|
360
|
|
|
|
|
|
|
} |
|
361
|
0
|
|
|
|
|
|
seek($gi->{fh},$filepos,0); |
|
362
|
0
|
|
|
|
|
|
return $gi; |
|
363
|
|
|
|
|
|
|
} |
|
364
|
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
sub _seek_country { |
|
366
|
0
|
|
|
0
|
|
|
my ($gi, $ipnum) = @_; |
|
367
|
|
|
|
|
|
|
|
|
368
|
0
|
|
|
|
|
|
my $fh = $gi->{fh}; |
|
369
|
0
|
|
|
|
|
|
my $offset = 0; |
|
370
|
|
|
|
|
|
|
|
|
371
|
0
|
|
|
|
|
|
my ($x0, $x1); |
|
372
|
|
|
|
|
|
|
|
|
373
|
0
|
|
|
|
|
|
my $reclen = $gi->{"record_length"}; |
|
374
|
|
|
|
|
|
|
|
|
375
|
0
|
|
|
|
|
|
for (my $depth = 31; $depth >= 0; $depth--) { |
|
376
|
0
|
0
|
|
|
|
|
unless ( exists $gi->{buf} ) { |
|
377
|
0
|
|
|
|
|
|
seek $fh, $offset * 2 * $reclen, 0; |
|
378
|
0
|
|
|
|
|
|
read $fh, $x0, $reclen; |
|
379
|
0
|
|
|
|
|
|
read $fh, $x1, $reclen; |
|
380
|
|
|
|
|
|
|
} else { |
|
381
|
|
|
|
|
|
|
|
|
382
|
0
|
|
|
|
|
|
$x0 = substr($gi->{buf}, $offset * 2 * $reclen, $reclen); |
|
383
|
0
|
|
|
|
|
|
$x1 = substr($gi->{buf}, $offset * 2 * $reclen + $reclen, $reclen); |
|
384
|
|
|
|
|
|
|
} |
|
385
|
|
|
|
|
|
|
|
|
386
|
0
|
|
|
|
|
|
$x0 = unpack("V1", $x0."\0"); |
|
387
|
0
|
|
|
|
|
|
$x1 = unpack("V1", $x1."\0"); |
|
388
|
|
|
|
|
|
|
|
|
389
|
0
|
0
|
|
|
|
|
if ($ipnum & (1 << $depth)) { |
|
390
|
0
|
0
|
|
|
|
|
if ($x1 >= $gi->{"databaseSegments"}) { |
|
391
|
0
|
|
|
|
|
|
$gi->{last_netmask} = 32 - $depth; |
|
392
|
0
|
|
|
|
|
|
return $x1; |
|
393
|
|
|
|
|
|
|
} |
|
394
|
0
|
|
|
|
|
|
$offset = $x1; |
|
395
|
|
|
|
|
|
|
} else { |
|
396
|
0
|
0
|
|
|
|
|
if ($x0 >= $gi->{"databaseSegments"}) { |
|
397
|
0
|
|
|
|
|
|
$gi->{last_netmask} = 32 - $depth; |
|
398
|
0
|
|
|
|
|
|
return $x0; |
|
399
|
|
|
|
|
|
|
} |
|
400
|
0
|
|
|
|
|
|
$offset = $x0; |
|
401
|
|
|
|
|
|
|
} |
|
402
|
|
|
|
|
|
|
} |
|
403
|
|
|
|
|
|
|
|
|
404
|
0
|
|
|
|
|
|
print STDERR "Error Traversing Database for ipnum = $ipnum - Perhaps database is corrupt?"; |
|
405
|
|
|
|
|
|
|
} |
|
406
|
|
|
|
|
|
|
sub charset { |
|
407
|
0
|
|
|
0
|
1
|
|
return $_[0]->{_charset}; |
|
408
|
|
|
|
|
|
|
} |
|
409
|
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
sub set_charset{ |
|
411
|
0
|
|
|
0
|
1
|
|
my ( $gi, $charset ) = @_; |
|
412
|
0
|
|
|
|
|
|
my $old_charset = $gi->{_charset}; |
|
413
|
0
|
|
|
|
|
|
$gi->{_charset} = $charset; |
|
414
|
|
|
|
|
|
|
|
|
415
|
0
|
|
|
|
|
|
return $old_charset; |
|
416
|
|
|
|
|
|
|
} |
|
417
|
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
#this function returns the country code of ip address |
|
419
|
|
|
|
|
|
|
sub country_code_by_addr { |
|
420
|
0
|
|
|
0
|
1
|
|
my ($gi, $ip_address) = @_; |
|
421
|
0
|
0
|
|
|
|
|
return unless $ip_address =~ m!^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$!; |
|
422
|
0
|
|
|
|
|
|
return $countries[$gi->id_by_addr($ip_address)]; |
|
423
|
|
|
|
|
|
|
} |
|
424
|
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
#this function returns the country code3 of ip address |
|
426
|
|
|
|
|
|
|
sub country_code3_by_addr { |
|
427
|
0
|
|
|
0
|
1
|
|
my ($gi, $ip_address) = @_; |
|
428
|
0
|
0
|
|
|
|
|
return unless $ip_address =~ m!^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$!; |
|
429
|
0
|
|
|
|
|
|
return $code3s[$gi->id_by_addr($ip_address)]; |
|
430
|
|
|
|
|
|
|
} |
|
431
|
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
#this function returns the name of ip address |
|
433
|
|
|
|
|
|
|
sub country_name_by_addr { |
|
434
|
0
|
|
|
0
|
1
|
|
my ($gi, $ip_address) = @_; |
|
435
|
0
|
0
|
|
|
|
|
return unless $ip_address =~ m!^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$!; |
|
436
|
0
|
|
|
|
|
|
return $names[$gi->id_by_addr($ip_address)]; |
|
437
|
|
|
|
|
|
|
} |
|
438
|
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
sub id_by_addr { |
|
440
|
0
|
|
|
0
|
0
|
|
my ($gi, $ip_address) = @_; |
|
441
|
0
|
0
|
|
|
|
|
return unless $ip_address =~ m!^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$!; |
|
442
|
0
|
|
|
|
|
|
return $gi->_seek_country(addr_to_num($ip_address)) - GEOIP_COUNTRY_BEGIN; |
|
443
|
|
|
|
|
|
|
} |
|
444
|
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
#this function returns the country code of domain name |
|
446
|
|
|
|
|
|
|
sub country_code_by_name { |
|
447
|
0
|
|
|
0
|
1
|
|
my ($gi, $host) = @_; |
|
448
|
0
|
|
|
|
|
|
my $country_id = $gi->id_by_name($host); |
|
449
|
0
|
|
|
|
|
|
return $countries[$country_id]; |
|
450
|
|
|
|
|
|
|
} |
|
451
|
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
#this function returns the country code3 of domain name |
|
453
|
|
|
|
|
|
|
sub country_code3_by_name { |
|
454
|
0
|
|
|
0
|
1
|
|
my ($gi, $host) = @_; |
|
455
|
0
|
|
|
|
|
|
my $country_id = $gi->id_by_name($host); |
|
456
|
0
|
|
|
|
|
|
return $code3s[$country_id]; |
|
457
|
|
|
|
|
|
|
} |
|
458
|
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
#this function returns the country name of domain name |
|
460
|
|
|
|
|
|
|
sub country_name_by_name { |
|
461
|
0
|
|
|
0
|
1
|
|
my ($gi, $host) = @_; |
|
462
|
0
|
|
|
|
|
|
my $country_id = $gi->id_by_name($host); |
|
463
|
0
|
|
|
|
|
|
return $names[$country_id]; |
|
464
|
|
|
|
|
|
|
} |
|
465
|
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
sub id_by_name { |
|
467
|
0
|
|
|
0
|
0
|
|
my ($gi, $host) = @_; |
|
468
|
0
|
|
|
|
|
|
my $ip_address; |
|
469
|
0
|
0
|
|
|
|
|
if ($host =~ m!^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$!) { |
|
470
|
0
|
|
|
|
|
|
$ip_address = $host; |
|
471
|
|
|
|
|
|
|
} else { |
|
472
|
0
|
|
|
|
|
|
$ip_address = join('.',unpack('C4',(gethostbyname($host))[4])); |
|
473
|
|
|
|
|
|
|
} |
|
474
|
0
|
0
|
|
|
|
|
return unless $ip_address; |
|
475
|
0
|
|
|
|
|
|
return $gi->_seek_country(addr_to_num($ip_address)) - GEOIP_COUNTRY_BEGIN; |
|
476
|
|
|
|
|
|
|
} |
|
477
|
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
#this function returns the city record as a array |
|
479
|
|
|
|
|
|
|
sub get_city_record { |
|
480
|
0
|
|
|
0
|
1
|
|
my ($gi, $host) = @_; |
|
481
|
0
|
|
|
|
|
|
my $ip_address = $gi->get_ip_address($host); |
|
482
|
0
|
0
|
|
|
|
|
return unless $ip_address; |
|
483
|
0
|
|
|
|
|
|
my $record_buf; |
|
484
|
|
|
|
|
|
|
my $record_buf_pos; |
|
485
|
0
|
|
|
|
|
|
my $char; |
|
486
|
0
|
|
|
|
|
|
my $metroarea_combo; |
|
487
|
0
|
|
|
|
|
|
my $record_country_code = ""; |
|
488
|
0
|
|
|
|
|
|
my $record_country_code3 = ""; |
|
489
|
0
|
|
|
|
|
|
my $record_country_name = ""; |
|
490
|
0
|
|
|
|
|
|
my $record_region = ""; |
|
491
|
0
|
|
|
|
|
|
my $record_city = ""; |
|
492
|
0
|
|
|
|
|
|
my $record_postal_code = ""; |
|
493
|
0
|
|
|
|
|
|
my $record_latitude = ""; |
|
494
|
0
|
|
|
|
|
|
my $record_longitude = ""; |
|
495
|
0
|
|
|
|
|
|
my $record_metro_code = ""; |
|
496
|
0
|
|
|
|
|
|
my $record_area_code = ""; |
|
497
|
0
|
|
|
|
|
|
my $str_length = 0; |
|
498
|
0
|
|
|
|
|
|
my $i; |
|
499
|
|
|
|
|
|
|
my $j; |
|
500
|
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
#lookup the city |
|
502
|
0
|
|
|
|
|
|
my $seek_country = $gi->_seek_country(addr_to_num($ip_address)); |
|
503
|
0
|
0
|
|
|
|
|
if ($seek_country == $gi->{"databaseSegments"}) { |
|
504
|
0
|
|
|
|
|
|
return; |
|
505
|
|
|
|
|
|
|
} |
|
506
|
|
|
|
|
|
|
#set the record pointer to location of the city record |
|
507
|
0
|
|
|
|
|
|
my $record_pointer = $seek_country + (2 * $gi->{"record_length"} - 1) * $gi->{"databaseSegments"}; |
|
508
|
|
|
|
|
|
|
|
|
509
|
0
|
0
|
|
|
|
|
unless ( exists $gi->{buf} ) { |
|
510
|
0
|
|
|
|
|
|
seek( $gi->{"fh"}, $record_pointer, 0 ); |
|
511
|
0
|
|
|
|
|
|
read( $gi->{"fh"}, $record_buf, FULL_RECORD_LENGTH ); |
|
512
|
0
|
|
|
|
|
|
$record_buf_pos = 0; |
|
513
|
|
|
|
|
|
|
} |
|
514
|
|
|
|
|
|
|
else { |
|
515
|
0
|
|
|
|
|
|
$record_buf = substr($gi->{buf}, $record_pointer, FULL_RECORD_LENGTH); |
|
516
|
0
|
|
|
|
|
|
$record_buf_pos = 0; |
|
517
|
|
|
|
|
|
|
} |
|
518
|
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
#get the country |
|
520
|
0
|
|
|
|
|
|
$char = ord(substr($record_buf,$record_buf_pos,1)); |
|
521
|
0
|
|
|
|
|
|
$record_country_code = $countries[$char];#get the country code |
|
522
|
0
|
|
|
|
|
|
$record_country_code3 = $code3s[$char];#get the country code with 3 letters |
|
523
|
0
|
|
|
|
|
|
$record_country_name = $names[$char];#get the country name |
|
524
|
0
|
|
|
|
|
|
$record_buf_pos++; |
|
525
|
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
#get the region |
|
527
|
0
|
|
|
|
|
|
$char = ord(substr($record_buf,$record_buf_pos+$str_length,1)); |
|
528
|
0
|
|
|
|
|
|
while ($char != 0) { |
|
529
|
0
|
|
|
|
|
|
$str_length++;#get the length of string |
|
530
|
0
|
|
|
|
|
|
$char = ord(substr($record_buf,$record_buf_pos+$str_length,1)); |
|
531
|
|
|
|
|
|
|
} |
|
532
|
0
|
0
|
|
|
|
|
if ($str_length > 0) { |
|
533
|
0
|
|
|
|
|
|
$record_region = substr($record_buf,$record_buf_pos,$str_length); |
|
534
|
|
|
|
|
|
|
} |
|
535
|
0
|
|
|
|
|
|
$record_buf_pos += $str_length + 1; |
|
536
|
0
|
|
|
|
|
|
$str_length = 0; |
|
537
|
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
#get the city |
|
539
|
0
|
|
|
|
|
|
$char = ord(substr($record_buf,$record_buf_pos+$str_length,1)); |
|
540
|
0
|
|
|
|
|
|
while ($char != 0) { |
|
541
|
0
|
|
|
|
|
|
$str_length++;#get the length of string |
|
542
|
0
|
|
|
|
|
|
$char = ord(substr($record_buf,$record_buf_pos+$str_length,1)); |
|
543
|
|
|
|
|
|
|
} |
|
544
|
0
|
0
|
|
|
|
|
if ($str_length > 0) { |
|
545
|
0
|
|
|
|
|
|
$record_city = substr($record_buf,$record_buf_pos,$str_length); |
|
546
|
|
|
|
|
|
|
} |
|
547
|
0
|
|
|
|
|
|
$record_buf_pos += $str_length + 1; |
|
548
|
0
|
|
|
|
|
|
$str_length = 0; |
|
549
|
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
#get the postal code |
|
551
|
0
|
|
|
|
|
|
$char = ord(substr($record_buf,$record_buf_pos+$str_length,1)); |
|
552
|
0
|
|
|
|
|
|
while ($char != 0) { |
|
553
|
0
|
|
|
|
|
|
$str_length++;#get the length of string |
|
554
|
0
|
|
|
|
|
|
$char = ord(substr($record_buf,$record_buf_pos+$str_length,1)); |
|
555
|
|
|
|
|
|
|
} |
|
556
|
0
|
0
|
|
|
|
|
if ($str_length > 0) { |
|
557
|
0
|
|
|
|
|
|
$record_postal_code = substr($record_buf,$record_buf_pos,$str_length); |
|
558
|
|
|
|
|
|
|
} |
|
559
|
0
|
|
|
|
|
|
$record_buf_pos += $str_length + 1; |
|
560
|
0
|
|
|
|
|
|
$str_length = 0; |
|
561
|
0
|
|
|
|
|
|
my $latitude = 0; |
|
562
|
0
|
|
|
|
|
|
my $longitude = 0; |
|
563
|
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
#get the latitude |
|
565
|
0
|
|
|
|
|
|
for ($j = 0;$j < 3; ++$j) { |
|
566
|
0
|
|
|
|
|
|
$char = ord(substr($record_buf,$record_buf_pos++,1)); |
|
567
|
0
|
|
|
|
|
|
$latitude += ($char << ($j * 8)); |
|
568
|
|
|
|
|
|
|
} |
|
569
|
0
|
|
|
|
|
|
$record_latitude = ($latitude/10000) - 180; |
|
570
|
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
#get the longitude |
|
572
|
0
|
|
|
|
|
|
for ($j = 0;$j < 3; ++$j) { |
|
573
|
0
|
|
|
|
|
|
$char = ord(substr($record_buf,$record_buf_pos++,1)); |
|
574
|
0
|
|
|
|
|
|
$longitude += ($char << ($j * 8)); |
|
575
|
|
|
|
|
|
|
} |
|
576
|
0
|
|
|
|
|
|
$record_longitude = ($longitude/10000) - 180; |
|
577
|
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
#get the metro code and the area code |
|
579
|
0
|
0
|
|
|
|
|
if (GEOIP_CITY_EDITION_REV1 == $gi->{"databaseType"}) { |
|
580
|
0
|
|
|
|
|
|
$metroarea_combo = 0; |
|
581
|
0
|
0
|
|
|
|
|
if ($record_country_code eq "US") { |
|
582
|
|
|
|
|
|
|
#if the country is US then read the metro area combo |
|
583
|
0
|
|
|
|
|
|
for ($j = 0;$j < 3;++$j) { |
|
584
|
0
|
|
|
|
|
|
$char = ord(substr($record_buf,$record_buf_pos++,1)); |
|
585
|
0
|
|
|
|
|
|
$metroarea_combo += ($char << ($j * 8)); |
|
586
|
|
|
|
|
|
|
} |
|
587
|
|
|
|
|
|
|
#split the metro area combo into the metro code and the area code |
|
588
|
0
|
|
|
|
|
|
$record_metro_code = int($metroarea_combo/1000); |
|
589
|
0
|
|
|
|
|
|
$record_area_code = $metroarea_combo%1000; |
|
590
|
|
|
|
|
|
|
} |
|
591
|
|
|
|
|
|
|
} |
|
592
|
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
# the pureperl API must convert the string by themself to UTF8 |
|
594
|
|
|
|
|
|
|
# using Encode for perl >= 5.008 otherwise use it's own iso-8859-1 to utf8 converter |
|
595
|
0
|
0
|
|
|
|
|
$record_city = decode( 'iso-8859-1' => $record_city ) |
|
596
|
|
|
|
|
|
|
if $gi->charset == GEOIP_CHARSET_UTF8; |
|
597
|
|
|
|
|
|
|
|
|
598
|
0
|
|
|
|
|
|
return ($record_country_code,$record_country_code3,$record_country_name,$record_region,$record_city,$record_postal_code,$record_latitude,$record_longitude,$record_metro_code,$record_area_code); |
|
599
|
|
|
|
|
|
|
} |
|
600
|
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
#this function returns the city record as a hash ref |
|
602
|
|
|
|
|
|
|
sub get_city_record_as_hash { |
|
603
|
0
|
|
|
0
|
1
|
|
my ($gi, $host) = @_; |
|
604
|
0
|
|
|
|
|
|
my %h; |
|
605
|
0
|
|
|
|
|
|
@h{qw/ country_code country_code3 country_name |
|
606
|
|
|
|
|
|
|
region city postal_code |
|
607
|
|
|
|
|
|
|
latitude longitude metro_code |
|
608
|
|
|
|
|
|
|
area_code /} |
|
609
|
|
|
|
|
|
|
= $gi->get_city_record($host); |
|
610
|
0
|
|
|
|
|
|
$h{dma_code} = $h{metro_code}; # alias for depreciated dma_code |
|
611
|
0
|
|
|
|
|
|
return \%h; |
|
612
|
|
|
|
|
|
|
} |
|
613
|
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
#this function returns isp or org of the domain name |
|
615
|
|
|
|
|
|
|
sub org_by_name { |
|
616
|
0
|
|
|
0
|
1
|
|
my ($gi, $host) = @_; |
|
617
|
0
|
|
|
|
|
|
my $ip_address = $gi->get_ip_address($host); |
|
618
|
0
|
|
|
|
|
|
my $seek_org = $gi->_seek_country(addr_to_num($ip_address)); |
|
619
|
0
|
|
|
|
|
|
my $char; |
|
620
|
|
|
|
|
|
|
my $org_buf; |
|
621
|
0
|
|
|
|
|
|
my $org_buf_length = 0; |
|
622
|
0
|
|
|
|
|
|
my $record_pointer; |
|
623
|
|
|
|
|
|
|
|
|
624
|
0
|
0
|
|
|
|
|
if ($seek_org == $gi->{"databaseSegments"}) { |
|
625
|
0
|
|
|
|
|
|
return undef; |
|
626
|
|
|
|
|
|
|
} |
|
627
|
|
|
|
|
|
|
|
|
628
|
0
|
|
|
|
|
|
$record_pointer = $seek_org + (2 * $gi->{"record_length"} - 1) * $gi->{"databaseSegments"}; |
|
629
|
|
|
|
|
|
|
|
|
630
|
0
|
0
|
|
|
|
|
unless ( exists $gi->{buf} ) { |
|
631
|
0
|
|
|
|
|
|
seek( $gi->{"fh"}, $record_pointer, 0 ); |
|
632
|
0
|
|
|
|
|
|
read( $gi->{"fh"}, $org_buf, MAX_ORG_RECORD_LENGTH ); |
|
633
|
|
|
|
|
|
|
} |
|
634
|
|
|
|
|
|
|
else { |
|
635
|
0
|
|
|
|
|
|
$org_buf = substr($gi->{buf}, $record_pointer, MAX_ORG_RECORD_LENGTH ); |
|
636
|
|
|
|
|
|
|
} |
|
637
|
|
|
|
|
|
|
|
|
638
|
0
|
|
|
|
|
|
$char = ord(substr($org_buf,0,1)); |
|
639
|
0
|
|
|
|
|
|
while ($char != 0) { |
|
640
|
0
|
|
|
|
|
|
$org_buf_length++; |
|
641
|
0
|
|
|
|
|
|
$char = ord(substr($org_buf,$org_buf_length,1)); |
|
642
|
|
|
|
|
|
|
} |
|
643
|
|
|
|
|
|
|
|
|
644
|
0
|
|
|
|
|
|
$org_buf = substr($org_buf, 0, $org_buf_length); |
|
645
|
0
|
|
|
|
|
|
return $org_buf; |
|
646
|
|
|
|
|
|
|
} |
|
647
|
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
#this function returns isp or org of the domain name |
|
649
|
|
|
|
|
|
|
*isp_by_name = \*org_by_name; |
|
650
|
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
*org_by_addr = \*org_by_name; |
|
652
|
|
|
|
|
|
|
*isp_by_addr = \*org_by_name; |
|
653
|
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
#this function returns the region |
|
655
|
|
|
|
|
|
|
sub region_by_name { |
|
656
|
0
|
|
|
0
|
0
|
|
my ($gi, $host) = @_; |
|
657
|
0
|
|
|
|
|
|
my $ip_address = $gi->get_ip_address($host); |
|
658
|
0
|
0
|
|
|
|
|
return unless $ip_address; |
|
659
|
0
|
0
|
|
|
|
|
if ($gi->{"databaseType"} == GEOIP_REGION_EDITION_REV0) { |
|
|
|
0
|
|
|
|
|
|
|
660
|
0
|
|
|
|
|
|
my $seek_region = $gi->_seek_country(addr_to_num($ip_address)) - GEOIP_STATE_BEGIN_REV0; |
|
661
|
0
|
0
|
|
|
|
|
if ($seek_region >= 1000) { |
|
662
|
0
|
|
|
|
|
|
return ("US",chr(($seek_region - 1000)/26 + 65) . chr(($seek_region - 1000)%26 + 65)); |
|
663
|
|
|
|
|
|
|
} else { |
|
664
|
0
|
|
|
|
|
|
return ($countries[$seek_region],""); |
|
665
|
|
|
|
|
|
|
} |
|
666
|
|
|
|
|
|
|
} elsif ($gi->{"databaseType"} == GEOIP_REGION_EDITION_REV1) { |
|
667
|
0
|
|
|
|
|
|
my $seek_region = $gi->_seek_country(addr_to_num($ip_address)) - GEOIP_STATE_BEGIN_REV1; |
|
668
|
0
|
0
|
|
|
|
|
if ($seek_region < US_OFFSET) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
669
|
0
|
|
|
|
|
|
return ("",""); |
|
670
|
|
|
|
|
|
|
} elsif ($seek_region < CANADA_OFFSET) { |
|
671
|
|
|
|
|
|
|
# return a us state |
|
672
|
0
|
|
|
|
|
|
return ("US",chr(($seek_region - US_OFFSET)/26 + 65) . chr(($seek_region - US_OFFSET)%26 + 65)); |
|
673
|
|
|
|
|
|
|
} elsif ($seek_region < WORLD_OFFSET) { |
|
674
|
|
|
|
|
|
|
# return a canada province |
|
675
|
0
|
|
|
|
|
|
return ("CA",chr(($seek_region - CANADA_OFFSET)/26 + 65) . chr(($seek_region - CANADA_OFFSET)%26 + 65)); |
|
676
|
|
|
|
|
|
|
} else { |
|
677
|
|
|
|
|
|
|
# return a country of the world |
|
678
|
0
|
|
|
|
|
|
my $c = $countries[($seek_region - WORLD_OFFSET) / FIPS_RANGE]; |
|
679
|
0
|
|
|
|
|
|
my $a2 = ($seek_region - WORLD_OFFSET) % FIPS_RANGE; |
|
680
|
0
|
|
|
|
|
|
my $r = chr(($a2 / 100)+48) . chr((($a2 / 10) % 10)+48) . chr(($a2 % 10)+48); |
|
681
|
0
|
|
|
|
|
|
return ($c,$r); |
|
682
|
|
|
|
|
|
|
} |
|
683
|
|
|
|
|
|
|
} |
|
684
|
|
|
|
|
|
|
} |
|
685
|
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
sub get_ip_address { |
|
687
|
0
|
|
|
0
|
0
|
|
my ($gi, $host) = @_; |
|
688
|
0
|
|
|
|
|
|
my $ip_address; |
|
689
|
|
|
|
|
|
|
#check if host is ip address |
|
690
|
0
|
0
|
|
|
|
|
if ($host =~ m!^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$!) { |
|
691
|
|
|
|
|
|
|
#host is ip address |
|
692
|
0
|
|
|
|
|
|
$ip_address = $host; |
|
693
|
|
|
|
|
|
|
} else { |
|
694
|
|
|
|
|
|
|
#host is domain name do a dns lookup |
|
695
|
0
|
|
|
|
|
|
$ip_address = join('.',unpack('C4',(gethostbyname($host))[4])); |
|
696
|
|
|
|
|
|
|
} |
|
697
|
0
|
|
|
|
|
|
return $ip_address; |
|
698
|
|
|
|
|
|
|
} |
|
699
|
|
|
|
|
|
|
|
|
700
|
0
|
|
|
0
|
0
|
|
sub addr_to_num { unpack( N => pack( C4 => split( /\./, $_[0] ) ) ) } |
|
701
|
0
|
|
|
0
|
0
|
|
sub num_to_addr { join q{.}, unpack( C4 => pack( N => $_[0] ) ) } |
|
702
|
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
sub database_info { |
|
704
|
0
|
|
|
0
|
1
|
|
my $gi = shift; |
|
705
|
0
|
|
|
|
|
|
my $i = 0; |
|
706
|
0
|
|
|
|
|
|
my $buf; |
|
707
|
|
|
|
|
|
|
my $retval; |
|
708
|
0
|
|
|
|
|
|
my $hasStructureInfo; |
|
709
|
0
|
|
|
|
|
|
seek($gi->{fh},-3,2); |
|
710
|
0
|
|
|
|
|
|
for (my $i = 0;$i < STRUCTURE_INFO_MAX_SIZE;$i++) { |
|
711
|
0
|
|
|
|
|
|
read($gi->{fh},$buf,3); |
|
712
|
0
|
0
|
|
|
|
|
if ($buf eq (chr(255) . chr(255) . chr(255))) { |
|
713
|
0
|
|
|
|
|
|
$hasStructureInfo = 1; |
|
714
|
0
|
|
|
|
|
|
last; |
|
715
|
|
|
|
|
|
|
} |
|
716
|
0
|
|
|
|
|
|
seek($gi->{fh},-4,1); |
|
717
|
|
|
|
|
|
|
} |
|
718
|
0
|
0
|
|
|
|
|
if ($hasStructureInfo == 1) { |
|
719
|
0
|
|
|
|
|
|
seek($gi->{fh},-6,1); |
|
720
|
|
|
|
|
|
|
} else { |
|
721
|
|
|
|
|
|
|
# no structure info, must be pre Sep 2002 database, go back to |
|
722
|
0
|
|
|
|
|
|
seek($gi->{fh},-3,2); |
|
723
|
|
|
|
|
|
|
} |
|
724
|
0
|
|
|
|
|
|
for (my $i = 0;$i < DATABASE_INFO_MAX_SIZE;$i++){ |
|
725
|
0
|
|
|
|
|
|
read($gi->{fh},$buf,3); |
|
726
|
0
|
0
|
|
|
|
|
if ($buf eq (chr(0). chr(0). chr(0))){ |
|
727
|
0
|
|
|
|
|
|
read($gi->{fh},$retval,$i); |
|
728
|
0
|
|
|
|
|
|
return $retval; |
|
729
|
|
|
|
|
|
|
} |
|
730
|
0
|
|
|
|
|
|
seek($gi->{fh},-4,1); |
|
731
|
|
|
|
|
|
|
} |
|
732
|
0
|
|
|
|
|
|
return ""; |
|
733
|
|
|
|
|
|
|
} |
|
734
|
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
sub range_by_ip { |
|
736
|
0
|
|
|
0
|
1
|
|
my $gi = shift; |
|
737
|
0
|
|
|
|
|
|
my $ipnum = addr_to_num( shift ); |
|
738
|
0
|
|
|
|
|
|
my $c = $gi->_seek_country( $ipnum ); |
|
739
|
0
|
|
|
|
|
|
my $nm = $gi->last_netmask; |
|
740
|
0
|
|
|
|
|
|
my $m = 0xffffffff << 32 - $nm; |
|
741
|
0
|
|
|
|
|
|
my $left_seek_num = $ipnum & $m; |
|
742
|
0
|
|
|
|
|
|
my $right_seek_num = $left_seek_num + ( 0xffffffff & ~$m ); |
|
743
|
|
|
|
|
|
|
|
|
744
|
0
|
|
0
|
|
|
|
while ( $left_seek_num != 0 |
|
745
|
|
|
|
|
|
|
and $c == $gi->_seek_country( $left_seek_num - 1) ) { |
|
746
|
0
|
|
|
|
|
|
my $lm = 0xffffffff << 32 - $gi->last_netmask; |
|
747
|
0
|
|
|
|
|
|
$left_seek_num = ( $left_seek_num - 1 ) & $lm; |
|
748
|
|
|
|
|
|
|
} |
|
749
|
0
|
|
0
|
|
|
|
while ( $right_seek_num != 0xffffffff |
|
750
|
|
|
|
|
|
|
and $c == $gi->_seek_country( $right_seek_num + 1 ) ) { |
|
751
|
0
|
|
|
|
|
|
my $rm = 0xffffffff << 32 - $gi->last_netmask; |
|
752
|
0
|
|
|
|
|
|
$right_seek_num = ( $right_seek_num + 1 ) & $rm; |
|
753
|
0
|
|
|
|
|
|
$right_seek_num += ( 0xffffffff & ~$rm ); |
|
754
|
|
|
|
|
|
|
} |
|
755
|
0
|
|
|
|
|
|
return ( num_to_addr($left_seek_num), num_to_addr($right_seek_num) ); |
|
756
|
|
|
|
|
|
|
} |
|
757
|
|
|
|
|
|
|
|
|
758
|
0
|
|
|
0
|
1
|
|
sub netmask { $_[0]->{last_netmask} = $_[1] } |
|
759
|
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
sub last_netmask { |
|
761
|
0
|
|
|
0
|
1
|
|
return $_[0]->{last_netmask}; |
|
762
|
|
|
|
|
|
|
} |
|
763
|
|
|
|
|
|
|
|
|
764
|
|
|
|
|
|
|
sub DESTROY { |
|
765
|
0
|
|
|
0
|
|
|
my $gi = shift; |
|
766
|
|
|
|
|
|
|
|
|
767
|
0
|
0
|
0
|
|
|
|
if ( exists $gi->{buf} && $gi->{flags} && ( $gi->{flags} & GEOIP_MMAP_CACHE ) ) { |
|
|
|
|
0
|
|
|
|
|
|
768
|
0
|
0
|
|
|
|
|
munmap( $gi->{buf} ) or die "munmap: $!"; |
|
769
|
0
|
|
|
|
|
|
delete $gi->{buf}; |
|
770
|
|
|
|
|
|
|
} |
|
771
|
|
|
|
|
|
|
} |
|
772
|
|
|
|
|
|
|
1; |
|
773
|
|
|
|
|
|
|
__END__ |