GeoIP Detection - Version 2.12.0

Version Description

New: Ipstack.com can be used as data source

Download this release

Release Info

Developer benjaminpick
Plugin Icon 128x128 GeoIP Detection
Version 2.12.0
Comparing to
See all releases

Code changes from version 2.11.1 to 2.12.0

admin-ui.php CHANGED
@@ -177,3 +177,52 @@ function geoip_detect_option_page() {
177
  function geoip_detect_option_client_ip_page() {
178
  include_once(GEOIP_PLUGIN_DIR . '/views/client-ip.php');
179
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  function geoip_detect_option_client_ip_page() {
178
  include_once(GEOIP_PLUGIN_DIR . '/views/client-ip.php');
179
  }
180
+
181
+ function _geoip_detect_improve_data_for_lookup($data, $shorten_attributes = false) {
182
+ if ($shorten_attributes) {
183
+ $short = [
184
+ 'city',
185
+ 'subdivisions',
186
+ 'country',
187
+ 'location'
188
+ ];
189
+ $short = array_combine($short, $short);
190
+ $data = array_intersect_key($data, $short);
191
+
192
+ unset($data['city']['geoname_id']);
193
+ unset($data['country']['geoname_id']);
194
+ unset($data['country']['is_in_european_union']);
195
+ unset($data['location']['accuracy_radius']);
196
+ foreach ($data['subdivisions'] as $i => $s) {
197
+ unset($data['subdivisions'][$i]['geoname_id']);
198
+ }
199
+ }
200
+
201
+ // Logical order
202
+ $order = [
203
+ 'is_empty',
204
+ 'city',
205
+ 'most_specific_subdivision',
206
+ 'subdivisions',
207
+ 'postal',
208
+ 'country',
209
+ 'registered_country',
210
+ 'represented_country',
211
+ 'continent',
212
+ 'location',
213
+ 'traits',
214
+ 'maxmind',
215
+ 'extra'
216
+ ];
217
+
218
+ uksort($data, function($a, $b) use ($order) {
219
+ $a_found = array_search($a, $order);
220
+ $b_found = array_search($b, $order);
221
+
222
+ if ($a_found === false) $a_found = 1000;
223
+ if ($b_found === false) $b_found = 1000;
224
+ return $a_found > $b_found;
225
+ });
226
+
227
+ return $data;
228
+ }
ajax.php CHANGED
@@ -41,7 +41,7 @@ function geoip_detect_ajax_get_info_from_current_ip() {
41
 
42
  // Enabled in preferences? If not, do as if the plugin doesn't even exist.
43
  if (!get_option('geoip-detect-ajax_enabled')) {
44
- _geoip_detect_ajax_error('AJAX must be enabled in the options of the plugin.');
45
  }
46
 
47
  if (!defined( 'DOING_AJAX' ))
41
 
42
  // Enabled in preferences? If not, do as if the plugin doesn't even exist.
43
  if (!get_option('geoip-detect-ajax_enabled')) {
44
+ return;
45
  }
46
 
47
  if (!defined( 'DOING_AJAX' ))
data-sources/abstract.php CHANGED
@@ -81,7 +81,7 @@ class ExtraInformation extends \GeoIp2\Record\AbstractRecord {
81
  /**
82
  * @ignore
83
  */
84
- protected $validAttributes = array('source', 'cached', 'error');
85
  }
86
 
87
  interface ReaderInterface extends \GeoIp2\ProviderInterface {
81
  /**
82
  * @ignore
83
  */
84
+ protected $validAttributes = array('source', 'cached', 'error', 'original');
85
  }
86
 
87
  interface ReaderInterface extends \GeoIp2\ProviderInterface {
data-sources/auto.php CHANGED
@@ -231,8 +231,8 @@ HTML;
231
  }
232
 
233
  public function schedule_next_cron_run() {
234
- // The Lite databases are updated on the first tuesday of each month. Maybe not at midnight, so we schedule it for the night afterwards.
235
- $next = strtotime('first tuesday of next month + 1 day');
236
  $next += mt_rand(1, WEEK_IN_SECONDS);
237
  wp_schedule_single_event($next, 'geoipdetectupdate');
238
  }
231
  }
232
 
233
  public function schedule_next_cron_run() {
234
+ // Try to update every 1-2 weeks
235
+ $next = time() + WEEK_IN_SECONDS;
236
  $next += mt_rand(1, WEEK_IN_SECONDS);
237
  wp_schedule_single_event($next, 'geoipdetectupdate');
238
  }
data-sources/header.php CHANGED
@@ -69,7 +69,7 @@ class HeaderDataSource extends AbstractDataSource {
69
  public function getId() { return 'header'; }
70
  public function getLabel() { return __('Special Hosting Providers (Cloudflare, Amazon AWS CloudFront)', 'geoip-detect'); }
71
 
72
- public function getDescriptionHTML() { return __('These hosting providers already do geodetection, but only of the visitor\'s country.', 'geoip-detect'); }
73
 
74
  public function getStatusInformationHTML() {
75
  $provider = get_option('geoip-detect-header-provider');
69
  public function getId() { return 'header'; }
70
  public function getLabel() { return __('Special Hosting Providers (Cloudflare, Amazon AWS CloudFront)', 'geoip-detect'); }
71
 
72
+ public function getDescriptionHTML() { return __('These servers already do geodetection, but only of the visitor\'s country.', 'geoip-detect'); }
73
 
74
  public function getStatusInformationHTML() {
75
  $provider = get_option('geoip-detect-header-provider');
data-sources/hostinfo.php CHANGED
@@ -28,6 +28,8 @@ class Reader implements \YellowTree\GeoipDetect\DataSources\ReaderInterface {
28
 
29
  $r = array();
30
 
 
 
31
  if ($data['country_name'])
32
  $r['country']['names'] = array('en' => $data['country_name']);
33
  if ($data['country_code'])
28
 
29
  $r = array();
30
 
31
+ $r['traits']['original'] = $data;
32
+
33
  if ($data['country_name'])
34
  $r['country']['names'] = array('en' => $data['country_name']);
35
  if ($data['country_code'])
data-sources/ipstack.php ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Copyright 2013-2019 Yellow Tree, Siegen, Germany
4
+ Author: Benjamin Pick (wp-geoip-detect| |posteo.de)
5
+
6
+ This program is free software; you can redistribute it and/or modify
7
+ it under the terms of the GNU General Public License as published by
8
+ the Free Software Foundation; either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU General Public License for more details.
15
+
16
+ You should have received a copy of the GNU General Public License
17
+ along with this program; if not, write to the Free Software
18
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+ namespace YellowTree\GeoipDetect\DataSources\Ipstack;
22
+
23
+ use YellowTree\GeoipDetect\DataSources\AbstractDataSource;
24
+
25
+ class Reader implements \YellowTree\GeoipDetect\DataSources\ReaderInterface {
26
+
27
+ const URL = 'api.ipstack.com/';
28
+ protected $options = array();
29
+ protected $params = array();
30
+
31
+ function __construct($params, $locales, $options) {
32
+ $this->params= $params;
33
+ $this->params['language'] = reset($locales);
34
+ if (empty($this->params['language'])) {
35
+ $this->params['language'] = 'en';
36
+ }
37
+
38
+ $default_options = array(
39
+ 'timeout' => 1,
40
+ );
41
+ $this->options = $options + $default_options;
42
+ }
43
+
44
+ protected function locales($locale, $value) {
45
+ $locales = array('en' => $value);
46
+ if ($locale != 'en') {
47
+ $locales[$locale] = $value;
48
+ }
49
+ return $locales;
50
+ }
51
+
52
+ public function city($ip) {
53
+ $data = $this->api_call($ip);
54
+
55
+ if (!$data)
56
+ return null;
57
+
58
+ $r = array();
59
+
60
+ $r['extra']['original'] = $data;
61
+
62
+ if (isset($data['success']) && $data['success'] === false) {
63
+ throw new \RuntimeException($data['error']['info']);
64
+ // Example error:
65
+ /* @see https://ipstack.com/documentation#errors
66
+ {
67
+ "success": false,
68
+ "error": {
69
+ "code": 104,
70
+ "type": "monthly_limit_reached",
71
+ "info": "Your monthly API request volume has been reached. Please upgrade your plan."
72
+ }
73
+ }
74
+ */
75
+ }
76
+
77
+ $locale = $this->params['language'];
78
+ if (!empty($data['continent_name']))
79
+ $r['continent']['names'] = $this->locales($locale, $data['continent_name']);
80
+ if (!empty($data['continent_code']))
81
+ $r['continent']['code'] = strtoupper($data['continent_code']);
82
+ if (!empty($data['country_name']))
83
+ $r['country']['names'] = $this->locales($locale, $data['country_name']);
84
+ if (!empty($data['country_code']))
85
+ $r['country']['iso_code'] = strtoupper($data['country_code']);
86
+
87
+ if (!empty($data['region_code'])) {
88
+ $r['subdivisions'][0] = array(
89
+ 'iso_code' => $data['region_code'],
90
+ 'names' => $this->locales($locale, $data['region_name']),
91
+ );
92
+ }
93
+
94
+ if (!empty($data['city']))
95
+ $r['city']['names'] = $this->locales($locale, $data['city']);
96
+ if (!empty($data['latitude']))
97
+ $r['location']['latitude'] = $data['latitude'];
98
+ if (!empty($data['longitude']))
99
+ $r['location']['longitude'] = $data['longitude'];
100
+
101
+ if (isset($data['is_eu']))
102
+ $r['country']['is_in_european_union'] = $data['is_eu'];
103
+ if (isset($data['timezone']['id']))
104
+ $r['location']['time_zone'] = $data['timezone']['id'];
105
+
106
+ if (isset($data['connection']['asn']))
107
+ $r['traits']['autonomous_system_number'] = $data['connection']['asn'];
108
+ if (isset($data['connection']['isp']))
109
+ $r['traits']['isp'] = $data['connection']['isp'];
110
+ if (isset($data['security']['is_proxy']))
111
+ $r['traits']['is_anonymous_vpn'] = $data['security']['is_proxy'] && $data['security']['proxy_type'] == 'vpn';
112
+ if (isset($data['security']['is_tor']))
113
+ $r['traits']['is_tor_exit_node'] = $data['security']['is_tor'];
114
+
115
+ $r['traits']['ip_address'] = $ip;
116
+
117
+ $record = new \GeoIp2\Model\City($r, array('en'));
118
+
119
+ return $record;
120
+ }
121
+
122
+ public function country($ip) {
123
+ return $this->city($ip); // too much info shouldn't hurt ...
124
+ }
125
+
126
+ public function close() {
127
+
128
+ }
129
+
130
+ private function build_url($ip) {
131
+ $url = $this->params['ssl'] ? 'https' : 'http';
132
+ $url .= '://' . self::URL . $ip;
133
+
134
+ $params = [
135
+ 'access_key' => $this->params['key'],
136
+ 'language' => $this->params['language'],
137
+ ];
138
+ return $url . '?' . \http_build_query($params);
139
+ }
140
+
141
+ private function api_call($ip) {
142
+ try {
143
+ // Setting timeout limit to speed up sites
144
+ $context = stream_context_create(
145
+ array(
146
+ 'http' => array(
147
+ 'timeout' => $this->options['timeout'],
148
+ ),
149
+ )
150
+ );
151
+ // Using @file... to supress errors
152
+ // Example output: {"country_name":"UNITED STATES","country_code":"US","city":"Aurora, TX","ip":"12.215.42.19"}
153
+
154
+ $body = @file_get_contents($this->build_url($ip), false, $context);
155
+ $data = json_decode($body, true);
156
+
157
+ return $data;
158
+ } catch (\Exception $e) {
159
+ // If the API isn't available, we have to do this
160
+ throw $e;
161
+ return null;
162
+ }
163
+ }
164
+ }
165
+
166
+
167
+ class IpstackSource extends AbstractDataSource {
168
+ protected $params = array();
169
+
170
+ public function __construct() {
171
+ $this->params['key'] = get_option('geoip-detect-ipstack_key', '');
172
+ $this->params['ssl'] = get_option('geoip-detect-ipstack_ssl', 0);
173
+ }
174
+
175
+ public function getId() { return 'ipstack'; }
176
+ public function getLabel() { return __('Ipstack Web-API', 'geoip-detect'); }
177
+
178
+ public function getDescriptionHTML() { return __('<a href="https://ipstack.com/">Ipstack</a>', 'geoip-detect'); }
179
+ public function getStatusInformationHTML() {
180
+ $html = '';
181
+
182
+ $html .= __('Last Error Seen: ', 'geoip-detect') . '<br />';
183
+
184
+ $html .= \sprintf(__('SSL: %s', 'geoip-detect'), $this->params['ssl'] ? __('Enabled', 'geoip-detect') : __('Disabled', 'geoip-detect')) . '<br />';
185
+
186
+
187
+ if (!$this->isWorking())
188
+ $html .= '<div class="geoip_detect_error">' . __('Ipstack only works with an API key.', 'geoip-detect') . '</div>';
189
+
190
+ return $html;
191
+ }
192
+
193
+ public function getParameterHTML() {
194
+ $label_key = __('API Access Key:', 'geoip-detect');
195
+ $label_ssl = __('Access the API via SSL:', 'geoip-detect');
196
+
197
+ $key = esc_attr($this->params['key']);
198
+
199
+ $html = <<<HTML
200
+ $label_key <input type="text" autocomplete="off" size="20" name="options_ipstack[key]" value="$key" /><br />
201
+ $label_ssl <select name="options_ipstack[ssl]">
202
+ HTML;
203
+ $html .= '<option value="0" ' . (!$this->params['ssl'] ? ' selected="selected"' : '') . '">' . __('HTTP (without encryption, not GDPR-compatible)', 'geoip-detect') . '</option>';
204
+ $html .= '<option value="1" ' . ($this->params['ssl'] ? ' selected="selected"' : '') . '">' . __('HTTPS (with encryption - paid plans only)', 'geoip-detect') . '</option>';
205
+ $html .= '</select>';
206
+
207
+ return $html;
208
+ }
209
+
210
+ public function saveParameters($post) {
211
+ $message = '';
212
+
213
+ if (isset($post['options_ipstack']['key'])) {
214
+ update_option('geoip-detect-ipstack_key', $post['options_ipstack']['key']);
215
+ $this->params['key']= $post['options_ipstack']['key'];
216
+ }
217
+
218
+ if (isset($post['options_ipstack']['ssl'])) {
219
+ $ssl = (int) $post['options_ipstack']['ssl'];
220
+ update_option('geoip-detect-ipstack_ssl', $ssl);
221
+ $this->params['ssl'] = $post['options_ipstack']['ssl'];
222
+ }
223
+
224
+ if (geoip_detect2_is_source_active('ipstack') && !$this->isWorking())
225
+ $message .= __('Ipstack only works with an API key.', 'geoip-detect');
226
+
227
+ return $message;
228
+ }
229
+
230
+ public function getReader($locales = array('en'), $options = array()) {
231
+ return new Reader($this->params, $locales, $options);
232
+ }
233
+
234
+ public function isWorking() {
235
+ return !empty($this->params['key']);
236
+ }
237
+
238
+ }
239
+ geoip_detect2_register_source(new IpstackSource());
geoip-detect-lib.php CHANGED
@@ -202,7 +202,10 @@ function _geoip_detect2_record_enrich_data($record, $ip, $sourceId, $error) {
202
  }
203
  $data['extra']['source'] = $sourceId;
204
  $data['extra']['cached'] = 0;
205
- $data['extra']['error'] = $error;
 
 
 
206
 
207
  /**
208
  * Filter: geoip_detect2_record_data
@@ -445,3 +448,13 @@ function _geoip_maybe_disable_pagecache() {
445
 
446
  return true;
447
  }
 
 
 
 
 
 
 
 
 
 
202
  }
203
  $data['extra']['source'] = $sourceId;
204
  $data['extra']['cached'] = 0;
205
+
206
+ if ($error || !isset($data['extra']['error'])) {
207
+ $data['extra']['error'] = $error;
208
+ }
209
 
210
  /**
211
  * Filter: geoip_detect2_record_data
448
 
449
  return true;
450
  }
451
+
452
+ function _geoip_dashes_to_camel_case($string, $capitalizeFirstCharacter = false) {
453
+ $str = str_replace(' ', '', ucwords(str_replace('_', ' ', $string)));
454
+
455
+ if (!$capitalizeFirstCharacter) {
456
+ $str = lcfirst($str);
457
+ }
458
+
459
+ return $str;
460
+ }
geoip-detect.php CHANGED
@@ -5,7 +5,7 @@ Plugin URI: http://www.yellowtree.de
5
  Description: Retrieving Geo-Information using the Maxmind GeoIP (Lite) Database.
6
  Author: Yellow Tree (Benjamin Pick)
7
  Author URI: http://www.yellowtree.de
8
- Version: 2.11.1
9
  License: GPLv3 or later
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
  Text Domain: geoip-detect
@@ -16,7 +16,7 @@ Requires WP: 4.0
16
  Requires PHP: 5.4
17
  */
18
 
19
- define('GEOIP_DETECT_VERSION', '2.11.1');
20
 
21
  /*
22
  Copyright 2013-2019 Yellow Tree, Siegen, Germany
@@ -79,6 +79,7 @@ include_once(GEOIP_PLUGIN_DIR . '/data-sources/manual.php');
79
  include_once(GEOIP_PLUGIN_DIR . '/data-sources/auto.php');
80
  include_once(GEOIP_PLUGIN_DIR . '/data-sources/precision.php');
81
  include_once(GEOIP_PLUGIN_DIR . '/data-sources/header.php');
 
82
 
83
  // You can define these constants in your theme/plugin if you like.
84
 
5
  Description: Retrieving Geo-Information using the Maxmind GeoIP (Lite) Database.
6
  Author: Yellow Tree (Benjamin Pick)
7
  Author URI: http://www.yellowtree.de
8
+ Version: 2.12.0
9
  License: GPLv3 or later
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
  Text Domain: geoip-detect
16
  Requires PHP: 5.4
17
  */
18
 
19
+ define('GEOIP_DETECT_VERSION', '2.12.0');
20
 
21
  /*
22
  Copyright 2013-2019 Yellow Tree, Siegen, Germany
79
  include_once(GEOIP_PLUGIN_DIR . '/data-sources/auto.php');
80
  include_once(GEOIP_PLUGIN_DIR . '/data-sources/precision.php');
81
  include_once(GEOIP_PLUGIN_DIR . '/data-sources/header.php');
82
+ include_once(GEOIP_PLUGIN_DIR . '/data-sources/ipstack.php');
83
 
84
  // You can define these constants in your theme/plugin if you like.
85
 
init.php CHANGED
@@ -118,14 +118,20 @@ function geoip_detect_add_privacy_policy_content() {
118
  return;
119
  }
120
 
 
 
121
  $caching = '';
122
- if (GEOIP_DETECT_READER_CACHE_TIME > 0 && !DataSourceRegistry::getInstance()->isCachingUsed()) {
123
  $caching = sprintf(__('This site is saving the IP of the visitors of the last %s for performance reasons.', 'geoip-detect'), human_time_diff(0, GEOIP_DETECT_READER_CACHE_TIME));
124
  }
 
 
 
125
  $source = geoip_detect2_get_current_source_description();
126
  $content = sprintf(__( 'This site is using %s to identify the geographic location of your IP adress. %s (Add here: how this information is used, how long it is retained. Be especially careful when using this information to change prices or selling options, as this might not be legal.)', 'geoip-detect' ),
127
  $source, $caching);
128
 
 
129
  wp_add_privacy_policy_content(
130
  'GeoIP Detection',
131
  wp_kses_post( wpautop( $content, false ) )
118
  return;
119
  }
120
 
121
+ $registry = DataSourceRegistry::getInstance();
122
+
123
  $caching = '';
124
+ if (GEOIP_DETECT_READER_CACHE_TIME > 0 && !$registry->isCachingUsed()) {
125
  $caching = sprintf(__('This site is saving the IP of the visitors of the last %s for performance reasons.', 'geoip-detect'), human_time_diff(0, GEOIP_DETECT_READER_CACHE_TIME));
126
  }
127
+ if ($registry->isCachingUsed()) {
128
+ $caching = __('This site is sending the visitor\'s IP to (add Provider name) in order to receive the geographic information. (You will need to have a data-processing contract with this provider.)', 'geoip-detect');
129
+ }
130
  $source = geoip_detect2_get_current_source_description();
131
  $content = sprintf(__( 'This site is using %s to identify the geographic location of your IP adress. %s (Add here: how this information is used, how long it is retained. Be especially careful when using this information to change prices or selling options, as this might not be legal.)', 'geoip-detect' ),
132
  $source, $caching);
133
 
134
+
135
  wp_add_privacy_policy_content(
136
  'GeoIP Detection',
137
  wp_kses_post( wpautop( $content, false ) )
readme.txt CHANGED
@@ -2,7 +2,7 @@
2
  Contributors: benjaminpick
3
  Tags: geoip, maxmind, geolocation, locator
4
  Requires at least: 4.0
5
- Tested up to: 5.1
6
  Requires PHP: 5.4
7
  Stable tag: trunk
8
  License: GPLv3 or later
@@ -30,6 +30,7 @@ as a shortcode, or via CSS body classes. The city & country names are translated
30
  * Commercial Web-API: [Maxmind GeoIP2 Precision](https://www.maxmind.com/en/geoip2-precision-services) (City, Country or Insights)
31
  * Free (default source): [HostIP.info](http://www.hostip.info/) (IPv4 only)
32
  * Hosting-Provider dependent: [Cloudflare](https://support.cloudflare.com/hc/en-us/articles/200168236-What-does-CloudFlare-IP-Geolocation-do-) or [Amazon AWS CloudFront](https://aws.amazon.com/blogs/aws/enhanced-cloudfront-customization/) (Country)
 
33
  * For the property names, see the results of a specific IP in the wordpress backend (under *Tools > GeoIP Detection*).
34
  * You can include these properties into your posts and pages by using the shortcode `[geoip_detect2 property="country.name" default="(country could not be detected)" lang="en"]` (where 'country.name' can be one of the other property names as well, and 'default' and 'lang' are optional).
35
  * You can show or hide content by using a shortcode `[geoip_detect2_show_if country="FR, DE" not_city="Berlin"]TEXT[/geoip_detect2_show_if]`. See [Shortcode Documentation](https://github.com/yellowtree/geoip-detect/wiki/API:-Shortcodes#show-or-hide-content-depending-on-the-location).
@@ -53,7 +54,7 @@ See [Documentation](https://github.com/yellowtree/geoip-detect/wiki) for more in
53
 
54
  **System Requirements**: You will need at least PHP 5.4.
55
 
56
- *GDPR: This plugin does not store any cookie or user-dependent data. If you use a web-based source (hostip.info, Maxmind Precision), the plugin stores all IPs that visited the site in a cache (by default for 7 days) for performance reasons. If you want to disable this behavior, add `define('GEOIP_DETECT_READER_CACHE_TIME', 0);` in your theme's `function.php`. Be especially careful when using this information to change prices or selling options, as this might not be legal.*
57
 
58
  *This extension is "charity-ware". If you are happy with it, please [leave a tip](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=BSYUZHS8FH3CL) for the benefit of [this charity](http://www.jmem-hainichen.de/homepage). (See [FAQ](https://github.com/yellowtree/geoip-detect/wiki/FAQ#what-you-mean-by-this-plugin-is-charity-ware) for more infos.)*
59
 
@@ -108,6 +109,10 @@ Does `geoip_detect2_get_info_from_current_ip()` return the same country, regardl
108
 
109
  == Upgrade Notice ==
110
 
 
 
 
 
111
  = 2.11.0 =
112
 
113
  The Download code of the automatically updated Maxmind file was rewritten for better performance. Also, AJAX support is now in beta (see documentation).
@@ -127,6 +132,13 @@ New: Shortcode for showing/hiding content!
127
 
128
  == Changelog ==
129
 
 
 
 
 
 
 
 
130
  = 2.11.1 =
131
  * FIX: When activating the plugin on Wordpress MultiSite, an error was thrown before
132
  * NEW: Add body class "geoip-country-is-in-european-union" if the detected country is inside of the European Union
2
  Contributors: benjaminpick
3
  Tags: geoip, maxmind, geolocation, locator
4
  Requires at least: 4.0
5
+ Tested up to: 5.2
6
  Requires PHP: 5.4
7
  Stable tag: trunk
8
  License: GPLv3 or later
30
  * Commercial Web-API: [Maxmind GeoIP2 Precision](https://www.maxmind.com/en/geoip2-precision-services) (City, Country or Insights)
31
  * Free (default source): [HostIP.info](http://www.hostip.info/) (IPv4 only)
32
  * Hosting-Provider dependent: [Cloudflare](https://support.cloudflare.com/hc/en-us/articles/200168236-What-does-CloudFlare-IP-Geolocation-do-) or [Amazon AWS CloudFront](https://aws.amazon.com/blogs/aws/enhanced-cloudfront-customization/) (Country)
33
+ * Free or Commercial Web-API: [Ipstack](https://ipstack.com)
34
  * For the property names, see the results of a specific IP in the wordpress backend (under *Tools > GeoIP Detection*).
35
  * You can include these properties into your posts and pages by using the shortcode `[geoip_detect2 property="country.name" default="(country could not be detected)" lang="en"]` (where 'country.name' can be one of the other property names as well, and 'default' and 'lang' are optional).
36
  * You can show or hide content by using a shortcode `[geoip_detect2_show_if country="FR, DE" not_city="Berlin"]TEXT[/geoip_detect2_show_if]`. See [Shortcode Documentation](https://github.com/yellowtree/geoip-detect/wiki/API:-Shortcodes#show-or-hide-content-depending-on-the-location).
54
 
55
  **System Requirements**: You will need at least PHP 5.4.
56
 
57
+ *GDPR: This plugin does not store any cookie or user-dependent data. If you use a web-based source (hostip.info, Maxmind Precision, ipstack), the plugin stores all IPs that visited the site in a cache (by default for 7 days) for performance reasons. If you want to disable this behavior, add `define('GEOIP_DETECT_READER_CACHE_TIME', 0);` in your theme's `function.php`. Be especially careful when using geographic information to change prices or selling options, as this might not be legal.*
58
 
59
  *This extension is "charity-ware". If you are happy with it, please [leave a tip](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=BSYUZHS8FH3CL) for the benefit of [this charity](http://www.jmem-hainichen.de/homepage). (See [FAQ](https://github.com/yellowtree/geoip-detect/wiki/FAQ#what-you-mean-by-this-plugin-is-charity-ware) for more infos.)*
60
 
109
 
110
  == Upgrade Notice ==
111
 
112
+ = 2.12.0 =
113
+
114
+ New: Ipstack.com can be used as data source
115
+
116
  = 2.11.0 =
117
 
118
  The Download code of the automatically updated Maxmind file was rewritten for better performance. Also, AJAX support is now in beta (see documentation).
132
 
133
  == Changelog ==
134
 
135
+ = 2.12.0 =
136
+ * NEW: It is now possible to use ipstack.com as a data source.
137
+ * The Backup Lookup UI now can show all properties and you can choose if you want to see the PHP, Shortcode or JS syntax.
138
+
139
+ = 2.11.2 =
140
+ * The auto-updater of the Maxmind City Lite source now updates more often (every 1-2weeks) in order to get more accurate data.
141
+
142
  = 2.11.1 =
143
  * FIX: When activating the plugin on Wordpress MultiSite, an error was thrown before
144
  * NEW: Add body class "geoip-country-is-in-european-union" if the detected country is inside of the European Union
shortcode.php CHANGED
@@ -56,7 +56,7 @@ add_shortcode('geoip_detect', 'geoip_detect_shortcode');
56
  * `[geoip_detect2 property="country" lang="fr,de"]` -> Allemagne
57
  * `[geoip_detect2 property="country.confidence" skip_cache="true" default="default value"]` -> default value
58
  *
59
- * @param string $property Property to read. Instead of '->', use '.'
60
  * @param string $lang Language(s) (optional. If not set, current site language is used.)
61
  * @param string $default Default Value that will be shown if value not set (optional)
62
  * @param string $skip_cache if 'true': Do not cache value
56
  * `[geoip_detect2 property="country" lang="fr,de"]` -> Allemagne
57
  * `[geoip_detect2 property="country.confidence" skip_cache="true" default="default value"]` -> default value
58
  *
59
+ * @param string $property Property to read. For a list of all possible property names, see https://github.com/yellowtree/geoip-detect/wiki/Record-Properties#list-of-all-property-names
60
  * @param string $lang Language(s) (optional. If not set, current site language is used.)
61
  * @param string $default Default Value that will be shown if value not set (optional)
62
  * @param string $skip_cache if 'true': Do not cache value
views/lookup.php CHANGED
@@ -4,16 +4,7 @@ $date_format = get_option('date_format') . ' ' . get_option('time_format');
4
 
5
  $current_source = DataSourceRegistry::getInstance()->getCurrentSource();
6
 
7
- $shortcode_options = array();
8
- $shortcode_attr = '';
9
- if (!empty($_POST['locales']))
10
- $shortcode_options['lang'] = $_POST['locales'];
11
- if ($shortcode_options) {
12
- $shortcode_attr = '';
13
- foreach($shortcode_options as $key => $value){
14
- $shortcode_attr .= ' ' . $key.'="'.esc_attr($value).'"';
15
- }
16
- }
17
  ?>
18
  <div class="wrap geoip-detect-wrap">
19
  <h1><?php _e('GeoIP Detection', 'geoip-detect');?></h1>
@@ -46,7 +37,15 @@ if ($shortcode_options) {
46
  <option value="" <?php if (empty($_POST['locales'])) echo 'selected="selected"'?>><?php _e('Default (Current site language, English otherwise)', 'geoip-detect')?></option>
47
  <option value="en" <?php if (!empty($_POST['locales']) && $_POST['locales'] == 'en') echo 'selected="selected"'?>><?php _e('English only', 'geoip-detect')?></option>
48
  <option value="fr,en" <?php if (!empty($_POST['locales']) && $_POST['locales'] == 'fr,en') echo 'selected="selected"'?>><?php _e('French, English otherwise', 'geoip-detect')?></option>
49
- </select> </label><br />
 
 
 
 
 
 
 
 
50
  <label><input type="checkbox" name="skip_cache" value="1" <?php if (!empty($_POST['skip_cache'])) echo 'checked="checked"'?>/><?php _e('Skip cache', 'geoip-detect')?></label><br />
51
  <br />
52
  <input type="submit" class="button button-primary" value="<?php _e('Lookup', 'geoip-detect'); ?>" />
@@ -54,11 +53,24 @@ if ($shortcode_options) {
54
  <?php if ($ip_lookup_result !== false) :
55
  if (is_object($ip_lookup_result)) :
56
  $record = $ip_lookup_result;
 
 
57
 
58
  ?>
59
  <h3><?php _e('Lookup Result', 'geoip-detect'); ?></h3>
60
  <p>
 
61
  <?php printf(__('The function %s returns an object:', 'geoip-detect'), "<code>\$record = geoip_detect2_get_info_from_ip('" . esc_html($request_ip) . "', " . var_export($request_locales, true) . ($request_skipCache ? ', TRUE' : '') .");</code>"); ?><br />
 
 
 
 
 
 
 
 
 
 
62
  <?php printf(__('Lookup duration: %.5f s', 'geoip-detect'), $ip_lookup_duration); ?>
63
  <?php if ($record->extra->cached) : ?>
64
  <br /><?php printf(__('(Served from cache. Was cached %s ago)', 'geoip-detect'), human_time_diff($record->extra->cached));?>
@@ -73,59 +85,102 @@ if ($shortcode_options) {
73
 
74
  <table>
75
  <tr>
76
- <th><?php _e('Key', 'geoip-detect'); ?></th>
77
- <th><?php _e('Value', 'geoip-detect'); ?></th>
78
- <th><?php _e('Shortcode equivalent', 'geoip-detect'); ?></th>
79
  </tr>
80
 
81
- <tr>
82
- <td><code>$record-&gt;city-&gt;name</code></td>
83
- <td><?php echo esc_html($record->city->name);?></td>
84
- <td><code>[geoip_detect2 property="city"<?php echo $shortcode_attr; ?>]</code></td>
85
- </tr>
86
- <tr>
87
- <td><code>$record-&gt;mostSpecificSubdivision-&gt;isoCode</code></td>
88
- <td><?php echo esc_html($record->mostSpecificSubdivision->isoCode);?></td>
89
- <td><code>[geoip_detect2 property="mostSpecificSubdivision.isoCode"]</code></td>
90
- </tr>
91
- <tr>
92
- <td><code>$record-&gt;mostSpecificSubdivision-&gt;name</code></td>
93
- <td><?php echo esc_html($record->mostSpecificSubdivision->name);?></td>
94
- <td><code>[geoip_detect2 property="mostSpecificSubdivision"<?php echo $shortcode_attr; ?>]</code></td>
95
- </tr>
96
- <tr>
97
- <td><code>$record-&gt;country-&gt;isoCode</code></td>
98
- <td><?php echo esc_html($record->country->isoCode);?></td>
99
- <td><code>[geoip_detect2 property="country.isoCode"]</code></td>
100
- </tr>
101
- <tr>
102
- <td><code>$record-&gt;country-&gt;name</code></td>
103
- <td><?php echo esc_html($record->country->name);?></td>
104
- <td><code>[geoip_detect2 property="country"<?php echo $shortcode_attr; ?>]</code></td>
105
- </tr>
106
- <tr>
107
- <td><code>$record-&gt;location-&gt;latitude</code></td>
108
- <td><?php echo esc_html($record->location->latitude);?></td>
109
- <td><code>[geoip_detect2 property="location.latitude"]</code></td>
110
- </tr>
111
- <tr>
112
- <td><code>$record-&gt;location-&gt;longitude</code></td>
113
- <td><?php echo esc_html($record->location->longitude);?></td>
114
- <td><code>[geoip_detect2 property="location.longitude"]</code></td>
115
- </tr>
116
- <tr>
117
- <td><code>$record-&gt;continent-&gt;code</code></td>
118
- <td><?php echo esc_html($record->continent->code);?></td>
119
- <td><code>[geoip_detect2 property="continent.code"]</code></td>
120
- </tr>
121
- <tr>
122
- <td><code>$record-&gt;location-&gt;timeZone</code></td>
123
- <td><?php echo esc_html($record->location->timeZone);?></td>
124
- <td><code>[geoip_detect2 property="location.timeZone"]</code></td>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  </tr>
126
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  </table>
128
 
 
 
 
 
129
  <?php elseif ($ip_lookup_result === 0 || is_null($ip_lookup_result)) : ?>
130
  <p>
131
  <?php _e('No information found about this IP.', 'geoip-detect')?>
@@ -137,3 +192,12 @@ if ($shortcode_options) {
137
  </p>
138
  <?php require(GEOIP_PLUGIN_DIR . '/views/footer.php'); ?>
139
  </div>
 
 
 
 
 
 
 
 
 
4
 
5
  $current_source = DataSourceRegistry::getInstance()->getCurrentSource();
6
 
7
+ $is_ajax_enabled = !!get_option('geoip-detect-ajax_enabled');
 
 
 
 
 
 
 
 
 
8
  ?>
9
  <div class="wrap geoip-detect-wrap">
10
  <h1><?php _e('GeoIP Detection', 'geoip-detect');?></h1>
37
  <option value="" <?php if (empty($_POST['locales'])) echo 'selected="selected"'?>><?php _e('Default (Current site language, English otherwise)', 'geoip-detect')?></option>
38
  <option value="en" <?php if (!empty($_POST['locales']) && $_POST['locales'] == 'en') echo 'selected="selected"'?>><?php _e('English only', 'geoip-detect')?></option>
39
  <option value="fr,en" <?php if (!empty($_POST['locales']) && $_POST['locales'] == 'fr,en') echo 'selected="selected"'?>><?php _e('French, English otherwise', 'geoip-detect')?></option>
40
+ </select>
41
+ </label><br />
42
+ <label><?php _e('Which syntax:', 'geoip_detect'); ?>
43
+ <select name="syntax">
44
+ <option value="php" <?php if (empty($_POST['syntax']) || $_POST['syntax'] === 'php') echo 'selected="selected"'?>><?= __('PHP Syntax') ?></option>
45
+ <option value="shortcode" <?php if (!empty($_POST['syntax']) && $_POST['syntax'] === 'shortcode') echo 'selected="selected"'?>><?= __('Shortcode Syntax') ?></option>
46
+ <option value="js" <?php if (!empty($_POST['syntax']) && $_POST['syntax'] === 'js') echo 'selected="selected"'?>><?= __('JS Syntax') ?></option>
47
+ </select>
48
+ </label><br>
49
  <label><input type="checkbox" name="skip_cache" value="1" <?php if (!empty($_POST['skip_cache'])) echo 'checked="checked"'?>/><?php _e('Skip cache', 'geoip-detect')?></label><br />
50
  <br />
51
  <input type="submit" class="button button-primary" value="<?php _e('Lookup', 'geoip-detect'); ?>" />
53
  <?php if ($ip_lookup_result !== false) :
54
  if (is_object($ip_lookup_result)) :
55
  $record = $ip_lookup_result;
56
+ $data = _geoip_detect_improve_data_for_lookup($record->jsonSerialize());
57
+ $data_short = _geoip_detect_improve_data_for_lookup($record->jsonSerialize(), true);
58
 
59
  ?>
60
  <h3><?php _e('Lookup Result', 'geoip-detect'); ?></h3>
61
  <p>
62
+ <?php if ($_POST['syntax'] == 'php') : ?>
63
  <?php printf(__('The function %s returns an object:', 'geoip-detect'), "<code>\$record = geoip_detect2_get_info_from_ip('" . esc_html($request_ip) . "', " . var_export($request_locales, true) . ($request_skipCache ? ', TRUE' : '') .");</code>"); ?><br />
64
+ <?= sprintf(__('See %s for more information.', 'geoip-detect'), '<a href="https://github.com/yellowtree/geoip-detect/wiki/API:-PHP">API: PHP</a>'); ?>
65
+ <?php elseif ($_POST['syntax'] == 'shortcode') : ?>
66
+ <?= sprintf(__('You can use the following shortcodes.', 'geoip-detect')); ?><br />
67
+ <?= sprintf(__('See %s for more information.', 'geoip-detect'), '<a href="https://github.com/yellowtree/geoip-detect/wiki/API:-Shortcodes">API: Shortcodes</a>'); ?>
68
+ <?php elseif ($_POST['syntax'] == 'js') : ?>
69
+ <?= sprintf(__('AJAX and JS must be enabled in the preferences!', 'geoip-detect')); ?><br />
70
+ <?= sprintf(__('See %s for more information.', 'geoip-detect'), '<a href="https://github.com/yellowtree/geoip-detect/wiki/API:-AJAX">API: AJAX</a>'); ?>
71
+ <?php endif; ?>
72
+ </p>
73
+ <p>
74
  <?php printf(__('Lookup duration: %.5f s', 'geoip-detect'), $ip_lookup_duration); ?>
75
  <?php if ($record->extra->cached) : ?>
76
  <br /><?php printf(__('(Served from cache. Was cached %s ago)', 'geoip-detect'), human_time_diff($record->extra->cached));?>
85
 
86
  <table>
87
  <tr>
88
+ <th></th>
89
+ <th style="text-align: left"><?php _e('Value', 'geoip-detect'); ?></th>
 
90
  </tr>
91
 
92
+ <?php
93
+ function show_row($record, $key_1, $key_2, $value = null, $class = '') {
94
+ if (is_array($value)) {
95
+ if ($key_2 === 'names') {
96
+ show_row($record, $key_1, 'name', null, $class);
97
+ return;
98
+ }
99
+ if ($key_1 === 'subdivisions') {
100
+ foreach ($value as $key_3 => $v) {
101
+ show_row($record, 'most_specific_subdivision', $key_3, $v, $class);
102
+ }
103
+ return;
104
+ }
105
+ }
106
+ $camel_key_1 = _geoip_dashes_to_camel_case($key_1);
107
+ $camel_key_2 = _geoip_dashes_to_camel_case($key_2);
108
+
109
+ try {
110
+ if (is_object($record) ) {
111
+ $value = $record->$camel_key_1;
112
+ if (is_object($value)) {
113
+ $value = $value->$camel_key_2;
114
+ }
115
+ }
116
+ } catch(\RuntimeException $e) {
117
+ return; // Access did not work.
118
+ }
119
+ if (!is_string($value)) {
120
+ $value = var_export($value, true);
121
+ }
122
+
123
+ switch($_POST['syntax']) {
124
+ case 'shortcode':
125
+ $extra = '';
126
+ if (!empty($_POST['locales']) && $key_2 === 'name') {
127
+ $extra .= ' lang="' . $_POST['locales'] . '"';
128
+ }
129
+ if (!empty($_POST['skip_cache'])) {
130
+ $extra .= ' skip_cache="true"';
131
+ }
132
+
133
+ $access = '[geoip_detect2 property="' . $camel_key_1 . '.' . $camel_key_2 . '"' . $extra . ']';
134
+ break;
135
+
136
+ case 'js':
137
+ $prop = '"' . $key_1 . '.' . $key_2 . '"';
138
+ if (!empty($_POST['locales']) && $key_2 === 'name') {
139
+ $access = 'record.get_with_locales(' . $prop . ', ' . json_encode(explode(',', $_POST['locales'])) . ')';
140
+ } else {
141
+ $access = 'record.get(' . $prop . ')';
142
+ }
143
+ break;
144
+
145
+ case 'php':
146
+ default:
147
+ $access = '$record->' . $camel_key_1 . '->' . $camel_key_2;
148
+ break;
149
+ }
150
+ ?>
151
+ <tr class="<?= $class ?>">
152
+ <td><code><?= esc_html($access) ?></code></td>
153
+ <td><?= esc_html($value);?></td>
154
  </tr>
155
 
156
+ <?php
157
+
158
+ }
159
+
160
+ foreach($data as $key_1 => $value_1) {
161
+ if (is_array($value_1)) {
162
+ foreach($value_1 as $key_2 => $value_2) {
163
+ show_row($record, $key_1, $key_2, $value_2, 'all');
164
+ }
165
+ }
166
+ }
167
+
168
+ foreach($data_short as $key_1 => $value_1) {
169
+ if (is_array($value_1)) {
170
+ foreach($value_1 as $key_2 => $value_2) {
171
+ show_row($record, $key_1, $key_2, $value_2, 'short');
172
+ }
173
+ }
174
+ }
175
+
176
+ ?>
177
+
178
  </table>
179
 
180
+ <p class="all"><a href="#" onclick="geoip_properties_toggle('short', 'all'); return false;"><?= __('Show only the most common properties', 'geoip-detect') ?></a></p>
181
+ <p class="short"><a href="#" onclick="geoip_properties_toggle('all', 'short'); return false;"><?= __('Show all available properties', 'geoip-detect') ?></a></p>
182
+ <p><?= __('(More properties might be available for other IPs and with other data sources.)', 'geoip-detect'); ?></p>
183
+
184
  <?php elseif ($ip_lookup_result === 0 || is_null($ip_lookup_result)) : ?>
185
  <p>
186
  <?php _e('No information found about this IP.', 'geoip-detect')?>
192
  </p>
193
  <?php require(GEOIP_PLUGIN_DIR . '/views/footer.php'); ?>
194
  </div>
195
+ <script>
196
+ function geoip_properties_toggle(show, hide) {
197
+ jQuery('.' + show).show();
198
+ jQuery('.' + hide).hide();
199
+ }
200
+ jQuery('document').ready(function() {
201
+ jQuery('.all').hide();
202
+ })
203
+ </script>