Issues (1182)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/class-wc-geo-ip.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1665
			return $this->GEOIP_COUNTRY_CODES[ $country_id ];
1666
		}
1667
1668
		return false;
1669
	}
1670
1671
	/**
1672
	 * Country code by addr.
1673
	 *
1674
	 * @param  string $addr
1675
	 * @return string
1676
	 */
1677
	public function geoip_country_code_by_addr( $addr ) {
1678
		if ( $this->databaseType == self::GEOIP_CITY_EDITION_REV1 ) {
1679
			$record = $this->geoip_record_by_addr( $addr );
1680
			if ( $record !== false ) {
1681
				return $record->country_code;
1682
			}
1683 View Code Duplication
		} else {
1684
			$country_id = $this->geoip_country_id_by_addr( $addr );
1685
			if ( $country_id !== false && isset( $this->GEOIP_COUNTRY_CODES[ $country_id ] ) ) {
1686
				return $this->GEOIP_COUNTRY_CODES[ $country_id ];
1687
			}
1688
		}
1689
1690
		return false;
1691
	}
1692
1693
	/**
1694
	 * Encode string.
1695
	 *
1696
	 * @param  string $string
1697
	 * @param  int    $start
1698
	 * @param  int    $length
1699
	 * @return string
1700
	 */
1701
	private function _safe_substr( $string, $start, $length ) {
1702
		// workaround php's broken substr, strpos, etc handling with
1703
		// mbstring.func_overload and mbstring.internal_encoding
1704
		$mb_exists = extension_loaded( 'mbstring' );
1705
1706
		if ( $mb_exists ) {
1707
			$enc = mb_internal_encoding();
1708
			mb_internal_encoding( 'ISO-8859-1' );
1709
		}
1710
1711
		$buf = substr( $string, $start, $length );
1712
1713
		if ( $mb_exists ) {
1714
			mb_internal_encoding( $enc );
1715
		}
1716
1717
		return $buf;
1718
	}
1719
}
1720
1721
/**
1722
 * Geo IP Record class.
1723
 */
1724
class WC_Geo_IP_Record {
1725
1726
	/**
1727
	 * Country code.
1728
	 *
1729
	 * @var string
1730
	 */
1731
	public $country_code;
1732
1733
	/**
1734
	 * 3 letters country code.
1735
	 *
1736
	 * @var string
1737
	 */
1738
	public $country_code3;
1739
1740
	/**
1741
	 * Country name.
1742
	 *
1743
	 * @var string
1744
	 */
1745
	public $country_name;
1746
1747
	/**
1748
	 * Region.
1749
	 *
1750
	 * @var string
1751
	 */
1752
	public $region;
1753
1754
	/**
1755
	 * City.
1756
	 *
1757
	 * @var string
1758
	 */
1759
	public $city;
1760
1761
	/**
1762
	 * Postal code.
1763
	 *
1764
	 * @var string
1765
	 */
1766
	public $postal_code;
1767
1768
	/**
1769
	 * Latitude
1770
	 *
1771
	 * @var float
1772
	 */
1773
	public $latitude;
1774
1775
	/**
1776
	 * Longitude.
1777
	 *
1778
	 * @var float
1779
	 */
1780
	public $longitude;
1781
1782
	/**
1783
	 * Area code.
1784
	 *
1785
	 * @var string
1786
	 */
1787
	public $area_code;
1788
1789
	/**
1790
	 * DMA Code.
1791
	 *
1792
	 * Metro and DMA code are the same.
1793
	 * Use metro code instead.
1794
	 *
1795
	 * @var int
1796
	 */
1797
	public $dma_code;
1798
1799
	/**
1800
	 * Metro code.
1801
	 *
1802
	 * @var int
1803
	 */
1804
	public $metro_code;
1805
1806
	/**
1807
	 * Continent code.
1808
	 *
1809
	 * @var string
1810
	 */
1811
	public $continent_code;
1812
}
1813