]> CyberLeo.Net >> Repos - Github/YOURLS.git/blob - includes/geo/geoip.inc
Update GeoIP
[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", 1);
32 define("GEOIP_PROXY_EDITION", 8);
33 define("GEOIP_ASNUM_EDITION", 9);
34 define("GEOIP_NETSPEED_EDITION", 10);
35 define("GEOIP_REGION_EDITION_REV0", 7);
36 define("GEOIP_REGION_EDITION_REV1", 3);
37 define("GEOIP_CITY_EDITION_REV0", 6);
38 define("GEOIP_CITY_EDITION_REV1", 2);
39 define("GEOIP_ORG_EDITION", 5);
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);
70
71 define("CITYCOMBINED_FIXED_RECORD", 7);
72
73 class GeoIP
74 {
75     public $flags;
76     public $filehandle;
77     public $memory_buffer;
78     public $databaseType;
79     public $databaseSegments;
80     public $record_length;
81     public $shmid;
82     public $GEOIP_COUNTRY_CODE_TO_NUMBER = array(
83         "" => 0,
84         "AP" => 1,
85         "EU" => 2,
86         "AD" => 3,
87         "AE" => 4,
88         "AF" => 5,
89         "AG" => 6,
90         "AI" => 7,
91         "AL" => 8,
92         "AM" => 9,
93         "CW" => 10,
94         "AO" => 11,
95         "AQ" => 12,
96         "AR" => 13,
97         "AS" => 14,
98         "AT" => 15,
99         "AU" => 16,
100         "AW" => 17,
101         "AZ" => 18,
102         "BA" => 19,
103         "BB" => 20,
104         "BD" => 21,
105         "BE" => 22,
106         "BF" => 23,
107         "BG" => 24,
108         "BH" => 25,
109         "BI" => 26,
110         "BJ" => 27,
111         "BM" => 28,
112         "BN" => 29,
113         "BO" => 30,
114         "BR" => 31,
115         "BS" => 32,
116         "BT" => 33,
117         "BV" => 34,
118         "BW" => 35,
119         "BY" => 36,
120         "BZ" => 37,
121         "CA" => 38,
122         "CC" => 39,
123         "CD" => 40,
124         "CF" => 41,
125         "CG" => 42,
126         "CH" => 43,
127         "CI" => 44,
128         "CK" => 45,
129         "CL" => 46,
130         "CM" => 47,
131         "CN" => 48,
132         "CO" => 49,
133         "CR" => 50,
134         "CU" => 51,
135         "CV" => 52,
136         "CX" => 53,
137         "CY" => 54,
138         "CZ" => 55,
139         "DE" => 56,
140         "DJ" => 57,
141         "DK" => 58,
142         "DM" => 59,
143         "DO" => 60,
144         "DZ" => 61,
145         "EC" => 62,
146         "EE" => 63,
147         "EG" => 64,
148         "EH" => 65,
149         "ER" => 66,
150         "ES" => 67,
151         "ET" => 68,
152         "FI" => 69,
153         "FJ" => 70,
154         "FK" => 71,
155         "FM" => 72,
156         "FO" => 73,
157         "FR" => 74,
158         "SX" => 75,
159         "GA" => 76,
160         "GB" => 77,
161         "GD" => 78,
162         "GE" => 79,
163         "GF" => 80,
164         "GH" => 81,
165         "GI" => 82,
166         "GL" => 83,
167         "GM" => 84,
168         "GN" => 85,
169         "GP" => 86,
170         "GQ" => 87,
171         "GR" => 88,
172         "GS" => 89,
173         "GT" => 90,
174         "GU" => 91,
175         "GW" => 92,
176         "GY" => 93,
177         "HK" => 94,
178         "HM" => 95,
179         "HN" => 96,
180         "HR" => 97,
181         "HT" => 98,
182         "HU" => 99,
183         "ID" => 100,
184         "IE" => 101,
185         "IL" => 102,
186         "IN" => 103,
187         "IO" => 104,
188         "IQ" => 105,
189         "IR" => 106,
190         "IS" => 107,
191         "IT" => 108,
192         "JM" => 109,
193         "JO" => 110,
194         "JP" => 111,
195         "KE" => 112,
196         "KG" => 113,
197         "KH" => 114,
198         "KI" => 115,
199         "KM" => 116,
200         "KN" => 117,
201         "KP" => 118,
202         "KR" => 119,
203         "KW" => 120,
204         "KY" => 121,
205         "KZ" => 122,
206         "LA" => 123,
207         "LB" => 124,
208         "LC" => 125,
209         "LI" => 126,
210         "LK" => 127,
211         "LR" => 128,
212         "LS" => 129,
213         "LT" => 130,
214         "LU" => 131,
215         "LV" => 132,
216         "LY" => 133,
217         "MA" => 134,
218         "MC" => 135,
219         "MD" => 136,
220         "MG" => 137,
221         "MH" => 138,
222         "MK" => 139,
223         "ML" => 140,
224         "MM" => 141,
225         "MN" => 142,
226         "MO" => 143,
227         "MP" => 144,
228         "MQ" => 145,
229         "MR" => 146,
230         "MS" => 147,
231         "MT" => 148,
232         "MU" => 149,
233         "MV" => 150,
234         "MW" => 151,
235         "MX" => 152,
236         "MY" => 153,
237         "MZ" => 154,
238         "NA" => 155,
239         "NC" => 156,
240         "NE" => 157,
241         "NF" => 158,
242         "NG" => 159,
243         "NI" => 160,
244         "NL" => 161,
245         "NO" => 162,
246         "NP" => 163,
247         "NR" => 164,
248         "NU" => 165,
249         "NZ" => 166,
250         "OM" => 167,
251         "PA" => 168,
252         "PE" => 169,
253         "PF" => 170,
254         "PG" => 171,
255         "PH" => 172,
256         "PK" => 173,
257         "PL" => 174,
258         "PM" => 175,
259         "PN" => 176,
260         "PR" => 177,
261         "PS" => 178,
262         "PT" => 179,
263         "PW" => 180,
264         "PY" => 181,
265         "QA" => 182,
266         "RE" => 183,
267         "RO" => 184,
268         "RU" => 185,
269         "RW" => 186,
270         "SA" => 187,
271         "SB" => 188,
272         "SC" => 189,
273         "SD" => 190,
274         "SE" => 191,
275         "SG" => 192,
276         "SH" => 193,
277         "SI" => 194,
278         "SJ" => 195,
279         "SK" => 196,
280         "SL" => 197,
281         "SM" => 198,
282         "SN" => 199,
283         "SO" => 200,
284         "SR" => 201,
285         "ST" => 202,
286         "SV" => 203,
287         "SY" => 204,
288         "SZ" => 205,
289         "TC" => 206,
290         "TD" => 207,
291         "TF" => 208,
292         "TG" => 209,
293         "TH" => 210,
294         "TJ" => 211,
295         "TK" => 212,
296         "TM" => 213,
297         "TN" => 214,
298         "TO" => 215,
299         "TL" => 216,
300         "TR" => 217,
301         "TT" => 218,
302         "TV" => 219,
303         "TW" => 220,
304         "TZ" => 221,
305         "UA" => 222,
306         "UG" => 223,
307         "UM" => 224,
308         "US" => 225,
309         "UY" => 226,
310         "UZ" => 227,
311         "VA" => 228,
312         "VC" => 229,
313         "VE" => 230,
314         "VG" => 231,
315         "VI" => 232,
316         "VN" => 233,
317         "VU" => 234,
318         "WF" => 235,
319         "WS" => 236,
320         "YE" => 237,
321         "YT" => 238,
322         "RS" => 239,
323         "ZA" => 240,
324         "ZM" => 241,
325         "ME" => 242,
326         "ZW" => 243,
327         "A1" => 244,
328         "A2" => 245,
329         "O1" => 246,
330         "AX" => 247,
331         "GG" => 248,
332         "IM" => 249,
333         "JE" => 250,
334         "BL" => 251,
335         "MF" => 252,
336         "BQ" => 253,
337         "SS" => 254
338     );
339
340     public $GEOIP_COUNTRY_CODES = array(
341         "",
342         "AP",
343         "EU",
344         "AD",
345         "AE",
346         "AF",
347         "AG",
348         "AI",
349         "AL",
350         "AM",
351         "CW",
352         "AO",
353         "AQ",
354         "AR",
355         "AS",
356         "AT",
357         "AU",
358         "AW",
359         "AZ",
360         "BA",
361         "BB",
362         "BD",
363         "BE",
364         "BF",
365         "BG",
366         "BH",
367         "BI",
368         "BJ",
369         "BM",
370         "BN",
371         "BO",
372         "BR",
373         "BS",
374         "BT",
375         "BV",
376         "BW",
377         "BY",
378         "BZ",
379         "CA",
380         "CC",
381         "CD",
382         "CF",
383         "CG",
384         "CH",
385         "CI",
386         "CK",
387         "CL",
388         "CM",
389         "CN",
390         "CO",
391         "CR",
392         "CU",
393         "CV",
394         "CX",
395         "CY",
396         "CZ",
397         "DE",
398         "DJ",
399         "DK",
400         "DM",
401         "DO",
402         "DZ",
403         "EC",
404         "EE",
405         "EG",
406         "EH",
407         "ER",
408         "ES",
409         "ET",
410         "FI",
411         "FJ",
412         "FK",
413         "FM",
414         "FO",
415         "FR",
416         "SX",
417         "GA",
418         "GB",
419         "GD",
420         "GE",
421         "GF",
422         "GH",
423         "GI",
424         "GL",
425         "GM",
426         "GN",
427         "GP",
428         "GQ",
429         "GR",
430         "GS",
431         "GT",
432         "GU",
433         "GW",
434         "GY",
435         "HK",
436         "HM",
437         "HN",
438         "HR",
439         "HT",
440         "HU",
441         "ID",
442         "IE",
443         "IL",
444         "IN",
445         "IO",
446         "IQ",
447         "IR",
448         "IS",
449         "IT",
450         "JM",
451         "JO",
452         "JP",
453         "KE",
454         "KG",
455         "KH",
456         "KI",
457         "KM",
458         "KN",
459         "KP",
460         "KR",
461         "KW",
462         "KY",
463         "KZ",
464         "LA",
465         "LB",
466         "LC",
467         "LI",
468         "LK",
469         "LR",
470         "LS",
471         "LT",
472         "LU",
473         "LV",
474         "LY",
475         "MA",
476         "MC",
477         "MD",
478         "MG",
479         "MH",
480         "MK",
481         "ML",
482         "MM",
483         "MN",
484         "MO",
485         "MP",
486         "MQ",
487         "MR",
488         "MS",
489         "MT",
490         "MU",
491         "MV",
492         "MW",
493         "MX",
494         "MY",
495         "MZ",
496         "NA",
497         "NC",
498         "NE",
499         "NF",
500         "NG",
501         "NI",
502         "NL",
503         "NO",
504         "NP",
505         "NR",
506         "NU",
507         "NZ",
508         "OM",
509         "PA",
510         "PE",
511         "PF",
512         "PG",
513         "PH",
514         "PK",
515         "PL",
516         "PM",
517         "PN",
518         "PR",
519         "PS",
520         "PT",
521         "PW",
522         "PY",
523         "QA",
524         "RE",
525         "RO",
526         "RU",
527         "RW",
528         "SA",
529         "SB",
530         "SC",
531         "SD",
532         "SE",
533         "SG",
534         "SH",
535         "SI",
536         "SJ",
537         "SK",
538         "SL",
539         "SM",
540         "SN",
541         "SO",
542         "SR",
543         "ST",
544         "SV",
545         "SY",
546         "SZ",
547         "TC",
548         "TD",
549         "TF",
550         "TG",
551         "TH",
552         "TJ",
553         "TK",
554         "TM",
555         "TN",
556         "TO",
557         "TL",
558         "TR",
559         "TT",
560         "TV",
561         "TW",
562         "TZ",
563         "UA",
564         "UG",
565         "UM",
566         "US",
567         "UY",
568         "UZ",
569         "VA",
570         "VC",
571         "VE",
572         "VG",
573         "VI",
574         "VN",
575         "VU",
576         "WF",
577         "WS",
578         "YE",
579         "YT",
580         "RS",
581         "ZA",
582         "ZM",
583         "ME",
584         "ZW",
585         "A1",
586         "A2",
587         "O1",
588         "AX",
589         "GG",
590         "IM",
591         "JE",
592         "BL",
593         "MF",
594         "BQ",
595         "SS",
596         "O1"
597     );
598
599     public $GEOIP_COUNTRY_CODES3 = array(
600         "",
601         "AP",
602         "EU",
603         "AND",
604         "ARE",
605         "AFG",
606         "ATG",
607         "AIA",
608         "ALB",
609         "ARM",
610         "CUW",
611         "AGO",
612         "ATA",
613         "ARG",
614         "ASM",
615         "AUT",
616         "AUS",
617         "ABW",
618         "AZE",
619         "BIH",
620         "BRB",
621         "BGD",
622         "BEL",
623         "BFA",
624         "BGR",
625         "BHR",
626         "BDI",
627         "BEN",
628         "BMU",
629         "BRN",
630         "BOL",
631         "BRA",
632         "BHS",
633         "BTN",
634         "BVT",
635         "BWA",
636         "BLR",
637         "BLZ",
638         "CAN",
639         "CCK",
640         "COD",
641         "CAF",
642         "COG",
643         "CHE",
644         "CIV",
645         "COK",
646         "CHL",
647         "CMR",
648         "CHN",
649         "COL",
650         "CRI",
651         "CUB",
652         "CPV",
653         "CXR",
654         "CYP",
655         "CZE",
656         "DEU",
657         "DJI",
658         "DNK",
659         "DMA",
660         "DOM",
661         "DZA",
662         "ECU",
663         "EST",
664         "EGY",
665         "ESH",
666         "ERI",
667         "ESP",
668         "ETH",
669         "FIN",
670         "FJI",
671         "FLK",
672         "FSM",
673         "FRO",
674         "FRA",
675         "SXM",
676         "GAB",
677         "GBR",
678         "GRD",
679         "GEO",
680         "GUF",
681         "GHA",
682         "GIB",
683         "GRL",
684         "GMB",
685         "GIN",
686         "GLP",
687         "GNQ",
688         "GRC",
689         "SGS",
690         "GTM",
691         "GUM",
692         "GNB",
693         "GUY",
694         "HKG",
695         "HMD",
696         "HND",
697         "HRV",
698         "HTI",
699         "HUN",
700         "IDN",
701         "IRL",
702         "ISR",
703         "IND",
704         "IOT",
705         "IRQ",
706         "IRN",
707         "ISL",
708         "ITA",
709         "JAM",
710         "JOR",
711         "JPN",
712         "KEN",
713         "KGZ",
714         "KHM",
715         "KIR",
716         "COM",
717         "KNA",
718         "PRK",
719         "KOR",
720         "KWT",
721         "CYM",
722         "KAZ",
723         "LAO",
724         "LBN",
725         "LCA",
726         "LIE",
727         "LKA",
728         "LBR",
729         "LSO",
730         "LTU",
731         "LUX",
732         "LVA",
733         "LBY",
734         "MAR",
735         "MCO",
736         "MDA",
737         "MDG",
738         "MHL",
739         "MKD",
740         "MLI",
741         "MMR",
742         "MNG",
743         "MAC",
744         "MNP",
745         "MTQ",
746         "MRT",
747         "MSR",
748         "MLT",
749         "MUS",
750         "MDV",
751         "MWI",
752         "MEX",
753         "MYS",
754         "MOZ",
755         "NAM",
756         "NCL",
757         "NER",
758         "NFK",
759         "NGA",
760         "NIC",
761         "NLD",
762         "NOR",
763         "NPL",
764         "NRU",
765         "NIU",
766         "NZL",
767         "OMN",
768         "PAN",
769         "PER",
770         "PYF",
771         "PNG",
772         "PHL",
773         "PAK",
774         "POL",
775         "SPM",
776         "PCN",
777         "PRI",
778         "PSE",
779         "PRT",
780         "PLW",
781         "PRY",
782         "QAT",
783         "REU",
784         "ROU",
785         "RUS",
786         "RWA",
787         "SAU",
788         "SLB",
789         "SYC",
790         "SDN",
791         "SWE",
792         "SGP",
793         "SHN",
794         "SVN",
795         "SJM",
796         "SVK",
797         "SLE",
798         "SMR",
799         "SEN",
800         "SOM",
801         "SUR",
802         "STP",
803         "SLV",
804         "SYR",
805         "SWZ",
806         "TCA",
807         "TCD",
808         "ATF",
809         "TGO",
810         "THA",
811         "TJK",
812         "TKL",
813         "TKM",
814         "TUN",
815         "TON",
816         "TLS",
817         "TUR",
818         "TTO",
819         "TUV",
820         "TWN",
821         "TZA",
822         "UKR",
823         "UGA",
824         "UMI",
825         "USA",
826         "URY",
827         "UZB",
828         "VAT",
829         "VCT",
830         "VEN",
831         "VGB",
832         "VIR",
833         "VNM",
834         "VUT",
835         "WLF",
836         "WSM",
837         "YEM",
838         "MYT",
839         "SRB",
840         "ZAF",
841         "ZMB",
842         "MNE",
843         "ZWE",
844         "A1",
845         "A2",
846         "O1",
847         "ALA",
848         "GGY",
849         "IMN",
850         "JEY",
851         "BLM",
852         "MAF",
853         "BES",
854         "SSD",
855         "O1"
856     );
857
858     public $GEOIP_COUNTRY_NAMES = array(
859         "",
860         "Asia/Pacific Region",
861         "Europe",
862         "Andorra",
863         "United Arab Emirates",
864         "Afghanistan",
865         "Antigua and Barbuda",
866         "Anguilla",
867         "Albania",
868         "Armenia",
869         "Curacao",
870         "Angola",
871         "Antarctica",
872         "Argentina",
873         "American Samoa",
874         "Austria",
875         "Australia",
876         "Aruba",
877         "Azerbaijan",
878         "Bosnia and Herzegovina",
879         "Barbados",
880         "Bangladesh",
881         "Belgium",
882         "Burkina Faso",
883         "Bulgaria",
884         "Bahrain",
885         "Burundi",
886         "Benin",
887         "Bermuda",
888         "Brunei Darussalam",
889         "Bolivia",
890         "Brazil",
891         "Bahamas",
892         "Bhutan",
893         "Bouvet Island",
894         "Botswana",
895         "Belarus",
896         "Belize",
897         "Canada",
898         "Cocos (Keeling) Islands",
899         "Congo, The Democratic Republic of the",
900         "Central African Republic",
901         "Congo",
902         "Switzerland",
903         "Cote D'Ivoire",
904         "Cook Islands",
905         "Chile",
906         "Cameroon",
907         "China",
908         "Colombia",
909         "Costa Rica",
910         "Cuba",
911         "Cape Verde",
912         "Christmas Island",
913         "Cyprus",
914         "Czech Republic",
915         "Germany",
916         "Djibouti",
917         "Denmark",
918         "Dominica",
919         "Dominican Republic",
920         "Algeria",
921         "Ecuador",
922         "Estonia",
923         "Egypt",
924         "Western Sahara",
925         "Eritrea",
926         "Spain",
927         "Ethiopia",
928         "Finland",
929         "Fiji",
930         "Falkland Islands (Malvinas)",
931         "Micronesia, Federated States of",
932         "Faroe Islands",
933         "France",
934         "Sint Maarten (Dutch part)",
935         "Gabon",
936         "United Kingdom",
937         "Grenada",
938         "Georgia",
939         "French Guiana",
940         "Ghana",
941         "Gibraltar",
942         "Greenland",
943         "Gambia",
944         "Guinea",
945         "Guadeloupe",
946         "Equatorial Guinea",
947         "Greece",
948         "South Georgia and the South Sandwich Islands",
949         "Guatemala",
950         "Guam",
951         "Guinea-Bissau",
952         "Guyana",
953         "Hong Kong",
954         "Heard Island and McDonald Islands",
955         "Honduras",
956         "Croatia",
957         "Haiti",
958         "Hungary",
959         "Indonesia",
960         "Ireland",
961         "Israel",
962         "India",
963         "British Indian Ocean Territory",
964         "Iraq",
965         "Iran, Islamic Republic of",
966         "Iceland",
967         "Italy",
968         "Jamaica",
969         "Jordan",
970         "Japan",
971         "Kenya",
972         "Kyrgyzstan",
973         "Cambodia",
974         "Kiribati",
975         "Comoros",
976         "Saint Kitts and Nevis",
977         "Korea, Democratic People's Republic of",
978         "Korea, Republic of",
979         "Kuwait",
980         "Cayman Islands",
981         "Kazakhstan",
982         "Lao People's Democratic Republic",
983         "Lebanon",
984         "Saint Lucia",
985         "Liechtenstein",
986         "Sri Lanka",
987         "Liberia",
988         "Lesotho",
989         "Lithuania",
990         "Luxembourg",
991         "Latvia",
992         "Libya",
993         "Morocco",
994         "Monaco",
995         "Moldova, Republic of",
996         "Madagascar",
997         "Marshall Islands",
998         "Macedonia",
999         "Mali",
1000         "Myanmar",
1001         "Mongolia",
1002         "Macau",
1003         "Northern Mariana Islands",
1004         "Martinique",
1005         "Mauritania",
1006         "Montserrat",
1007         "Malta",
1008         "Mauritius",
1009         "Maldives",
1010         "Malawi",
1011         "Mexico",
1012         "Malaysia",
1013         "Mozambique",
1014         "Namibia",
1015         "New Caledonia",
1016         "Niger",
1017         "Norfolk Island",
1018         "Nigeria",
1019         "Nicaragua",
1020         "Netherlands",
1021         "Norway",
1022         "Nepal",
1023         "Nauru",
1024         "Niue",
1025         "New Zealand",
1026         "Oman",
1027         "Panama",
1028         "Peru",
1029         "French Polynesia",
1030         "Papua New Guinea",
1031         "Philippines",
1032         "Pakistan",
1033         "Poland",
1034         "Saint Pierre and Miquelon",
1035         "Pitcairn Islands",
1036         "Puerto Rico",
1037         "Palestinian Territory",
1038         "Portugal",
1039         "Palau",
1040         "Paraguay",
1041         "Qatar",
1042         "Reunion",
1043         "Romania",
1044         "Russian Federation",
1045         "Rwanda",
1046         "Saudi Arabia",
1047         "Solomon Islands",
1048         "Seychelles",
1049         "Sudan",
1050         "Sweden",
1051         "Singapore",
1052         "Saint Helena",
1053         "Slovenia",
1054         "Svalbard and Jan Mayen",
1055         "Slovakia",
1056         "Sierra Leone",
1057         "San Marino",
1058         "Senegal",
1059         "Somalia",
1060         "Suriname",
1061         "Sao Tome and Principe",
1062         "El Salvador",
1063         "Syrian Arab Republic",
1064         "Swaziland",
1065         "Turks and Caicos Islands",
1066         "Chad",
1067         "French Southern Territories",
1068         "Togo",
1069         "Thailand",
1070         "Tajikistan",
1071         "Tokelau",
1072         "Turkmenistan",
1073         "Tunisia",
1074         "Tonga",
1075         "Timor-Leste",
1076         "Turkey",
1077         "Trinidad and Tobago",
1078         "Tuvalu",
1079         "Taiwan",
1080         "Tanzania, United Republic of",
1081         "Ukraine",
1082         "Uganda",
1083         "United States Minor Outlying Islands",
1084         "United States",
1085         "Uruguay",
1086         "Uzbekistan",
1087         "Holy See (Vatican City State)",
1088         "Saint Vincent and the Grenadines",
1089         "Venezuela",
1090         "Virgin Islands, British",
1091         "Virgin Islands, U.S.",
1092         "Vietnam",
1093         "Vanuatu",
1094         "Wallis and Futuna",
1095         "Samoa",
1096         "Yemen",
1097         "Mayotte",
1098         "Serbia",
1099         "South Africa",
1100         "Zambia",
1101         "Montenegro",
1102         "Zimbabwe",
1103         "Anonymous Proxy",
1104         "Satellite Provider",
1105         "Other",
1106         "Aland Islands",
1107         "Guernsey",
1108         "Isle of Man",
1109         "Jersey",
1110         "Saint Barthelemy",
1111         "Saint Martin",
1112         "Bonaire, Saint Eustatius and Saba",
1113         "South Sudan",
1114         "Other"
1115     );
1116
1117     public $GEOIP_CONTINENT_CODES = array(
1118         "--",
1119         "AS",
1120         "EU",
1121         "EU",
1122         "AS",
1123         "AS",
1124         "NA",
1125         "NA",
1126         "EU",
1127         "AS",
1128         "NA",
1129         "AF",
1130         "AN",
1131         "SA",
1132         "OC",
1133         "EU",
1134         "OC",
1135         "NA",
1136         "AS",
1137         "EU",
1138         "NA",
1139         "AS",
1140         "EU",
1141         "AF",
1142         "EU",
1143         "AS",
1144         "AF",
1145         "AF",
1146         "NA",
1147         "AS",
1148         "SA",
1149         "SA",
1150         "NA",
1151         "AS",
1152         "AN",
1153         "AF",
1154         "EU",
1155         "NA",
1156         "NA",
1157         "AS",
1158         "AF",
1159         "AF",
1160         "AF",
1161         "EU",
1162         "AF",
1163         "OC",
1164         "SA",
1165         "AF",
1166         "AS",
1167         "SA",
1168         "NA",
1169         "NA",
1170         "AF",
1171         "AS",
1172         "AS",
1173         "EU",
1174         "EU",
1175         "AF",
1176         "EU",
1177         "NA",
1178         "NA",
1179         "AF",
1180         "SA",
1181         "EU",
1182         "AF",
1183         "AF",
1184         "AF",
1185         "EU",
1186         "AF",
1187         "EU",
1188         "OC",
1189         "SA",
1190         "OC",
1191         "EU",
1192         "EU",
1193         "NA",
1194         "AF",
1195         "EU",
1196         "NA",
1197         "AS",
1198         "SA",
1199         "AF",
1200         "EU",
1201         "NA",
1202         "AF",
1203         "AF",
1204         "NA",
1205         "AF",
1206         "EU",
1207         "AN",
1208         "NA",
1209         "OC",
1210         "AF",
1211         "SA",
1212         "AS",
1213         "AN",
1214         "NA",
1215         "EU",
1216         "NA",
1217         "EU",
1218         "AS",
1219         "EU",
1220         "AS",
1221         "AS",
1222         "AS",
1223         "AS",
1224         "AS",
1225         "EU",
1226         "EU",
1227         "NA",
1228         "AS",
1229         "AS",
1230         "AF",
1231         "AS",
1232         "AS",
1233         "OC",
1234         "AF",
1235         "NA",
1236         "AS",
1237         "AS",
1238         "AS",
1239         "NA",
1240         "AS",
1241         "AS",
1242         "AS",
1243         "NA",
1244         "EU",
1245         "AS",
1246         "AF",
1247         "AF",
1248         "EU",
1249         "EU",
1250         "EU",
1251         "AF",
1252         "AF",
1253         "EU",
1254         "EU",
1255         "AF",
1256         "OC",
1257         "EU",
1258         "AF",
1259         "AS",
1260         "AS",
1261         "AS",
1262         "OC",
1263         "NA",
1264         "AF",
1265         "NA",
1266         "EU",
1267         "AF",
1268         "AS",
1269         "AF",
1270         "NA",
1271         "AS",
1272         "AF",
1273         "AF",
1274         "OC",
1275         "AF",
1276         "OC",
1277         "AF",
1278         "NA",
1279         "EU",
1280         "EU",
1281         "AS",
1282         "OC",
1283         "OC",
1284         "OC",
1285         "AS",
1286         "NA",
1287         "SA",
1288         "OC",
1289         "OC",
1290         "AS",
1291         "AS",
1292         "EU",
1293         "NA",
1294         "OC",
1295         "NA",
1296         "AS",
1297         "EU",
1298         "OC",
1299         "SA",
1300         "AS",
1301         "AF",
1302         "EU",
1303         "EU",
1304         "AF",
1305         "AS",
1306         "OC",
1307         "AF",
1308         "AF",
1309         "EU",
1310         "AS",
1311         "AF",
1312         "EU",
1313         "EU",
1314         "EU",
1315         "AF",
1316         "EU",
1317         "AF",
1318         "AF",
1319         "SA",
1320         "AF",
1321         "NA",
1322         "AS",
1323         "AF",
1324         "NA",
1325         "AF",
1326         "AN",
1327         "AF",
1328         "AS",
1329         "AS",
1330         "OC",
1331         "AS",
1332         "AF",
1333         "OC",
1334         "AS",
1335         "EU",
1336         "NA",
1337         "OC",
1338         "AS",
1339         "AF",
1340         "EU",
1341         "AF",
1342         "OC",
1343         "NA",
1344         "SA",
1345         "AS",
1346         "EU",
1347         "NA",
1348         "SA",
1349         "NA",
1350         "NA",
1351         "AS",
1352         "OC",
1353         "OC",
1354         "OC",
1355         "AS",
1356         "AF",
1357         "EU",
1358         "AF",
1359         "AF",
1360         "EU",
1361         "AF",
1362         "--",
1363         "--",
1364         "--",
1365         "EU",
1366         "EU",
1367         "EU",
1368         "EU",
1369         "NA",
1370         "NA",
1371         "NA",
1372         "AF",
1373         "--"
1374     );
1375 }
1376
1377 function geoip_load_shared_mem($file)
1378 {
1379     $fp = fopen($file, "rb");
1380     if (!$fp) {
1381         print "error opening $file: $php_errormsg\n";
1382         exit;
1383     }
1384     $s_array = fstat($fp);
1385     $size = $s_array['size'];
1386     if (($shmid = @shmop_open(GEOIP_SHM_KEY, "w", 0, 0))) {
1387         shmop_delete($shmid);
1388         shmop_close($shmid);
1389     }
1390     $shmid = shmop_open(GEOIP_SHM_KEY, "c", 0644, $size);
1391     shmop_write($shmid, fread($fp, $size), 0);
1392     shmop_close($shmid);
1393 }
1394
1395 function _setup_segments($gi)
1396 {
1397     $gi->databaseType = GEOIP_COUNTRY_EDITION;
1398     $gi->record_length = STANDARD_RECORD_LENGTH;
1399     if ($gi->flags & GEOIP_SHARED_MEMORY) {
1400         $offset = shmop_size($gi->shmid) - 3;
1401         for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
1402             $delim = shmop_read($gi->shmid, $offset, 3);
1403             $offset += 3;
1404             if ($delim == (chr(255) . chr(255) . chr(255))) {
1405                 $gi->databaseType = ord(shmop_read($gi->shmid, $offset, 1));
1406                 if ($gi->databaseType >= 106) {
1407                     $gi->databaseType -= 105;
1408                 }
1409                 $offset++;
1410
1411                 if ($gi->databaseType == GEOIP_REGION_EDITION_REV0) {
1412                     $gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
1413                 } elseif ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
1414                     $gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
1415                 } elseif (($gi->databaseType == GEOIP_CITY_EDITION_REV0)
1416                     || ($gi->databaseType == GEOIP_CITY_EDITION_REV1)
1417                     || ($gi->databaseType == GEOIP_ORG_EDITION)
1418                     || ($gi->databaseType == GEOIP_ORG_EDITION_V6)
1419                     || ($gi->databaseType == GEOIP_DOMAIN_EDITION)
1420                     || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
1421                     || ($gi->databaseType == GEOIP_ISP_EDITION)
1422                     || ($gi->databaseType == GEOIP_ISP_EDITION_V6)
1423                     || ($gi->databaseType == GEOIP_USERTYPE_EDITION)
1424                     || ($gi->databaseType == GEOIP_USERTYPE_EDITION_V6)
1425                     || ($gi->databaseType == GEOIP_LOCATIONA_EDITION)
1426                     || ($gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION)
1427                     || ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
1428                     || ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
1429                     || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1)
1430                     || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6)
1431                     || ($gi->databaseType == GEOIP_ASNUM_EDITION)
1432                     || ($gi->databaseType == GEOIP_ASNUM_EDITION_V6)
1433                 ) {
1434                     $gi->databaseSegments = 0;
1435                     $buf = shmop_read($gi->shmid, $offset, SEGMENT_RECORD_LENGTH);
1436                     for ($j = 0; $j < SEGMENT_RECORD_LENGTH; $j++) {
1437                         $gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
1438                     }
1439                     if (($gi->databaseType == GEOIP_ORG_EDITION)
1440                         || ($gi->databaseType == GEOIP_ORG_EDITION_V6)
1441                         || ($gi->databaseType == GEOIP_DOMAIN_EDITION)
1442                         || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
1443                         || ($gi->databaseType == GEOIP_ISP_EDITION)
1444                         || ($gi->databaseType == GEOIP_ISP_EDITION_V6)
1445                     ) {
1446                         $gi->record_length = ORG_RECORD_LENGTH;
1447                     }
1448                 }
1449                 break;
1450             } else {
1451                 $offset -= 4;
1452             }
1453         }
1454         if (($gi->databaseType == GEOIP_COUNTRY_EDITION) ||
1455             ($gi->databaseType == GEOIP_COUNTRY_EDITION_V6) ||
1456             ($gi->databaseType == GEOIP_PROXY_EDITION) ||
1457             ($gi->databaseType == GEOIP_NETSPEED_EDITION)
1458         ) {
1459             $gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
1460         }
1461     } else {
1462         $filepos = ftell($gi->filehandle);
1463         fseek($gi->filehandle, -3, SEEK_END);
1464         for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
1465             $delim = fread($gi->filehandle, 3);
1466             if ($delim == (chr(255) . chr(255) . chr(255))) {
1467                 $gi->databaseType = ord(fread($gi->filehandle, 1));
1468                 if ($gi->databaseType >= 106) {
1469                     $gi->databaseType -= 105;
1470                 }
1471                 if ($gi->databaseType == GEOIP_REGION_EDITION_REV0) {
1472                     $gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
1473                 } elseif ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
1474                     $gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
1475                 } elseif (($gi->databaseType == GEOIP_CITY_EDITION_REV0)
1476                     || ($gi->databaseType == GEOIP_CITY_EDITION_REV1)
1477                     || ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
1478                     || ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
1479                     || ($gi->databaseType == GEOIP_ORG_EDITION)
1480                     || ($gi->databaseType == GEOIP_DOMAIN_EDITION)
1481                     || ($gi->databaseType == GEOIP_ISP_EDITION)
1482                     || ($gi->databaseType == GEOIP_ORG_EDITION_V6)
1483                     || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
1484                     || ($gi->databaseType == GEOIP_ISP_EDITION_V6)
1485                     || ($gi->databaseType == GEOIP_LOCATIONA_EDITION)
1486                     || ($gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION)
1487                     || ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
1488                     || ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
1489                     || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1)
1490                     || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6)
1491                     || ($gi->databaseType == GEOIP_USERTYPE_EDITION)
1492                     || ($gi->databaseType == GEOIP_USERTYPE_EDITION_V6)
1493                     || ($gi->databaseType == GEOIP_ASNUM_EDITION)
1494                     || ($gi->databaseType == GEOIP_ASNUM_EDITION_V6)
1495                 ) {
1496                     $gi->databaseSegments = 0;
1497
1498                     $buf = fread($gi->filehandle, SEGMENT_RECORD_LENGTH);
1499                     for ($j = 0; $j < SEGMENT_RECORD_LENGTH; $j++) {
1500                         $gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
1501                     }
1502                     if (($gi->databaseType == GEOIP_ORG_EDITION)
1503                         || ($gi->databaseType == GEOIP_DOMAIN_EDITION)
1504                         || ($gi->databaseType == GEOIP_ISP_EDITION)
1505                         || ($gi->databaseType == GEOIP_ORG_EDITION_V6)
1506                         || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
1507                         || ($gi->databaseType == GEOIP_ISP_EDITION_V6)
1508                     ) {
1509                         $gi->record_length = ORG_RECORD_LENGTH;
1510                     }
1511                 }
1512                 break;
1513             } else {
1514                 fseek($gi->filehandle, -4, SEEK_CUR);
1515             }
1516         }
1517         if (($gi->databaseType == GEOIP_COUNTRY_EDITION) ||
1518             ($gi->databaseType == GEOIP_COUNTRY_EDITION_V6) ||
1519             ($gi->databaseType == GEOIP_PROXY_EDITION) ||
1520             ($gi->databaseType == GEOIP_NETSPEED_EDITION)
1521         ) {
1522             $gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
1523         }
1524         fseek($gi->filehandle, $filepos, SEEK_SET);
1525     }
1526     return $gi;
1527 }
1528
1529 # This should be only used for variable-length records where
1530 # $start + $maxLength may be greater than the shared mem size
1531 function _sharedMemRead($gi, $start, $maxLength)
1532 {
1533     $readLength = min(shmop_size($gi->shmid) - $start, $maxLength);
1534     return shmop_read($gi->shmid, $start, $readLength);
1535 }
1536
1537 function geoip_open($filename, $flags)
1538 {
1539     $gi = new GeoIP;
1540     $gi->flags = $flags;
1541     if ($gi->flags & GEOIP_SHARED_MEMORY) {
1542         $gi->shmid = shmop_open(GEOIP_SHM_KEY, "a", 0, 0);
1543     } else {
1544         $gi->filehandle = fopen($filename, "rb") or trigger_error("GeoIP API: Can not open $filename\n", E_USER_ERROR);
1545         if ($gi->flags & GEOIP_MEMORY_CACHE) {
1546             $s_array = fstat($gi->filehandle);
1547             $gi->memory_buffer = fread($gi->filehandle, $s_array['size']);
1548         }
1549     }
1550
1551     $gi = _setup_segments($gi);
1552     return $gi;
1553 }
1554
1555 function geoip_close($gi)
1556 {
1557     if ($gi->flags & GEOIP_SHARED_MEMORY) {
1558         return true;
1559     }
1560
1561     return fclose($gi->filehandle);
1562 }
1563
1564 function geoip_country_id_by_name_v6($gi, $name)
1565 {
1566     $rec = dns_get_record($name, DNS_AAAA);
1567     if (!$rec) {
1568         return false;
1569     }
1570     $addr = $rec[0]["ipv6"];
1571     if (!$addr || $addr == $name) {
1572         return false;
1573     }
1574     return geoip_country_id_by_addr_v6($gi, $addr);
1575 }
1576
1577 function geoip_country_id_by_name($gi, $name)
1578 {
1579     $addr = gethostbyname($name);
1580     if (!$addr || $addr == $name) {
1581         return false;
1582     }
1583     return geoip_country_id_by_addr($gi, $addr);
1584 }
1585
1586 function geoip_country_code_by_name_v6($gi, $name)
1587 {
1588     $country_id = geoip_country_id_by_name_v6($gi, $name);
1589     if ($country_id !== false) {
1590         return $gi->GEOIP_COUNTRY_CODES[$country_id];
1591     }
1592     return false;
1593 }
1594
1595 function geoip_country_code_by_name($gi, $name)
1596 {
1597     $country_id = geoip_country_id_by_name($gi, $name);
1598     if ($country_id !== false) {
1599         return $gi->GEOIP_COUNTRY_CODES[$country_id];
1600     }
1601     return false;
1602 }
1603
1604 function geoip_country_name_by_name_v6($gi, $name)
1605 {
1606     $country_id = geoip_country_id_by_name_v6($gi, $name);
1607     if ($country_id !== false) {
1608         return $gi->GEOIP_COUNTRY_NAMES[$country_id];
1609     }
1610     return false;
1611 }
1612
1613 function geoip_country_name_by_name($gi, $name)
1614 {
1615     $country_id = geoip_country_id_by_name($gi, $name);
1616     if ($country_id !== false) {
1617         return $gi->GEOIP_COUNTRY_NAMES[$country_id];
1618     }
1619     return false;
1620 }
1621
1622 function geoip_country_id_by_addr_v6($gi, $addr)
1623 {
1624     $ipnum = inet_pton($addr);
1625     return _geoip_seek_country_v6($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
1626 }
1627
1628 function geoip_country_id_by_addr($gi, $addr)
1629 {
1630     $ipnum = ip2long($addr);
1631     return _geoip_seek_country($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
1632 }
1633
1634 function geoip_country_code_by_addr_v6($gi, $addr)
1635 {
1636     $country_id = geoip_country_id_by_addr_v6($gi, $addr);
1637     if ($country_id !== false) {
1638         return $gi->GEOIP_COUNTRY_CODES[$country_id];
1639     }
1640     return false;
1641 }
1642
1643 function geoip_country_code_by_addr($gi, $addr)
1644 {
1645     if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
1646         $record = GeoIP_record_by_addr($gi, $addr);
1647         if ($record) {
1648             return $record->country_code;
1649         }
1650     } else {
1651         $country_id = geoip_country_id_by_addr($gi, $addr);
1652         if ($country_id !== false) {
1653             return $gi->GEOIP_COUNTRY_CODES[$country_id];
1654         }
1655     }
1656     return false;
1657 }
1658
1659 function geoip_country_name_by_addr_v6($gi, $addr)
1660 {
1661     $country_id = geoip_country_id_by_addr_v6($gi, $addr);
1662     if ($country_id !== false) {
1663         return $gi->GEOIP_COUNTRY_NAMES[$country_id];
1664     }
1665     return false;
1666 }
1667
1668 function geoip_country_name_by_addr($gi, $addr)
1669 {
1670     if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
1671         $record = GeoIP_record_by_addr($gi, $addr);
1672         return $record->country_name;
1673     } else {
1674         $country_id = geoip_country_id_by_addr($gi, $addr);
1675         if ($country_id !== false) {
1676             return $gi->GEOIP_COUNTRY_NAMES[$country_id];
1677         }
1678     }
1679     return false;
1680 }
1681
1682 function _geoip_seek_country_v6($gi, $ipnum)
1683 {
1684     # arrays from unpack start with offset 1
1685     # yet another php mystery. array_merge work around
1686     # this broken behaviour
1687     $v6vec = array_merge(unpack("C16", $ipnum));
1688
1689     $offset = 0;
1690     for ($depth = 127; $depth >= 0; --$depth) {
1691         if ($gi->flags & GEOIP_MEMORY_CACHE) {
1692             $buf = _safe_substr(
1693                 $gi->memory_buffer,
1694                 2 * $gi->record_length * $offset,
1695                 2 * $gi->record_length
1696             );
1697         } elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
1698             $buf = _sharedMemRead($gi,
1699                 2 * $gi->record_length * $offset,
1700                 2 * $gi->record_length
1701             );
1702         } else {
1703             fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
1704             or trigger_error("GeoIP API: fseek failed", E_USER_ERROR);
1705             $buf = fread($gi->filehandle, 2 * $gi->record_length);
1706         }
1707         $x = array(0, 0);
1708         for ($i = 0; $i < 2; ++$i) {
1709             for ($j = 0; $j < $gi->record_length; ++$j) {
1710                 $x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
1711             }
1712         }
1713
1714         $bnum = 127 - $depth;
1715         $idx = $bnum >> 3;
1716         $b_mask = 1 << ($bnum & 7 ^ 7);
1717         if (($v6vec[$idx] & $b_mask) > 0) {
1718             if ($x[1] >= $gi->databaseSegments) {
1719                 return $x[1];
1720             }
1721             $offset = $x[1];
1722         } else {
1723             if ($x[0] >= $gi->databaseSegments) {
1724                 return $x[0];
1725             }
1726             $offset = $x[0];
1727         }
1728     }
1729     trigger_error("GeoIP API: Error traversing database - perhaps it is corrupt?", E_USER_ERROR);
1730     return false;
1731 }
1732
1733 function _geoip_seek_country($gi, $ipnum)
1734 {
1735     $offset = 0;
1736     for ($depth = 31; $depth >= 0; --$depth) {
1737         if ($gi->flags & GEOIP_MEMORY_CACHE) {
1738             $buf = _safe_substr(
1739                 $gi->memory_buffer,
1740                 2 * $gi->record_length * $offset,
1741                 2 * $gi->record_length
1742             );
1743         } elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
1744             $buf = _sharedMemRead(
1745                 $gi,
1746                 2 * $gi->record_length * $offset,
1747                 2 * $gi->record_length
1748             );
1749         } else {
1750             fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
1751             or trigger_error("GeoIP API: fseek failed", E_USER_ERROR);
1752             $buf = fread($gi->filehandle, 2 * $gi->record_length);
1753         }
1754         $x = array(0, 0);
1755         for ($i = 0; $i < 2; ++$i) {
1756             for ($j = 0; $j < $gi->record_length; ++$j) {
1757                 $x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
1758             }
1759         }
1760         if ($ipnum & (1 << $depth)) {
1761             if ($x[1] >= $gi->databaseSegments) {
1762                 return $x[1];
1763             }
1764             $offset = $x[1];
1765         } else {
1766             if ($x[0] >= $gi->databaseSegments) {
1767                 return $x[0];
1768             }
1769             $offset = $x[0];
1770         }
1771     }
1772     trigger_error("GeoIP API: Error traversing database - perhaps it is corrupt?", E_USER_ERROR);
1773     return false;
1774 }
1775
1776 function _common_get_org($gi, $seek_org)
1777 {
1778     $record_pointer = $seek_org + (2 * $gi->record_length - 1) * $gi->databaseSegments;
1779     if ($gi->flags & GEOIP_SHARED_MEMORY) {
1780         $org_buf = _sharedMemRead($gi, $record_pointer, MAX_ORG_RECORD_LENGTH);
1781     } else {
1782         fseek($gi->filehandle, $record_pointer, SEEK_SET);
1783         $org_buf = fread($gi->filehandle, MAX_ORG_RECORD_LENGTH);
1784     }
1785     $org_buf = _safe_substr($org_buf, 0, strpos($org_buf, "\0"));
1786     return $org_buf;
1787 }
1788
1789 function _get_org_v6($gi, $ipnum)
1790 {
1791     $seek_org = _geoip_seek_country_v6($gi, $ipnum);
1792     if ($seek_org == $gi->databaseSegments) {
1793         return null;
1794     }
1795     return _common_get_org($gi, $seek_org);
1796 }
1797
1798 function _get_org($gi, $ipnum)
1799 {
1800     $seek_org = _geoip_seek_country($gi, $ipnum);
1801     if ($seek_org == $gi->databaseSegments) {
1802         return null;
1803     }
1804     return _common_get_org($gi, $seek_org);
1805 }
1806
1807
1808 function geoip_name_by_addr_v6($gi, $addr)
1809 {
1810     if ($addr == null) {
1811         return 0;
1812     }
1813     $ipnum = inet_pton($addr);
1814     return _get_org_v6($gi, $ipnum);
1815 }
1816
1817 function geoip_name_by_addr($gi, $addr)
1818 {
1819     if ($addr == null) {
1820         return 0;
1821     }
1822     $ipnum = ip2long($addr);
1823     return _get_org($gi, $ipnum);
1824 }
1825
1826 function geoip_org_by_addr($gi, $addr)
1827 {
1828     return geoip_name_by_addr($gi, $addr);
1829 }
1830
1831 function _get_region($gi, $ipnum)
1832 {
1833     if ($gi->databaseType == GEOIP_REGION_EDITION_REV0) {
1834         $seek_region = _geoip_seek_country($gi, $ipnum) - GEOIP_STATE_BEGIN_REV0;
1835         if ($seek_region >= 1000) {
1836             $country_code = "US";
1837             $region = chr(($seek_region - 1000) / 26 + 65) . chr(($seek_region - 1000) % 26 + 65);
1838         } else {
1839             $country_code = $gi->GEOIP_COUNTRY_CODES[$seek_region];
1840             $region = "";
1841         }
1842         return array($country_code, $region);
1843     } elseif ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
1844         $seek_region = _geoip_seek_country($gi, $ipnum) - GEOIP_STATE_BEGIN_REV1;
1845         if ($seek_region < US_OFFSET) {
1846             $country_code = "";
1847             $region = "";
1848         } elseif ($seek_region < CANADA_OFFSET) {
1849             $country_code = "US";
1850             $region = chr(($seek_region - US_OFFSET) / 26 + 65) . chr(($seek_region - US_OFFSET) % 26 + 65);
1851         } elseif ($seek_region < WORLD_OFFSET) {
1852             $country_code = "CA";
1853             $region = chr(($seek_region - CANADA_OFFSET) / 26 + 65) . chr(($seek_region - CANADA_OFFSET) % 26 + 65);
1854         } else {
1855             $country_code = $gi->GEOIP_COUNTRY_CODES[(int) (($seek_region - WORLD_OFFSET) / FIPS_RANGE)];
1856             $region = "";
1857         }
1858         return array($country_code, $region);
1859     }
1860     return null;
1861 }
1862
1863 function geoip_region_by_addr($gi, $addr)
1864 {
1865     if ($addr == null) {
1866         return 0;
1867     }
1868     $ipnum = ip2long($addr);
1869     return _get_region($gi, $ipnum);
1870 }
1871
1872 function _safe_substr($string, $start, $length)
1873 {
1874     // workaround php's broken substr, strpos, etc handling with
1875     // mbstring.func_overload and mbstring.internal_encoding
1876     $mbExists = extension_loaded('mbstring');
1877
1878     if ($mbExists) {
1879         $enc = mb_internal_encoding();
1880         mb_internal_encoding('ISO-8859-1');
1881     }
1882
1883     $buf = substr($string, $start, $length);
1884
1885     if ($mbExists) {
1886         mb_internal_encoding($enc);
1887     }
1888
1889     return $buf;
1890 }