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