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
23define("GEOIP_COUNTRY_BEGIN", 16776960);
24define("GEOIP_STATE_BEGIN_REV0", 16700000);
25define("GEOIP_STATE_BEGIN_REV1", 16000000);
26define("GEOIP_STANDARD", 0);
27define("GEOIP_MEMORY_CACHE", 1);
28define("GEOIP_SHARED_MEMORY", 2);
29define("STRUCTURE_INFO_MAX_SIZE", 20);
30define("DATABASE_INFO_MAX_SIZE", 100);
31define("GEOIP_COUNTRY_EDITION", 1);
32define("GEOIP_PROXY_EDITION", 8);
33define("GEOIP_ASNUM_EDITION", 9);
34define("GEOIP_NETSPEED_EDITION", 10);
35define("GEOIP_REGION_EDITION_REV0", 7);
36define("GEOIP_REGION_EDITION_REV1", 3);
37define("GEOIP_CITY_EDITION_REV0", 6);
38define("GEOIP_CITY_EDITION_REV1", 2);
39define("GEOIP_ORG_EDITION", 5);
40define("GEOIP_ISP_EDITION", 4);
41define("SEGMENT_RECORD_LENGTH", 3);
42define("STANDARD_RECORD_LENGTH", 3);
43define("ORG_RECORD_LENGTH", 4);
44define("MAX_RECORD_LENGTH", 4);
45define("MAX_ORG_RECORD_LENGTH", 300);
46define("GEOIP_SHM_KEY", 0x4f415401);
47define("US_OFFSET", 1);
48define("CANADA_OFFSET", 677);
49define("WORLD_OFFSET", 1353);
50define("FIPS_RANGE", 360);
51define("GEOIP_UNKNOWN_SPEED", 0);
52define("GEOIP_DIALUP_SPEED", 1);
53define("GEOIP_CABLEDSL_SPEED", 2);
54define("GEOIP_CORPORATE_SPEED", 3);
55define("GEOIP_DOMAIN_EDITION", 11);
56define("GEOIP_COUNTRY_EDITION_V6", 12);
57define("GEOIP_LOCATIONA_EDITION", 13);
58define("GEOIP_ACCURACYRADIUS_EDITION", 14);
59define("GEOIP_CITYCOMBINED_EDITION", 15);
60define("GEOIP_CITY_EDITION_REV1_V6", 30);
61define("GEOIP_CITY_EDITION_REV0_V6", 31);
62define("GEOIP_NETSPEED_EDITION_REV1", 32);
63define("GEOIP_NETSPEED_EDITION_REV1_V6", 33);
64define("GEOIP_USERTYPE_EDITION", 28);
65define("GEOIP_USERTYPE_EDITION_V6", 29);
66define("GEOIP_ASNUM_EDITION_V6", 21);
67define("GEOIP_ISP_EDITION_V6", 22);
68define("GEOIP_ORG_EDITION_V6", 23);
69define("GEOIP_DOMAIN_EDITION_V6", 24);
70
71define("CITYCOMBINED_FIXED_RECORD", 7);
72
73class 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
1377function 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
1395function _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                    $buf = fread($gi->filehandle, SEGMENT_RECORD_LENGTH);
1498                    for ($j = 0; $j < SEGMENT_RECORD_LENGTH; $j++) {
1499                        $gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
1500                    }
1501                    if (($gi->databaseType == GEOIP_ORG_EDITION)
1502                        || ($gi->databaseType == GEOIP_DOMAIN_EDITION)
1503                        || ($gi->databaseType == GEOIP_ISP_EDITION)
1504                        || ($gi->databaseType == GEOIP_ORG_EDITION_V6)
1505                        || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
1506                        || ($gi->databaseType == GEOIP_ISP_EDITION_V6)
1507                    ) {
1508                        $gi->record_length = ORG_RECORD_LENGTH;
1509                    }
1510                }
1511                break;
1512            } else {
1513                fseek($gi->filehandle, -4, SEEK_CUR);
1514            }
1515        }
1516        if (($gi->databaseType == GEOIP_COUNTRY_EDITION) ||
1517            ($gi->databaseType == GEOIP_COUNTRY_EDITION_V6) ||
1518            ($gi->databaseType == GEOIP_PROXY_EDITION) ||
1519            ($gi->databaseType == GEOIP_NETSPEED_EDITION)
1520        ) {
1521            $gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
1522        }
1523        fseek($gi->filehandle, $filepos, SEEK_SET);
1524    }
1525    return $gi;
1526}
1527
1528function geoip_open($filename, $flags)
1529{
1530    $gi = new GeoIP;
1531    $gi->flags = $flags;
1532    if ($gi->flags & GEOIP_SHARED_MEMORY) {
1533        $gi->shmid = @shmop_open(GEOIP_SHM_KEY, "a", 0, 0);
1534    } else {
1535        $gi->filehandle = fopen($filename, "rb") or die("Can not open $filename\n");
1536        if ($gi->flags & GEOIP_MEMORY_CACHE) {
1537            $s_array = fstat($gi->filehandle);
1538            $gi->memory_buffer = fread($gi->filehandle, $s_array['size']);
1539        }
1540    }
1541
1542    $gi = _setup_segments($gi);
1543    return $gi;
1544}
1545
1546function geoip_close($gi)
1547{
1548    if ($gi->flags & GEOIP_SHARED_MEMORY) {
1549        return true;
1550    }
1551
1552    return fclose($gi->filehandle);
1553}
1554
1555function geoip_country_id_by_name_v6($gi, $name)
1556{
1557    $rec = dns_get_record($name, DNS_AAAA);
1558    if (!$rec) {
1559        return false;
1560    }
1561    $addr = $rec[0]["ipv6"];
1562    if (!$addr || $addr == $name) {
1563        return false;
1564    }
1565    return geoip_country_id_by_addr_v6($gi, $addr);
1566}
1567
1568function geoip_country_id_by_name($gi, $name)
1569{
1570    $addr = gethostbyname($name);
1571    if (!$addr || $addr == $name) {
1572        return false;
1573    }
1574    return geoip_country_id_by_addr($gi, $addr);
1575}
1576
1577function geoip_country_code_by_name_v6($gi, $name)
1578{
1579    $country_id = geoip_country_id_by_name_v6($gi, $name);
1580    if ($country_id !== false) {
1581        return $gi->GEOIP_COUNTRY_CODES[$country_id];
1582    }
1583    return false;
1584}
1585
1586function geoip_country_code_by_name($gi, $name)
1587{
1588    $country_id = geoip_country_id_by_name($gi, $name);
1589    if ($country_id !== false) {
1590        return $gi->GEOIP_COUNTRY_CODES[$country_id];
1591    }
1592    return false;
1593}
1594
1595function geoip_country_name_by_name_v6($gi, $name)
1596{
1597    $country_id = geoip_country_id_by_name_v6($gi, $name);
1598    if ($country_id !== false) {
1599        return $gi->GEOIP_COUNTRY_NAMES[$country_id];
1600    }
1601    return false;
1602}
1603
1604function geoip_country_name_by_name($gi, $name)
1605{
1606    $country_id = geoip_country_id_by_name($gi, $name);
1607    if ($country_id !== false) {
1608        return $gi->GEOIP_COUNTRY_NAMES[$country_id];
1609    }
1610    return false;
1611}
1612
1613function geoip_country_id_by_addr_v6($gi, $addr)
1614{
1615    $ipnum = inet_pton($addr);
1616    return _geoip_seek_country_v6($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
1617}
1618
1619function geoip_country_id_by_addr($gi, $addr)
1620{
1621    $ipnum = ip2long($addr);
1622    return _geoip_seek_country($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
1623}
1624
1625function geoip_country_code_by_addr_v6($gi, $addr)
1626{
1627    $country_id = geoip_country_id_by_addr_v6($gi, $addr);
1628    if ($country_id !== false) {
1629        return $gi->GEOIP_COUNTRY_CODES[$country_id];
1630    }
1631    return false;
1632}
1633
1634function geoip_country_code_by_addr($gi, $addr)
1635{
1636    if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
1637        $record = geoip_record_by_addr($gi, $addr);
1638        if ($record !== false) {
1639            return $record->country_code;
1640        }
1641    } else {
1642        $country_id = geoip_country_id_by_addr($gi, $addr);
1643        if ($country_id !== false) {
1644            return $gi->GEOIP_COUNTRY_CODES[$country_id];
1645        }
1646    }
1647    return false;
1648}
1649
1650function geoip_country_name_by_addr_v6($gi, $addr)
1651{
1652    $country_id = geoip_country_id_by_addr_v6($gi, $addr);
1653    if ($country_id !== false) {
1654        return $gi->GEOIP_COUNTRY_NAMES[$country_id];
1655    }
1656    return false;
1657}
1658
1659function geoip_country_name_by_addr($gi, $addr)
1660{
1661    if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
1662        $record = geoip_record_by_addr($gi, $addr);
1663        return $record->country_name;
1664    } else {
1665        $country_id = geoip_country_id_by_addr($gi, $addr);
1666        if ($country_id !== false) {
1667            return $gi->GEOIP_COUNTRY_NAMES[$country_id];
1668        }
1669    }
1670    return false;
1671}
1672
1673function _geoip_seek_country_v6($gi, $ipnum)
1674{
1675    # arrays from unpack start with offset 1
1676    # yet another php mystery. array_merge work around
1677    # this broken behaviour
1678    $v6vec = array_merge(unpack("C16", $ipnum));
1679
1680    $offset = 0;
1681    for ($depth = 127; $depth >= 0; --$depth) {
1682        if ($gi->flags & GEOIP_MEMORY_CACHE) {
1683            $buf = _safe_substr(
1684                $gi->memory_buffer,
1685                2 * $gi->record_length * $offset,
1686                2 * $gi->record_length
1687            );
1688        } elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
1689            $buf = @shmop_read(
1690                $gi->shmid,
1691                2 * $gi->record_length * $offset,
1692                2 * $gi->record_length
1693            );
1694        } else {
1695            fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
1696            or die("fseek failed");
1697            $buf = fread($gi->filehandle, 2 * $gi->record_length);
1698        }
1699        $x = array(0, 0);
1700        for ($i = 0; $i < 2; ++$i) {
1701            for ($j = 0; $j < $gi->record_length; ++$j) {
1702                $x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
1703            }
1704        }
1705
1706        $bnum = 127 - $depth;
1707        $idx = $bnum >> 3;
1708        $b_mask = 1 << ($bnum & 7 ^ 7);
1709        if (($v6vec[$idx] & $b_mask) > 0) {
1710            if ($x[1] >= $gi->databaseSegments) {
1711                return $x[1];
1712            }
1713            $offset = $x[1];
1714        } else {
1715            if ($x[0] >= $gi->databaseSegments) {
1716                return $x[0];
1717            }
1718            $offset = $x[0];
1719        }
1720    }
1721    trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR);
1722    return false;
1723}
1724
1725function _geoip_seek_country($gi, $ipnum)
1726{
1727    $offset = 0;
1728    for ($depth = 31; $depth >= 0; --$depth) {
1729        if ($gi->flags & GEOIP_MEMORY_CACHE) {
1730            $buf = _safe_substr(
1731                $gi->memory_buffer,
1732                2 * $gi->record_length * $offset,
1733                2 * $gi->record_length
1734            );
1735        } elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
1736            $buf = @shmop_read(
1737                $gi->shmid,
1738                2 * $gi->record_length * $offset,
1739                2 * $gi->record_length
1740            );
1741        } else {
1742            fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
1743            or die("fseek failed");
1744            $buf = fread($gi->filehandle, 2 * $gi->record_length);
1745        }
1746        $x = array(0, 0);
1747        for ($i = 0; $i < 2; ++$i) {
1748            for ($j = 0; $j < $gi->record_length; ++$j) {
1749                $x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
1750            }
1751        }
1752        if ($ipnum & (1 << $depth)) {
1753            if ($x[1] >= $gi->databaseSegments) {
1754                return $x[1];
1755            }
1756            $offset = $x[1];
1757        } else {
1758            if ($x[0] >= $gi->databaseSegments) {
1759                return $x[0];
1760            }
1761            $offset = $x[0];
1762        }
1763    }
1764    trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR);
1765    return false;
1766}
1767
1768function _common_get_org($gi, $seek_org)
1769{
1770    $record_pointer = $seek_org + (2 * $gi->record_length - 1) * $gi->databaseSegments;
1771    if ($gi->flags & GEOIP_SHARED_MEMORY) {
1772        $org_buf = @shmop_read($gi->shmid, $record_pointer, MAX_ORG_RECORD_LENGTH);
1773    } else {
1774        fseek($gi->filehandle, $record_pointer, SEEK_SET);
1775        $org_buf = fread($gi->filehandle, MAX_ORG_RECORD_LENGTH);
1776    }
1777    $org_buf = _safe_substr($org_buf, 0, strpos($org_buf, "\0"));
1778    return $org_buf;
1779}
1780
1781function _get_org_v6($gi, $ipnum)
1782{
1783    $seek_org = _geoip_seek_country_v6($gi, $ipnum);
1784    if ($seek_org == $gi->databaseSegments) {
1785        return null;
1786    }
1787    return _common_get_org($gi, $seek_org);
1788}
1789
1790function _get_org($gi, $ipnum)
1791{
1792    $seek_org = _geoip_seek_country($gi, $ipnum);
1793    if ($seek_org == $gi->databaseSegments) {
1794        return null;
1795    }
1796    return _common_get_org($gi, $seek_org);
1797}
1798
1799
1800function geoip_name_by_addr_v6($gi, $addr)
1801{
1802    if ($addr == null) {
1803        return 0;
1804    }
1805    $ipnum = inet_pton($addr);
1806    return _get_org_v6($gi, $ipnum);
1807}
1808
1809function geoip_name_by_addr($gi, $addr)
1810{
1811    if ($addr == null) {
1812        return 0;
1813    }
1814    $ipnum = ip2long($addr);
1815    return _get_org($gi, $ipnum);
1816}
1817
1818function geoip_org_by_addr($gi, $addr)
1819{
1820    return geoip_name_by_addr($gi, $addr);
1821}
1822
1823function _get_region($gi, $ipnum)
1824{
1825    if ($gi->databaseType == GEOIP_REGION_EDITION_REV0) {
1826        $seek_region = _geoip_seek_country($gi, $ipnum) - GEOIP_STATE_BEGIN_REV0;
1827        if ($seek_region >= 1000) {
1828            $country_code = "US";
1829            $region = chr(($seek_region - 1000) / 26 + 65) . chr(($seek_region - 1000) % 26 + 65);
1830        } else {
1831            $country_code = $gi->GEOIP_COUNTRY_CODES[$seek_region];
1832            $region = "";
1833        }
1834        return array($country_code, $region);
1835    } elseif ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
1836        $seek_region = _geoip_seek_country($gi, $ipnum) - GEOIP_STATE_BEGIN_REV1;
1837        if ($seek_region < US_OFFSET) {
1838            $country_code = "";
1839            $region = "";
1840        } elseif ($seek_region < CANADA_OFFSET) {
1841            $country_code = "US";
1842            $region = chr(($seek_region - US_OFFSET) / 26 + 65) . chr(($seek_region - US_OFFSET) % 26 + 65);
1843        } elseif ($seek_region < WORLD_OFFSET) {
1844            $country_code = "CA";
1845            $region = chr(($seek_region - CANADA_OFFSET) / 26 + 65) . chr(($seek_region - CANADA_OFFSET) % 26 + 65);
1846        } else {
1847            $country_code = $gi->GEOIP_COUNTRY_CODES[($seek_region - WORLD_OFFSET) / FIPS_RANGE];
1848            $region = "";
1849        }
1850        return array($country_code, $region);
1851    }
1852}
1853
1854function geoip_region_by_addr($gi, $addr)
1855{
1856    if ($addr == null) {
1857        return 0;
1858    }
1859    $ipnum = ip2long($addr);
1860    return _get_region($gi, $ipnum);
1861}
1862
1863function _safe_substr($string, $start, $length)
1864{
1865    // workaround php's broken substr, strpos, etc handling with
1866    // mbstring.func_overload and mbstring.internal_encoding
1867    $mbExists = extension_loaded('mbstring');
1868
1869    if ($mbExists) {
1870        $enc = mb_internal_encoding();
1871        mb_internal_encoding('ISO-8859-1');
1872    }
1873
1874    $buf = substr($string, $start, $length);
1875
1876    if ($mbExists) {
1877        mb_internal_encoding($enc);
1878    }
1879
1880    return $buf;
1881}
1882