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);
61 var $databaseSegments;
64 var $GEOIP_COUNTRY_CODE_TO_NUMBER = array(
65 "" => 0, "AP" => 1, "EU" => 2, "AD" => 3, "AE" => 4, "AF" => 5,
66 "AG" => 6, "AI" => 7, "AL" => 8, "AM" => 9, "AN" => 10, "AO" => 11,
67 "AQ" => 12, "AR" => 13, "AS" => 14, "AT" => 15, "AU" => 16, "AW" => 17,
68 "AZ" => 18, "BA" => 19, "BB" => 20, "BD" => 21, "BE" => 22, "BF" => 23,
69 "BG" => 24, "BH" => 25, "BI" => 26, "BJ" => 27, "BM" => 28, "BN" => 29,
70 "BO" => 30, "BR" => 31, "BS" => 32, "BT" => 33, "BV" => 34, "BW" => 35,
71 "BY" => 36, "BZ" => 37, "CA" => 38, "CC" => 39, "CD" => 40, "CF" => 41,
72 "CG" => 42, "CH" => 43, "CI" => 44, "CK" => 45, "CL" => 46, "CM" => 47,
73 "CN" => 48, "CO" => 49, "CR" => 50, "CU" => 51, "CV" => 52, "CX" => 53,
74 "CY" => 54, "CZ" => 55, "DE" => 56, "DJ" => 57, "DK" => 58, "DM" => 59,
75 "DO" => 60, "DZ" => 61, "EC" => 62, "EE" => 63, "EG" => 64, "EH" => 65,
76 "ER" => 66, "ES" => 67, "ET" => 68, "FI" => 69, "FJ" => 70, "FK" => 71,
77 "FM" => 72, "FO" => 73, "FR" => 74, "FX" => 75, "GA" => 76, "GB" => 77,
78 "GD" => 78, "GE" => 79, "GF" => 80, "GH" => 81, "GI" => 82, "GL" => 83,
79 "GM" => 84, "GN" => 85, "GP" => 86, "GQ" => 87, "GR" => 88, "GS" => 89,
80 "GT" => 90, "GU" => 91, "GW" => 92, "GY" => 93, "HK" => 94, "HM" => 95,
81 "HN" => 96, "HR" => 97, "HT" => 98, "HU" => 99, "ID" => 100, "IE" => 101,
82 "IL" => 102, "IN" => 103, "IO" => 104, "IQ" => 105, "IR" => 106, "IS" => 107,
83 "IT" => 108, "JM" => 109, "JO" => 110, "JP" => 111, "KE" => 112, "KG" => 113,
84 "KH" => 114, "KI" => 115, "KM" => 116, "KN" => 117, "KP" => 118, "KR" => 119,
85 "KW" => 120, "KY" => 121, "KZ" => 122, "LA" => 123, "LB" => 124, "LC" => 125,
86 "LI" => 126, "LK" => 127, "LR" => 128, "LS" => 129, "LT" => 130, "LU" => 131,
87 "LV" => 132, "LY" => 133, "MA" => 134, "MC" => 135, "MD" => 136, "MG" => 137,
88 "MH" => 138, "MK" => 139, "ML" => 140, "MM" => 141, "MN" => 142, "MO" => 143,
89 "MP" => 144, "MQ" => 145, "MR" => 146, "MS" => 147, "MT" => 148, "MU" => 149,
90 "MV" => 150, "MW" => 151, "MX" => 152, "MY" => 153, "MZ" => 154, "NA" => 155,
91 "NC" => 156, "NE" => 157, "NF" => 158, "NG" => 159, "NI" => 160, "NL" => 161,
92 "NO" => 162, "NP" => 163, "NR" => 164, "NU" => 165, "NZ" => 166, "OM" => 167,
93 "PA" => 168, "PE" => 169, "PF" => 170, "PG" => 171, "PH" => 172, "PK" => 173,
94 "PL" => 174, "PM" => 175, "PN" => 176, "PR" => 177, "PS" => 178, "PT" => 179,
95 "PW" => 180, "PY" => 181, "QA" => 182, "RE" => 183, "RO" => 184, "RU" => 185,
96 "RW" => 186, "SA" => 187, "SB" => 188, "SC" => 189, "SD" => 190, "SE" => 191,
97 "SG" => 192, "SH" => 193, "SI" => 194, "SJ" => 195, "SK" => 196, "SL" => 197,
98 "SM" => 198, "SN" => 199, "SO" => 200, "SR" => 201, "ST" => 202, "SV" => 203,
99 "SY" => 204, "SZ" => 205, "TC" => 206, "TD" => 207, "TF" => 208, "TG" => 209,
100 "TH" => 210, "TJ" => 211, "TK" => 212, "TM" => 213, "TN" => 214, "TO" => 215,
101 "TL" => 216, "TR" => 217, "TT" => 218, "TV" => 219, "TW" => 220, "TZ" => 221,
102 "UA" => 222, "UG" => 223, "UM" => 224, "US" => 225, "UY" => 226, "UZ" => 227,
103 "VA" => 228, "VC" => 229, "VE" => 230, "VG" => 231, "VI" => 232, "VN" => 233,
104 "VU" => 234, "WF" => 235, "WS" => 236, "YE" => 237, "YT" => 238, "RS" => 239,
105 "ZA" => 240, "ZM" => 241, "ME" => 242, "ZW" => 243, "A1" => 244, "A2" => 245,
106 "O1" => 246, "AX" => 247, "GG" => 248, "IM" => 249, "JE" => 250, "BL" => 251,
109 var $GEOIP_COUNTRY_CODES = array(
110 "", "AP", "EU", "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ",
111 "AR", "AS", "AT", "AU", "AW", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH",
112 "BI", "BJ", "BM", "BN", "BO", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA",
113 "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CU",
114 "CV", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG",
115 "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "FX", "GA", "GB",
116 "GD", "GE", "GF", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT",
117 "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IN",
118 "IO", "IQ", "IR", "IS", "IT", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM",
119 "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS",
120 "LT", "LU", "LV", "LY", "MA", "MC", "MD", "MG", "MH", "MK", "ML", "MM", "MN",
121 "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA",
122 "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA",
123 "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY",
124 "QA", "RE", "RO", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI",
125 "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "ST", "SV", "SY", "SZ", "TC", "TD",
126 "TF", "TG", "TH", "TJ", "TK", "TM", "TN", "TO", "TL", "TR", "TT", "TV", "TW",
127 "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN",
128 "VU", "WF", "WS", "YE", "YT", "RS", "ZA", "ZM", "ME", "ZW", "A1", "A2", "O1",
129 "AX", "GG", "IM", "JE", "BL", "MF"
131 var $GEOIP_COUNTRY_CODES3 = array(
132 "","AP","EU","AND","ARE","AFG","ATG","AIA","ALB","ARM","ANT","AGO","AQ","ARG",
133 "ASM","AUT","AUS","ABW","AZE","BIH","BRB","BGD","BEL","BFA","BGR","BHR","BDI",
134 "BEN","BMU","BRN","BOL","BRA","BHS","BTN","BV","BWA","BLR","BLZ","CAN","CC",
135 "COD","CAF","COG","CHE","CIV","COK","CHL","CMR","CHN","COL","CRI","CUB","CPV",
136 "CX","CYP","CZE","DEU","DJI","DNK","DMA","DOM","DZA","ECU","EST","EGY","ESH",
137 "ERI","ESP","ETH","FIN","FJI","FLK","FSM","FRO","FRA","FX","GAB","GBR","GRD",
138 "GEO","GUF","GHA","GIB","GRL","GMB","GIN","GLP","GNQ","GRC","GS","GTM","GUM",
139 "GNB","GUY","HKG","HM","HND","HRV","HTI","HUN","IDN","IRL","ISR","IND","IO",
140 "IRQ","IRN","ISL","ITA","JAM","JOR","JPN","KEN","KGZ","KHM","KIR","COM","KNA",
141 "PRK","KOR","KWT","CYM","KAZ","LAO","LBN","LCA","LIE","LKA","LBR","LSO","LTU",
142 "LUX","LVA","LBY","MAR","MCO","MDA","MDG","MHL","MKD","MLI","MMR","MNG","MAC",
143 "MNP","MTQ","MRT","MSR","MLT","MUS","MDV","MWI","MEX","MYS","MOZ","NAM","NCL",
144 "NER","NFK","NGA","NIC","NLD","NOR","NPL","NRU","NIU","NZL","OMN","PAN","PER",
145 "PYF","PNG","PHL","PAK","POL","SPM","PCN","PRI","PSE","PRT","PLW","PRY","QAT",
146 "REU","ROU","RUS","RWA","SAU","SLB","SYC","SDN","SWE","SGP","SHN","SVN","SJM",
147 "SVK","SLE","SMR","SEN","SOM","SUR","STP","SLV","SYR","SWZ","TCA","TCD","TF",
148 "TGO","THA","TJK","TKL","TLS","TKM","TUN","TON","TUR","TTO","TUV","TWN","TZA",
149 "UKR","UGA","UM","USA","URY","UZB","VAT","VCT","VEN","VGB","VIR","VNM","VUT",
150 "WLF","WSM","YEM","YT","SRB","ZAF","ZMB","MNE","ZWE","A1","A2","O1",
151 "ALA","GGY","IMN","JEY","BLM","MAF"
153 var $GEOIP_COUNTRY_NAMES = array(
154 "", "Asia/Pacific Region", "Europe", "Andorra", "United Arab Emirates",
155 "Afghanistan", "Antigua and Barbuda", "Anguilla", "Albania", "Armenia",
156 "Netherlands Antilles", "Angola", "Antarctica", "Argentina", "American Samoa",
157 "Austria", "Australia", "Aruba", "Azerbaijan", "Bosnia and Herzegovina",
158 "Barbados", "Bangladesh", "Belgium", "Burkina Faso", "Bulgaria", "Bahrain",
159 "Burundi", "Benin", "Bermuda", "Brunei Darussalam", "Bolivia", "Brazil",
160 "Bahamas", "Bhutan", "Bouvet Island", "Botswana", "Belarus", "Belize",
161 "Canada", "Cocos (Keeling) Islands", "Congo, The Democratic Republic of the",
162 "Central African Republic", "Congo", "Switzerland", "Cote D'Ivoire", "Cook Islands",
163 "Chile", "Cameroon", "China", "Colombia", "Costa Rica", "Cuba", "Cape Verde",
164 "Christmas Island", "Cyprus", "Czech Republic", "Germany", "Djibouti",
165 "Denmark", "Dominica", "Dominican Republic", "Algeria", "Ecuador", "Estonia",
166 "Egypt", "Western Sahara", "Eritrea", "Spain", "Ethiopia", "Finland", "Fiji",
167 "Falkland Islands (Malvinas)", "Micronesia, Federated States of", "Faroe Islands",
168 "France", "France, Metropolitan", "Gabon", "United Kingdom",
169 "Grenada", "Georgia", "French Guiana", "Ghana", "Gibraltar", "Greenland",
170 "Gambia", "Guinea", "Guadeloupe", "Equatorial Guinea", "Greece", "South Georgia and the South Sandwich Islands",
171 "Guatemala", "Guam", "Guinea-Bissau",
172 "Guyana", "Hong Kong", "Heard Island and McDonald Islands", "Honduras",
173 "Croatia", "Haiti", "Hungary", "Indonesia", "Ireland", "Israel", "India",
174 "British Indian Ocean Territory", "Iraq", "Iran, Islamic Republic of",
175 "Iceland", "Italy", "Jamaica", "Jordan", "Japan", "Kenya", "Kyrgyzstan",
176 "Cambodia", "Kiribati", "Comoros", "Saint Kitts and Nevis", "Korea, Democratic People's Republic of",
177 "Korea, Republic of", "Kuwait", "Cayman Islands",
178 "Kazakhstan", "Lao People's Democratic Republic", "Lebanon", "Saint Lucia",
179 "Liechtenstein", "Sri Lanka", "Liberia", "Lesotho", "Lithuania", "Luxembourg",
180 "Latvia", "Libyan Arab Jamahiriya", "Morocco", "Monaco", "Moldova, Republic of",
181 "Madagascar", "Marshall Islands", "Macedonia",
182 "Mali", "Myanmar", "Mongolia", "Macau", "Northern Mariana Islands",
183 "Martinique", "Mauritania", "Montserrat", "Malta", "Mauritius", "Maldives",
184 "Malawi", "Mexico", "Malaysia", "Mozambique", "Namibia", "New Caledonia",
185 "Niger", "Norfolk Island", "Nigeria", "Nicaragua", "Netherlands", "Norway",
186 "Nepal", "Nauru", "Niue", "New Zealand", "Oman", "Panama", "Peru", "French Polynesia",
187 "Papua New Guinea", "Philippines", "Pakistan", "Poland", "Saint Pierre and Miquelon",
188 "Pitcairn Islands", "Puerto Rico", "Palestinian Territory",
189 "Portugal", "Palau", "Paraguay", "Qatar", "Reunion", "Romania",
190 "Russian Federation", "Rwanda", "Saudi Arabia", "Solomon Islands",
191 "Seychelles", "Sudan", "Sweden", "Singapore", "Saint Helena", "Slovenia",
192 "Svalbard and Jan Mayen", "Slovakia", "Sierra Leone", "San Marino", "Senegal",
193 "Somalia", "Suriname", "Sao Tome and Principe", "El Salvador", "Syrian Arab Republic",
194 "Swaziland", "Turks and Caicos Islands", "Chad", "French Southern Territories",
195 "Togo", "Thailand", "Tajikistan", "Tokelau", "Turkmenistan",
196 "Tunisia", "Tonga", "Timor-Leste", "Turkey", "Trinidad and Tobago", "Tuvalu",
197 "Taiwan", "Tanzania, United Republic of", "Ukraine",
198 "Uganda", "United States Minor Outlying Islands", "United States", "Uruguay",
199 "Uzbekistan", "Holy See (Vatican City State)", "Saint Vincent and the Grenadines",
200 "Venezuela", "Virgin Islands, British", "Virgin Islands, U.S.",
201 "Vietnam", "Vanuatu", "Wallis and Futuna", "Samoa", "Yemen", "Mayotte",
202 "Serbia", "South Africa", "Zambia", "Montenegro", "Zimbabwe",
203 "Anonymous Proxy","Satellite Provider","Other",
204 "Aland Islands","Guernsey","Isle of Man","Jersey","Saint Barthelemy","Saint Martin"
207 function geoip_load_shared_mem ($file) {
209 $fp = fopen($file, "rb");
211 print "error opening $file: $php_errormsg\n";
214 $s_array = fstat($fp);
215 $size = $s_array['size'];
216 if ($shmid = @shmop_open (GEOIP_SHM_KEY, "w", 0, 0)) {
217 shmop_delete ($shmid);
218 shmop_close ($shmid);
220 $shmid = shmop_open (GEOIP_SHM_KEY, "c", 0644, $size);
221 shmop_write ($shmid, fread($fp, $size), 0);
222 shmop_close ($shmid);
225 function _setup_segments($gi){
226 $gi->databaseType = GEOIP_COUNTRY_EDITION;
227 $gi->record_length = STANDARD_RECORD_LENGTH;
228 if ($gi->flags & GEOIP_SHARED_MEMORY) {
229 $offset = @shmop_size ($gi->shmid) - 3;
230 for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
231 $delim = @shmop_read ($gi->shmid, $offset, 3);
233 if ($delim == (chr(255).chr(255).chr(255))) {
234 $gi->databaseType = ord(@shmop_read ($gi->shmid, $offset, 1));
237 if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){
238 $gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
239 } else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1){
240 $gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
241 } else if (($gi->databaseType == GEOIP_CITY_EDITION_REV0)||
242 ($gi->databaseType == GEOIP_CITY_EDITION_REV1)
243 || ($gi->databaseType == GEOIP_ORG_EDITION)
244 || ($gi->databaseType == GEOIP_ISP_EDITION)
245 || ($gi->databaseType == GEOIP_ASNUM_EDITION)){
246 $gi->databaseSegments = 0;
247 $buf = @shmop_read ($gi->shmid, $offset, SEGMENT_RECORD_LENGTH);
248 for ($j = 0;$j < SEGMENT_RECORD_LENGTH;$j++){
249 $gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
251 if (($gi->databaseType == GEOIP_ORG_EDITION)||
252 ($gi->databaseType == GEOIP_ISP_EDITION)) {
253 $gi->record_length = ORG_RECORD_LENGTH;
261 if (($gi->databaseType == GEOIP_COUNTRY_EDITION)||
262 ($gi->databaseType == GEOIP_PROXY_EDITION)||
263 ($gi->databaseType == GEOIP_NETSPEED_EDITION)){
264 $gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
267 $filepos = ftell($gi->filehandle);
268 fseek($gi->filehandle, -3, SEEK_END);
269 for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
270 $delim = fread($gi->filehandle,3);
271 if ($delim == (chr(255).chr(255).chr(255))){
272 $gi->databaseType = ord(fread($gi->filehandle,1));
273 if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){
274 $gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
276 else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1){
277 $gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
278 } else if (($gi->databaseType == GEOIP_CITY_EDITION_REV0) ||
279 ($gi->databaseType == GEOIP_CITY_EDITION_REV1) ||
280 ($gi->databaseType == GEOIP_ORG_EDITION) ||
281 ($gi->databaseType == GEOIP_ISP_EDITION) ||
282 ($gi->databaseType == GEOIP_ASNUM_EDITION)){
283 $gi->databaseSegments = 0;
284 $buf = fread($gi->filehandle,SEGMENT_RECORD_LENGTH);
285 for ($j = 0;$j < SEGMENT_RECORD_LENGTH;$j++){
286 $gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
288 if ($gi->databaseType == GEOIP_ORG_EDITION ||
289 $gi->databaseType == GEOIP_ISP_EDITION) {
290 $gi->record_length = ORG_RECORD_LENGTH;
295 fseek($gi->filehandle, -4, SEEK_CUR);
298 if (($gi->databaseType == GEOIP_COUNTRY_EDITION)||
299 ($gi->databaseType == GEOIP_PROXY_EDITION)||
300 ($gi->databaseType == GEOIP_NETSPEED_EDITION)){
301 $gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
303 fseek($gi->filehandle,$filepos,SEEK_SET);
308 function geoip_open($filename, $flags) {
311 if ($gi->flags & GEOIP_SHARED_MEMORY) {
312 $gi->shmid = @shmop_open (GEOIP_SHM_KEY, "a", 0, 0);
314 $gi->filehandle = fopen($filename,"rb") or die( "Can not open $filename\n" );
315 if ($gi->flags & GEOIP_MEMORY_CACHE) {
316 $s_array = fstat($gi->filehandle);
317 $gi->memory_buffer = fread($gi->filehandle, $s_array['size']);
321 $gi = _setup_segments($gi);
325 function geoip_close($gi) {
326 if ($gi->flags & GEOIP_SHARED_MEMORY) {
330 return fclose($gi->filehandle);
333 function geoip_country_id_by_name($gi, $name) {
334 $addr = gethostbyname($name);
335 if (!$addr || $addr == $name) {
338 return geoip_country_id_by_addr($gi, $addr);
341 function geoip_country_code_by_name($gi, $name) {
342 $country_id = geoip_country_id_by_name($gi,$name);
343 if ($country_id !== false) {
344 return $gi->GEOIP_COUNTRY_CODES[$country_id];
349 function geoip_country_name_by_name($gi, $name) {
350 $country_id = geoip_country_id_by_name($gi,$name);
351 if ($country_id !== false) {
352 return $gi->GEOIP_COUNTRY_NAMES[$country_id];
357 function geoip_country_id_by_addr($gi, $addr) {
358 $ipnum = ip2long($addr);
359 return _geoip_seek_country($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
362 function geoip_country_code_by_addr($gi, $addr) {
363 if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
364 $record = geoip_record_by_addr($gi,$addr);
365 if ( $record !== false ) {
366 return $record->country_code;
369 $country_id = geoip_country_id_by_addr($gi,$addr);
370 if ($country_id !== false) {
371 return $gi->GEOIP_COUNTRY_CODES[$country_id];
377 function geoip_country_name_by_addr($gi, $addr) {
378 if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
379 $record = geoip_record_by_addr($gi,$addr);
380 return $record->country_name;
382 $country_id = geoip_country_id_by_addr($gi,$addr);
383 if ($country_id !== false) {
384 return $gi->GEOIP_COUNTRY_NAMES[$country_id];
390 function _geoip_seek_country($gi, $ipnum) {
392 for ($depth = 31; $depth >= 0; --$depth) {
393 if ($gi->flags & GEOIP_MEMORY_CACHE) {
394 $buf = substr($gi->memory_buffer,
395 2 * $gi->record_length * $offset,
396 2 * $gi->record_length);
397 } elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
398 $buf = @shmop_read ($gi->shmid,
399 2 * $gi->record_length * $offset,
400 2 * $gi->record_length );
402 fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
403 or die("fseek failed");
404 $buf = fread($gi->filehandle, 2 * $gi->record_length);
407 for ($i = 0; $i < 2; ++$i) {
408 for ($j = 0; $j < $gi->record_length; ++$j) {
409 $x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
412 if ($ipnum & (1 << $depth)) {
413 if ($x[1] >= $gi->databaseSegments) {
418 if ($x[0] >= $gi->databaseSegments) {
424 trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR);
428 function _get_org($gi,$ipnum){
429 $seek_org = _geoip_seek_country($gi,$ipnum);
430 if ($seek_org == $gi->databaseSegments) {
433 $record_pointer = $seek_org + (2 * $gi->record_length - 1) * $gi->databaseSegments;
434 if ($gi->flags & GEOIP_SHARED_MEMORY) {
435 $org_buf = @shmop_read ($gi->shmid, $record_pointer, MAX_ORG_RECORD_LENGTH);
437 fseek($gi->filehandle, $record_pointer, SEEK_SET);
438 $org_buf = fread($gi->filehandle,MAX_ORG_RECORD_LENGTH);
440 $org_buf = substr($org_buf, 0, strpos($org_buf, 0));
444 function geoip_org_by_addr ($gi,$addr) {
448 $ipnum = ip2long($addr);
449 return _get_org($gi, $ipnum);
452 function _get_region($gi,$ipnum){
453 if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){
454 $seek_region = _geoip_seek_country($gi,$ipnum) - GEOIP_STATE_BEGIN_REV0;
455 if ($seek_region >= 1000){
456 $country_code = "US";
457 $region = chr(($seek_region - 1000)/26 + 65) . chr(($seek_region - 1000)%26 + 65);
459 $country_code = $gi->GEOIP_COUNTRY_CODES[$seek_region];
462 return array ($country_code,$region);
463 } else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
464 $seek_region = _geoip_seek_country($gi,$ipnum) - GEOIP_STATE_BEGIN_REV1;
465 //print $seek_region;
466 if ($seek_region < US_OFFSET){
469 } else if ($seek_region < CANADA_OFFSET) {
470 $country_code = "US";
471 $region = chr(($seek_region - US_OFFSET)/26 + 65) . chr(($seek_region - US_OFFSET)%26 + 65);
472 } else if ($seek_region < WORLD_OFFSET) {
473 $country_code = "CA";
474 $region = chr(($seek_region - CANADA_OFFSET)/26 + 65) . chr(($seek_region - CANADA_OFFSET)%26 + 65);
476 $country_code = $gi->GEOIP_COUNTRY_CODES[($seek_region - WORLD_OFFSET) / FIPS_RANGE];
479 return array ($country_code,$region);
483 function geoip_region_by_addr ($gi,$addr) {
487 $ipnum = ip2long($addr);
488 return _get_region($gi, $ipnum);
491 function getdnsattributes ($l,$ip){
492 $r = new Net_DNS_Resolver();
493 $r->nameservers = array("ws1.maxmind.com");
494 $p = $r->search($l."." . $ip .".s.maxmind.com","TXT","IN");
495 $str = is_object($p->answer[0])?$p->answer[0]->string():'';
496 ereg("\"(.*)\"",$str,$regs);