3 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
6 * Copyright (C) 2007 MaxMind LLC
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 define("GEOIP_COUNTRY_BEGIN", 16776960);
24 define("GEOIP_STATE_BEGIN_REV0", 16700000);
25 define("GEOIP_STATE_BEGIN_REV1", 16000000);
26 define("GEOIP_STANDARD", 0);
27 define("GEOIP_MEMORY_CACHE", 1);
28 define("GEOIP_SHARED_MEMORY", 2);
29 define("STRUCTURE_INFO_MAX_SIZE", 20);
30 define("DATABASE_INFO_MAX_SIZE", 100);
31 define("GEOIP_COUNTRY_EDITION", 106);
32 define("GEOIP_PROXY_EDITION", 8);
33 define("GEOIP_ASNUM_EDITION", 9);
34 define("GEOIP_NETSPEED_EDITION", 10);
35 define("GEOIP_REGION_EDITION_REV0", 112);
36 define("GEOIP_REGION_EDITION_REV1", 3);
37 define("GEOIP_CITY_EDITION_REV0", 111);
38 define("GEOIP_CITY_EDITION_REV1", 2);
39 define("GEOIP_ORG_EDITION", 110);
40 define("GEOIP_ISP_EDITION", 4);
41 define("SEGMENT_RECORD_LENGTH", 3);
42 define("STANDARD_RECORD_LENGTH", 3);
43 define("ORG_RECORD_LENGTH", 4);
44 define("MAX_RECORD_LENGTH", 4);
45 define("MAX_ORG_RECORD_LENGTH", 300);
46 define("GEOIP_SHM_KEY", 0x4f415401);
47 define("US_OFFSET", 1);
48 define("CANADA_OFFSET", 677);
49 define("WORLD_OFFSET", 1353);
50 define("FIPS_RANGE", 360);
51 define("GEOIP_UNKNOWN_SPEED", 0);
52 define("GEOIP_DIALUP_SPEED", 1);
53 define("GEOIP_CABLEDSL_SPEED", 2);
54 define("GEOIP_CORPORATE_SPEED", 3);
55 define("GEOIP_DOMAIN_EDITION", 11);
56 define("GEOIP_COUNTRY_EDITION_V6", 12);
57 define("GEOIP_LOCATIONA_EDITION", 13);
58 define("GEOIP_ACCURACYRADIUS_EDITION", 14);
59 define("GEOIP_CITYCOMBINED_EDITION", 15);
60 define("GEOIP_CITY_EDITION_REV1_V6", 30);
61 define("GEOIP_CITY_EDITION_REV0_V6",31);
62 define("GEOIP_NETSPEED_EDITION_REV1",32);
63 define("GEOIP_NETSPEED_EDITION_REV1_V6",33);
64 define("GEOIP_USERTYPE_EDITION",28);
65 define("GEOIP_USERTYPE_EDITION_V6",29);
66 define("GEOIP_ASNUM_EDITION_V6",21);
67 define("GEOIP_ISP_EDITION_V6",22);
68 define("GEOIP_ORG_EDITION_V6",23);
69 define("GEOIP_DOMAIN_EDITION_V6",24);
71 define("CITYCOMBINED_FIXED_RECORD", 7 );
73 if( !class_exists('GeoIP', false) ) {
79 var $databaseSegments;
82 var $GEOIP_COUNTRY_CODE_TO_NUMBER = array(
83 "" => 0, "AP" => 1, "EU" => 2, "AD" => 3, "AE" => 4, "AF" => 5,
84 "AG" => 6, "AI" => 7, "AL" => 8, "AM" => 9, "CW" => 10, "AO" => 11,
85 "AQ" => 12, "AR" => 13, "AS" => 14, "AT" => 15, "AU" => 16, "AW" => 17,
86 "AZ" => 18, "BA" => 19, "BB" => 20, "BD" => 21, "BE" => 22, "BF" => 23,
87 "BG" => 24, "BH" => 25, "BI" => 26, "BJ" => 27, "BM" => 28, "BN" => 29,
88 "BO" => 30, "BR" => 31, "BS" => 32, "BT" => 33, "BV" => 34, "BW" => 35,
89 "BY" => 36, "BZ" => 37, "CA" => 38, "CC" => 39, "CD" => 40, "CF" => 41,
90 "CG" => 42, "CH" => 43, "CI" => 44, "CK" => 45, "CL" => 46, "CM" => 47,
91 "CN" => 48, "CO" => 49, "CR" => 50, "CU" => 51, "CV" => 52, "CX" => 53,
92 "CY" => 54, "CZ" => 55, "DE" => 56, "DJ" => 57, "DK" => 58, "DM" => 59,
93 "DO" => 60, "DZ" => 61, "EC" => 62, "EE" => 63, "EG" => 64, "EH" => 65,
94 "ER" => 66, "ES" => 67, "ET" => 68, "FI" => 69, "FJ" => 70, "FK" => 71,
95 "FM" => 72, "FO" => 73, "FR" => 74, "SX" => 75, "GA" => 76, "GB" => 77,
96 "GD" => 78, "GE" => 79, "GF" => 80, "GH" => 81, "GI" => 82, "GL" => 83,
97 "GM" => 84, "GN" => 85, "GP" => 86, "GQ" => 87, "GR" => 88, "GS" => 89,
98 "GT" => 90, "GU" => 91, "GW" => 92, "GY" => 93, "HK" => 94, "HM" => 95,
99 "HN" => 96, "HR" => 97, "HT" => 98, "HU" => 99, "ID" => 100, "IE" => 101,
100 "IL" => 102, "IN" => 103, "IO" => 104, "IQ" => 105, "IR" => 106, "IS" => 107,
101 "IT" => 108, "JM" => 109, "JO" => 110, "JP" => 111, "KE" => 112, "KG" => 113,
102 "KH" => 114, "KI" => 115, "KM" => 116, "KN" => 117, "KP" => 118, "KR" => 119,
103 "KW" => 120, "KY" => 121, "KZ" => 122, "LA" => 123, "LB" => 124, "LC" => 125,
104 "LI" => 126, "LK" => 127, "LR" => 128, "LS" => 129, "LT" => 130, "LU" => 131,
105 "LV" => 132, "LY" => 133, "MA" => 134, "MC" => 135, "MD" => 136, "MG" => 137,
106 "MH" => 138, "MK" => 139, "ML" => 140, "MM" => 141, "MN" => 142, "MO" => 143,
107 "MP" => 144, "MQ" => 145, "MR" => 146, "MS" => 147, "MT" => 148, "MU" => 149,
108 "MV" => 150, "MW" => 151, "MX" => 152, "MY" => 153, "MZ" => 154, "NA" => 155,
109 "NC" => 156, "NE" => 157, "NF" => 158, "NG" => 159, "NI" => 160, "NL" => 161,
110 "NO" => 162, "NP" => 163, "NR" => 164, "NU" => 165, "NZ" => 166, "OM" => 167,
111 "PA" => 168, "PE" => 169, "PF" => 170, "PG" => 171, "PH" => 172, "PK" => 173,
112 "PL" => 174, "PM" => 175, "PN" => 176, "PR" => 177, "PS" => 178, "PT" => 179,
113 "PW" => 180, "PY" => 181, "QA" => 182, "RE" => 183, "RO" => 184, "RU" => 185,
114 "RW" => 186, "SA" => 187, "SB" => 188, "SC" => 189, "SD" => 190, "SE" => 191,
115 "SG" => 192, "SH" => 193, "SI" => 194, "SJ" => 195, "SK" => 196, "SL" => 197,
116 "SM" => 198, "SN" => 199, "SO" => 200, "SR" => 201, "ST" => 202, "SV" => 203,
117 "SY" => 204, "SZ" => 205, "TC" => 206, "TD" => 207, "TF" => 208, "TG" => 209,
118 "TH" => 210, "TJ" => 211, "TK" => 212, "TM" => 213, "TN" => 214, "TO" => 215,
119 "TL" => 216, "TR" => 217, "TT" => 218, "TV" => 219, "TW" => 220, "TZ" => 221,
120 "UA" => 222, "UG" => 223, "UM" => 224, "US" => 225, "UY" => 226, "UZ" => 227,
121 "VA" => 228, "VC" => 229, "VE" => 230, "VG" => 231, "VI" => 232, "VN" => 233,
122 "VU" => 234, "WF" => 235, "WS" => 236, "YE" => 237, "YT" => 238, "RS" => 239,
123 "ZA" => 240, "ZM" => 241, "ME" => 242, "ZW" => 243, "A1" => 244, "A2" => 245,
124 "O1" => 246, "AX" => 247, "GG" => 248, "IM" => 249, "JE" => 250, "BL" => 251,
125 "MF" => 252, "BQ" => 253, "SS" => 254
127 var $GEOIP_COUNTRY_CODES = array(
128 "","AP","EU","AD","AE","AF","AG","AI","AL","AM","CW",
129 "AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB",
130 "BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO",
131 "BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD",
132 "CF","CG","CH","CI","CK","CL","CM","CN","CO","CR",
133 "CU","CV","CX","CY","CZ","DE","DJ","DK","DM","DO",
134 "DZ","EC","EE","EG","EH","ER","ES","ET","FI","FJ",
135 "FK","FM","FO","FR","SX","GA","GB","GD","GE","GF",
136 "GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT",
137 "GU","GW","GY","HK","HM","HN","HR","HT","HU","ID",
138 "IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO",
139 "JP","KE","KG","KH","KI","KM","KN","KP","KR","KW",
140 "KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT",
141 "LU","LV","LY","MA","MC","MD","MG","MH","MK","ML",
142 "MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV",
143 "MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI",
144 "NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF",
145 "PG","PH","PK","PL","PM","PN","PR","PS","PT","PW",
146 "PY","QA","RE","RO","RU","RW","SA","SB","SC","SD",
147 "SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO",
148 "SR","ST","SV","SY","SZ","TC","TD","TF","TG","TH",
149 "TJ","TK","TM","TN","TO","TL","TR","TT","TV","TW",
150 "TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE",
151 "VG","VI","VN","VU","WF","WS","YE","YT","RS","ZA",
152 "ZM","ME","ZW","A1","A2","O1","AX","GG","IM","JE",
153 "BL","MF", "BQ", "SS", "O1" );
154 var $GEOIP_COUNTRY_CODES3 = array(
155 "","AP","EU","AND","ARE","AFG","ATG","AIA","ALB","ARM","CUW",
156 "AGO","ATA","ARG","ASM","AUT","AUS","ABW","AZE","BIH","BRB",
157 "BGD","BEL","BFA","BGR","BHR","BDI","BEN","BMU","BRN","BOL",
158 "BRA","BHS","BTN","BVT","BWA","BLR","BLZ","CAN","CCK","COD",
159 "CAF","COG","CHE","CIV","COK","CHL","CMR","CHN","COL","CRI",
160 "CUB","CPV","CXR","CYP","CZE","DEU","DJI","DNK","DMA","DOM",
161 "DZA","ECU","EST","EGY","ESH","ERI","ESP","ETH","FIN","FJI",
162 "FLK","FSM","FRO","FRA","SXM","GAB","GBR","GRD","GEO","GUF",
163 "GHA","GIB","GRL","GMB","GIN","GLP","GNQ","GRC","SGS","GTM",
164 "GUM","GNB","GUY","HKG","HMD","HND","HRV","HTI","HUN","IDN",
165 "IRL","ISR","IND","IOT","IRQ","IRN","ISL","ITA","JAM","JOR",
166 "JPN","KEN","KGZ","KHM","KIR","COM","KNA","PRK","KOR","KWT",
167 "CYM","KAZ","LAO","LBN","LCA","LIE","LKA","LBR","LSO","LTU",
168 "LUX","LVA","LBY","MAR","MCO","MDA","MDG","MHL","MKD","MLI",
169 "MMR","MNG","MAC","MNP","MTQ","MRT","MSR","MLT","MUS","MDV",
170 "MWI","MEX","MYS","MOZ","NAM","NCL","NER","NFK","NGA","NIC",
171 "NLD","NOR","NPL","NRU","NIU","NZL","OMN","PAN","PER","PYF",
172 "PNG","PHL","PAK","POL","SPM","PCN","PRI","PSE","PRT","PLW",
173 "PRY","QAT","REU","ROU","RUS","RWA","SAU","SLB","SYC","SDN",
174 "SWE","SGP","SHN","SVN","SJM","SVK","SLE","SMR","SEN","SOM",
175 "SUR","STP","SLV","SYR","SWZ","TCA","TCD","ATF","TGO","THA",
176 "TJK","TKL","TKM","TUN","TON","TLS","TUR","TTO","TUV","TWN",
177 "TZA","UKR","UGA","UMI","USA","URY","UZB","VAT","VCT","VEN",
178 "VGB","VIR","VNM","VUT","WLF","WSM","YEM","MYT","SRB","ZAF",
179 "ZMB","MNE","ZWE","A1","A2","O1","ALA","GGY","IMN","JEY",
180 "BLM","MAF", "BES", "SSD", "O1"
182 var $GEOIP_COUNTRY_NAMES = array(
183 "","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Curacao",
184 "Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados",
185 "Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia",
186 "Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the",
187 "Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica",
188 "Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic",
189 "Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji",
190 "Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","Sint Maarten (Dutch part)","Gabon","United Kingdom","Grenada","Georgia","French Guiana",
191 "Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala",
192 "Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia",
193 "Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan",
194 "Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait",
195 "Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania",
196 "Luxembourg","Latvia","Libya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali",
197 "Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives",
198 "Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua",
199 "Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia",
200 "Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau",
201 "Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan",
202 "Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname",
203 "Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand",
204 "Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan",
205 "Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela",
206 "Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa",
207 "Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey",
208 "Saint Barthelemy","Saint Martin", "Bonaire, Saint Eustatius and Saba",
209 "South Sudan", "Other"
212 var $GEOIP_CONTINENT_CODES = array(
213 "--", "AS","EU","EU","AS","AS","NA","NA","EU","AS","NA",
214 "AF","AN","SA","OC","EU","OC","NA","AS","EU","NA",
215 "AS","EU","AF","EU","AS","AF","AF","NA","AS","SA",
216 "SA","NA","AS","AN","AF","EU","NA","NA","AS","AF",
217 "AF","AF","EU","AF","OC","SA","AF","AS","SA","NA",
218 "NA","AF","AS","AS","EU","EU","AF","EU","NA","NA",
219 "AF","SA","EU","AF","AF","AF","EU","AF","EU","OC",
220 "SA","OC","EU","EU","NA","AF","EU","NA","AS","SA",
221 "AF","EU","NA","AF","AF","NA","AF","EU","AN","NA",
222 "OC","AF","SA","AS","AN","NA","EU","NA","EU","AS",
223 "EU","AS","AS","AS","AS","AS","EU","EU","NA","AS",
224 "AS","AF","AS","AS","OC","AF","NA","AS","AS","AS",
225 "NA","AS","AS","AS","NA","EU","AS","AF","AF","EU",
226 "EU","EU","AF","AF","EU","EU","AF","OC","EU","AF",
227 "AS","AS","AS","OC","NA","AF","NA","EU","AF","AS",
228 "AF","NA","AS","AF","AF","OC","AF","OC","AF","NA",
229 "EU","EU","AS","OC","OC","OC","AS","NA","SA","OC",
230 "OC","AS","AS","EU","NA","OC","NA","AS","EU","OC",
231 "SA","AS","AF","EU","EU","AF","AS","OC","AF","AF",
232 "EU","AS","AF","EU","EU","EU","AF","EU","AF","AF",
233 "SA","AF","NA","AS","AF","NA","AF","AN","AF","AS",
234 "AS","OC","AS","AF","OC","AS","EU","NA","OC","AS",
235 "AF","EU","AF","OC","NA","SA","AS","EU","NA","SA",
236 "NA","NA","AS","OC","OC","OC","AS","AF","EU","AF",
237 "AF","EU","AF","--","--","--","EU","EU","EU","EU",
238 "NA","NA","NA", "AF", "--"
243 if( !function_exists('geoip_load_shared_mem') ) {
244 function geoip_load_shared_mem ($file) {
246 $fp = fopen($file, "rb");
248 print "error opening $file: $php_errormsg\n";
251 $s_array = fstat($fp);
252 $size = $s_array['size'];
253 if ($shmid = @shmop_open (GEOIP_SHM_KEY, "w", 0, 0)) {
254 shmop_delete ($shmid);
255 shmop_close ($shmid);
257 $shmid = shmop_open (GEOIP_SHM_KEY, "c", 0644, $size);
258 shmop_write ($shmid, fread($fp, $size), 0);
259 shmop_close ($shmid);
263 if( !function_exists('_setup_segments') ) {
264 function _setup_segments($gi){
265 $gi->databaseType = GEOIP_COUNTRY_EDITION;
266 $gi->record_length = STANDARD_RECORD_LENGTH;
267 if ($gi->flags & GEOIP_SHARED_MEMORY) {
268 $offset = @shmop_size ($gi->shmid) - 3;
269 for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
270 $delim = @shmop_read ($gi->shmid, $offset, 3);
272 if ($delim == (chr(255).chr(255).chr(255))) {
273 $gi->databaseType = ord(@shmop_read ($gi->shmid, $offset, 1));
276 if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){
277 $gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
278 } else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1){
279 $gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
280 } else if (($gi->databaseType == GEOIP_CITY_EDITION_REV0)||
281 ($gi->databaseType == GEOIP_CITY_EDITION_REV1)
282 || ($gi->databaseType == GEOIP_ORG_EDITION)
283 || ($gi->databaseType == GEOIP_ORG_EDITION_V6)
284 || ($gi->databaseType == GEOIP_DOMAIN_EDITION)
285 || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
286 || ($gi->databaseType == GEOIP_ISP_EDITION)
287 || ($gi->databaseType == GEOIP_ISP_EDITION_V6)
288 || ($gi->databaseType == GEOIP_USERTYPE_EDITION)
289 || ($gi->databaseType == GEOIP_USERTYPE_EDITION_V6)
290 || ($gi->databaseType == GEOIP_LOCATIONA_EDITION)
291 || ($gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION)
292 || ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
293 || ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
294 || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1)
295 || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6)
296 || ($gi->databaseType == GEOIP_ASNUM_EDITION)
297 || ($gi->databaseType == GEOIP_ASNUM_EDITION_V6)){
298 $gi->databaseSegments = 0;
299 $buf = @shmop_read ($gi->shmid, $offset, SEGMENT_RECORD_LENGTH);
300 for ($j = 0;$j < SEGMENT_RECORD_LENGTH;$j++){
301 $gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
303 if (($gi->databaseType == GEOIP_ORG_EDITION)
304 || ($gi->databaseType == GEOIP_ORG_EDITION_V6)
305 || ($gi->databaseType == GEOIP_DOMAIN_EDITION)
306 || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
307 || ($gi->databaseType == GEOIP_ISP_EDITION)
308 || ($gi->databaseType == GEOIP_ISP_EDITION_V6)) {
309 $gi->record_length = ORG_RECORD_LENGTH;
317 if (($gi->databaseType == GEOIP_COUNTRY_EDITION)||
318 ($gi->databaseType == GEOIP_COUNTRY_EDITION_V6)||
319 ($gi->databaseType == GEOIP_PROXY_EDITION)||
320 ($gi->databaseType == GEOIP_NETSPEED_EDITION)){
321 $gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
324 $filepos = ftell($gi->filehandle);
325 fseek($gi->filehandle, -3, SEEK_END);
326 for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
327 $delim = fread($gi->filehandle,3);
328 if ($delim == (chr(255).chr(255).chr(255))){
329 $gi->databaseType = ord(fread($gi->filehandle,1));
330 if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){
331 $gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
333 else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1){
334 $gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
335 } else if (($gi->databaseType == GEOIP_CITY_EDITION_REV0)
336 || ($gi->databaseType == GEOIP_CITY_EDITION_REV1)
337 || ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
338 || ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
339 || ($gi->databaseType == GEOIP_ORG_EDITION)
340 || ($gi->databaseType == GEOIP_DOMAIN_EDITION)
341 || ($gi->databaseType == GEOIP_ISP_EDITION)
342 || ($gi->databaseType == GEOIP_ORG_EDITION_V6)
343 || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
344 || ($gi->databaseType == GEOIP_ISP_EDITION_V6)
345 || ($gi->databaseType == GEOIP_LOCATIONA_EDITION)
346 || ($gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION)
347 || ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
348 || ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
349 || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1)
350 || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6)
351 || ($gi->databaseType == GEOIP_USERTYPE_EDITION)
352 || ($gi->databaseType == GEOIP_USERTYPE_EDITION_V6)
353 || ($gi->databaseType == GEOIP_ASNUM_EDITION)
354 || ($gi->databaseType == GEOIP_ASNUM_EDITION_V6)){
355 $gi->databaseSegments = 0;
356 $buf = fread($gi->filehandle,SEGMENT_RECORD_LENGTH);
357 for ($j = 0;$j < SEGMENT_RECORD_LENGTH;$j++){
358 $gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
360 if ( ( $gi->databaseType == GEOIP_ORG_EDITION )
361 || ( $gi->databaseType == GEOIP_DOMAIN_EDITION )
362 || ( $gi->databaseType == GEOIP_ISP_EDITION )
363 || ( $gi->databaseType == GEOIP_ORG_EDITION_V6 )
364 || ( $gi->databaseType == GEOIP_DOMAIN_EDITION_V6 )
365 || ( $gi->databaseType == GEOIP_ISP_EDITION_V6 )) {
366 $gi->record_length = ORG_RECORD_LENGTH;
371 fseek($gi->filehandle, -4, SEEK_CUR);
374 if (($gi->databaseType == GEOIP_COUNTRY_EDITION)||
375 ($gi->databaseType == GEOIP_COUNTRY_EDITION_V6)||
376 ($gi->databaseType == GEOIP_PROXY_EDITION)||
377 ($gi->databaseType == GEOIP_NETSPEED_EDITION)){
378 $gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
380 fseek($gi->filehandle,$filepos,SEEK_SET);
386 if( !function_exists( 'geoip_open' ) ) {
387 function geoip_open($filename, $flags) {
390 if ($gi->flags & GEOIP_SHARED_MEMORY) {
391 $gi->shmid = @shmop_open (GEOIP_SHM_KEY, "a", 0, 0);
393 $gi->filehandle = fopen($filename,"rb") or die( "Can not open $filename\n" );
394 if ($gi->flags & GEOIP_MEMORY_CACHE) {
395 $s_array = fstat($gi->filehandle);
396 $gi->memory_buffer = fread($gi->filehandle, $s_array['size']);
400 $gi = _setup_segments($gi);
405 if( !function_exists( 'geoip_close' ) ) {
406 function geoip_close($gi) {
407 if ($gi->flags & GEOIP_SHARED_MEMORY) {
411 return fclose($gi->filehandle);
415 if( !function_exists( 'geoip_country_id_by_name_v6' ) ) {
416 function geoip_country_id_by_name_v6($gi, $name) {
417 $rec = dns_get_record($name, DNS_AAAA);
421 $addr = $rec[0]["ipv6"];
422 if (!$addr || $addr == $name) {
425 return geoip_country_id_by_addr_v6($gi, $addr);
429 if( !function_exists( 'geoip_country_id_by_name' ) ) {
430 function geoip_country_id_by_name($gi, $name) {
431 $addr = gethostbyname($name);
432 if (!$addr || $addr == $name) {
435 return geoip_country_id_by_addr($gi, $addr);
439 if( !function_exists( 'geoip_country_code_by_name_v6' ) ) {
440 function geoip_country_code_by_name_v6($gi, $name) {
441 $country_id = geoip_country_id_by_name_v6($gi,$name);
442 if ($country_id !== false) {
443 return $gi->GEOIP_COUNTRY_CODES[$country_id];
449 if( !function_exists( 'geoip_country_code_by_name' ) ) {
450 function geoip_country_code_by_name($gi, $name) {
451 $country_id = geoip_country_id_by_name($gi,$name);
452 if ($country_id !== false) {
453 return $gi->GEOIP_COUNTRY_CODES[$country_id];
459 if( !function_exists( 'geoip_country_name_by_name_v6' ) ) {
460 function geoip_country_name_by_name_v6($gi, $name) {
461 $country_id = geoip_country_id_by_name_v6($gi,$name);
462 if ($country_id !== false) {
463 return $gi->GEOIP_COUNTRY_NAMES[$country_id];
469 if( !function_exists( 'geoip_country_name_by_name' ) ) {
470 function geoip_country_name_by_name($gi, $name) {
471 $country_id = geoip_country_id_by_name($gi,$name);
472 if ($country_id !== false) {
473 return $gi->GEOIP_COUNTRY_NAMES[$country_id];
479 if( !function_exists( 'geoip_country_id_by_addr_v6' ) ) {
480 function geoip_country_id_by_addr_v6($gi, $addr) {
481 $ipnum = inet_pton($addr);
482 return _geoip_seek_country_v6($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
486 if( !function_exists( 'geoip_country_id_by_addr' ) ) {
487 function geoip_country_id_by_addr($gi, $addr) {
488 $ipnum = ip2long($addr);
489 return _geoip_seek_country($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
493 if( !function_exists( 'geoip_country_code_by_addr_v6' ) ) {
494 function geoip_country_code_by_addr_v6($gi, $addr) {
495 $country_id = geoip_country_id_by_addr_v6($gi,$addr);
496 if ($country_id !== false) {
497 return $gi->GEOIP_COUNTRY_CODES[$country_id];
503 if( !function_exists( 'geoip_country_code_by_addr' ) ) {
504 function geoip_country_code_by_addr($gi, $addr) {
505 if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
506 $record = geoip_record_by_addr($gi,$addr);
507 if ( $record !== false ) {
508 return $record->country_code;
511 $country_id = geoip_country_id_by_addr($gi,$addr);
512 if ($country_id !== false) {
513 return $gi->GEOIP_COUNTRY_CODES[$country_id];
520 if( !function_exists( 'geoip_country_name_by_addr_v6' ) ) {
521 function geoip_country_name_by_addr_v6($gi, $addr) {
522 $country_id = geoip_country_id_by_addr_v6($gi,$addr);
523 if ($country_id !== false) {
524 return $gi->GEOIP_COUNTRY_NAMES[$country_id];
530 if( !function_exists( 'geoip_country_name_by_addr' ) ) {
531 function geoip_country_name_by_addr($gi, $addr) {
532 if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
533 $record = geoip_record_by_addr($gi,$addr);
534 return $record->country_name;
536 $country_id = geoip_country_id_by_addr($gi,$addr);
537 if ($country_id !== false) {
538 return $gi->GEOIP_COUNTRY_NAMES[$country_id];
545 if( !function_exists( '_geoip_seek_country_v6' ) ) {
546 function _geoip_seek_country_v6($gi, $ipnum) {
548 # arrays from unpack start with offset 1
549 # yet another php mystery. array_merge work around
550 # this broken behaviour
551 $v6vec = array_merge(unpack( "C16", $ipnum));
554 for ($depth = 127; $depth >= 0; --$depth) {
555 if ($gi->flags & GEOIP_MEMORY_CACHE) {
556 // workaround php's broken substr, strpos, etc handling with
557 // mbstring.func_overload and mbstring.internal_encoding
558 $enc = mb_internal_encoding();
559 mb_internal_encoding('ISO-8859-1');
561 $buf = substr($gi->memory_buffer,
562 2 * $gi->record_length * $offset,
563 2 * $gi->record_length);
565 mb_internal_encoding($enc);
566 } elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
567 $buf = @shmop_read ($gi->shmid,
568 2 * $gi->record_length * $offset,
569 2 * $gi->record_length );
571 fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
572 or die("fseek failed");
573 $buf = fread($gi->filehandle, 2 * $gi->record_length);
576 for ($i = 0; $i < 2; ++$i) {
577 for ($j = 0; $j < $gi->record_length; ++$j) {
578 $x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
582 $bnum = 127 - $depth;
584 $b_mask = 1 << ( $bnum & 7 ^ 7 );
585 if (($v6vec[$idx] & $b_mask) > 0) {
586 if ($x[1] >= $gi->databaseSegments) {
591 if ($x[0] >= $gi->databaseSegments) {
597 trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR);
602 if( !function_exists( '_geoip_seek_country' ) ) {
603 function _geoip_seek_country($gi, $ipnum) {
605 for ($depth = 31; $depth >= 0; --$depth) {
606 if ($gi->flags & GEOIP_MEMORY_CACHE) {
607 // workaround php's broken substr, strpos, etc handling with
608 // mbstring.func_overload and mbstring.internal_encoding
609 $enc = mb_internal_encoding();
610 mb_internal_encoding('ISO-8859-1');
612 $buf = substr($gi->memory_buffer,
613 2 * $gi->record_length * $offset,
614 2 * $gi->record_length);
616 mb_internal_encoding($enc);
617 } elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
618 $buf = @shmop_read ($gi->shmid,
619 2 * $gi->record_length * $offset,
620 2 * $gi->record_length );
622 fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
623 or die("fseek failed");
624 $buf = fread($gi->filehandle, 2 * $gi->record_length);
627 for ($i = 0; $i < 2; ++$i) {
628 for ($j = 0; $j < $gi->record_length; ++$j) {
629 $x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
632 if ($ipnum & (1 << $depth)) {
633 if ($x[1] >= $gi->databaseSegments) {
638 if ($x[0] >= $gi->databaseSegments) {
644 trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR);
649 if( !function_exists( '_common_get_org' ) ) {
650 function _common_get_org($gi, $seek_org){
651 $record_pointer = $seek_org + (2 * $gi->record_length - 1) * $gi->databaseSegments;
652 if ($gi->flags & GEOIP_SHARED_MEMORY) {
653 $org_buf = @shmop_read ($gi->shmid, $record_pointer, MAX_ORG_RECORD_LENGTH);
655 fseek($gi->filehandle, $record_pointer, SEEK_SET);
656 $org_buf = fread($gi->filehandle,MAX_ORG_RECORD_LENGTH);
658 // workaround php's broken substr, strpos, etc handling with
659 // mbstring.func_overload and mbstring.internal_encoding
660 $enc = mb_internal_encoding();
661 mb_internal_encoding('ISO-8859-1');
662 $org_buf = substr($org_buf, 0, strpos($org_buf, "\0"));
663 mb_internal_encoding($enc);
668 if( !function_exists( '_get_org_v6' ) ) {
669 function _get_org_v6($gi,$ipnum){
670 $seek_org = _geoip_seek_country_v6($gi,$ipnum);
671 if ($seek_org == $gi->databaseSegments) {
674 return _common_get_org($gi, $seek_org);
678 if( !function_exists( '_get_org' ) ) {
679 function _get_org($gi,$ipnum){
680 $seek_org = _geoip_seek_country($gi,$ipnum);
681 if ($seek_org == $gi->databaseSegments) {
684 return _common_get_org($gi, $seek_org);
690 if( !function_exists( 'geoip_name_by_addr_v6' ) ) {
691 function geoip_name_by_addr_v6 ($gi,$addr) {
695 $ipnum = inet_pton($addr);
696 return _get_org_v6($gi, $ipnum);
700 if( !function_exists( 'geoip_name_by_addr' ) ) {
701 function geoip_name_by_addr ($gi,$addr) {
705 $ipnum = ip2long($addr);
706 return _get_org($gi, $ipnum);
710 if( !function_exists( 'geoip_org_by_addr' ) ) {
711 function geoip_org_by_addr ($gi,$addr) {
712 return geoip_name_by_addr($gi, $addr);
716 if( !function_exists( '_get_region' ) ) {
717 function _get_region($gi,$ipnum){
718 if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){
719 $seek_region = _geoip_seek_country($gi,$ipnum) - GEOIP_STATE_BEGIN_REV0;
720 if ($seek_region >= 1000){
721 $country_code = "US";
722 $region = chr(($seek_region - 1000)/26 + 65) . chr(($seek_region - 1000)%26 + 65);
724 $country_code = $gi->GEOIP_COUNTRY_CODES[$seek_region];
727 return array ($country_code,$region);
728 } else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
729 $seek_region = _geoip_seek_country($gi,$ipnum) - GEOIP_STATE_BEGIN_REV1;
730 //print $seek_region;
731 if ($seek_region < US_OFFSET){
734 } else if ($seek_region < CANADA_OFFSET) {
735 $country_code = "US";
736 $region = chr(($seek_region - US_OFFSET)/26 + 65) . chr(($seek_region - US_OFFSET)%26 + 65);
737 } else if ($seek_region < WORLD_OFFSET) {
738 $country_code = "CA";
739 $region = chr(($seek_region - CANADA_OFFSET)/26 + 65) . chr(($seek_region - CANADA_OFFSET)%26 + 65);
741 $country_code = $gi->GEOIP_COUNTRY_CODES[($seek_region - WORLD_OFFSET) / FIPS_RANGE];
744 return array ($country_code,$region);
749 if( !function_exists( 'geoip_region_by_addr' ) ) {
750 function geoip_region_by_addr ($gi,$addr) {
754 $ipnum = ip2long($addr);
755 return _get_region($gi, $ipnum);
759 if( !function_exists( 'getdnsattributes' ) ) {
760 function getdnsattributes ($l,$ip){
761 $r = new Net_DNS_Resolver();
762 $r->nameservers = array("ws1.maxmind.com");
763 $p = $r->search($l."." . $ip .".s.maxmind.com","TXT","IN");
764 $str = is_object($p->answer[0])?$p->answer[0]->string():'';
765 $str = substr( $str, 1, -1 );