PluginProbe ʕ •ᴥ•ʔ
Paid Membership Plugin, Ecommerce, User Registration Form, Login Form, User Profile & Restrict Content – ProfilePress / 4.0.3
Paid Membership Plugin, Ecommerce, User Registration Form, Login Form, User Profile & Restrict Content – ProfilePress v4.0.3
4.17.2 4.17.1 4.17.0 4.16.19 4.16.18 4.16.17 4.16.16 trunk 1.0 1.0.1 1.0.2 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5a 1.1.6 1.1.7 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.4 1.4.1 1.4.2 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.7 1.7.1 1.7.2 1.8 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.1.9 2.2.10 2.2.11 2.2.12 2.2.13 2.2.14 2.2.15 2.2.16 2.2.2 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 3.0 3.1 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 3.1.19 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.10 3.2.11 3.2.12 3.2.13 3.2.14 3.2.15 3.2.16 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 4.0.0 4.0.1 4.0.2 4.0.3 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.10.0 4.10.1 4.10.2 4.10.3 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.13.3 4.13.4 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.15.0 4.15.1 4.15.10 4.15.11 4.15.12 4.15.13 4.15.14 4.15.15 4.15.16 4.15.17 4.15.18 4.15.19 4.15.2 4.15.20 4.15.20.1 4.15.21 4.15.22 4.15.23 4.15.24 4.15.25 4.15.3 4.15.4 4.15.5 4.15.6 4.15.7 4.15.8 4.15.9 4.16.0 4.16.1 4.16.10 4.16.11 4.16.12 4.16.13 4.16.14 4.16.15 4.16.2 4.16.3 4.16.4 4.16.5 4.16.6 4.16.7 4.16.8 4.16.9 4.2.0 4.3.0 4.3.1 4.3.2 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.7.0 4.8.0 4.9.0
wp-user-avatar / src / Classes / Geolocation.php
wp-user-avatar / src / Classes Last commit date
Installer 5 years ago AdminNotices.php 4 years ago AjaxHandler.php 4 years ago Autologin.php 4 years ago BuddyPressBbPress.php 5 years ago EditUserProfile.php 4 years ago ExtensionManager.php 4 years ago FileUploader.php 4 years ago FormPreviewHandler.php 5 years ago FormRepository.php 4 years ago FormShortcodeDefaults.php 5 years ago GDPR.php 4 years ago Geolocation.php 4 years ago GlobalSiteAccess.php 4 years ago ImageUploader.php 4 years ago LoginAuth.php 4 years ago Miscellaneous.php 4 years ago ModifyRedirectDefaultLinks.php 4 years ago PPRESS_Session.php 4 years ago PROFILEPRESS_sql.php 4 years ago PasswordReset.php 4 years ago ProfileUrlRewrite.php 4 years ago RegistrationAuth.php 4 years ago SendEmail.php 4 years ago ShortcodeThemeFactory.php 5 years ago UserAvatar.php 4 years ago UserSignupLocationListingPage.php 4 years ago UsernameEmailRestrictLogin.php 4 years ago WPProfileFieldParserTrait.php 4 years ago WelcomeEmailAfterSignup.php 4 years ago default-email-template.php 4 years ago index.php 5 years ago
Geolocation.php
247 lines
1 <?php
2
3 namespace ProfilePress\Core\Classes;
4
5 class Geolocation
6 {
7
8 /**
9 * API endpoints for looking up user IP address.
10 *
11 * @var array
12 */
13 private static $ip_lookup_apis = array(
14 'ipify' => 'http://api.ipify.org/',
15 'ipecho' => 'http://ipecho.net/plain',
16 'ident' => 'http://ident.me',
17 'whatismyipaddress' => 'http://bot.whatismyipaddress.com',
18 );
19
20 /**
21 * API endpoints for geolocating an IP address
22 *
23 * @var array
24 */
25 private static $geoip_apis = array(
26 'ipinfo.io' => 'https://ipinfo.io/%s/json',
27 'ip-api.com' => 'http://ip-api.com/json/%s',
28 );
29
30 /**
31 * Get current user IP Address.
32 *
33 * @return string
34 */
35 public static function get_ip_address()
36 {
37 if (isset($_SERVER['HTTP_X_REAL_IP'])) {
38 return sanitize_text_field(wp_unslash($_SERVER['HTTP_X_REAL_IP']));
39 } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
40 // Proxy servers can send through this header like this: X-Forwarded-For: client1, proxy1, proxy2
41 // Make sure we always only send through the first IP in the list which should always be the client IP.
42 return (string)rest_is_ip_address(trim(current(preg_split('/,/', sanitize_text_field(wp_unslash($_SERVER['HTTP_X_FORWARDED_FOR']))))));
43 } elseif (isset($_SERVER['REMOTE_ADDR'])) {
44 return sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR']));
45 }
46
47 return '';
48 }
49
50 /**
51 * Get user IP Address using an external service.
52 * This can be used as a fallback for users on localhost where
53 * get_ip_address() will be a local IP and non-geolocatable.
54 *
55 * @return string
56 */
57 public static function get_external_ip_address()
58 {
59 $external_ip_address = '0.0.0.0';
60
61 if ('' !== self::get_ip_address()) {
62 $transient_name = 'external_ip_address_' . self::get_ip_address();
63 $external_ip_address = get_transient($transient_name);
64 }
65
66 if (false === $external_ip_address) {
67 $external_ip_address = '0.0.0.0';
68 $ip_lookup_services = apply_filters('ppress_geolocation_ip_lookup_apis', self::$ip_lookup_apis);
69 $ip_lookup_services_keys = array_keys($ip_lookup_services);
70 shuffle($ip_lookup_services_keys);
71
72 foreach ($ip_lookup_services_keys as $service_name) {
73 $service_endpoint = $ip_lookup_services[$service_name];
74 $response = wp_safe_remote_get($service_endpoint, array('timeout' => 2));
75
76 if ( ! is_wp_error($response) && rest_is_ip_address($response['body'])) {
77 $external_ip_address = apply_filters('ppress_geolocation_ip_lookup_api_response', ppress_clean($response['body']), $service_name);
78 break;
79 }
80 }
81
82 if (isset($transient_name)) {
83 set_transient($transient_name, $external_ip_address, DAY_IN_SECONDS);
84 }
85 }
86
87 return $external_ip_address;
88 }
89
90 /**
91 * Geolocate an IP address.
92 *
93 * @param string $ip_address IP Address.
94 * @param bool $fallback If true, fallbacks to alternative IP detection (can be slower).
95 * @param bool $api_fallback If true, uses geolocation APIs if the database file doesn't exist (can be slower).
96 *
97 * @return array
98 */
99 public static function geolocate_ip($ip_address = '', $fallback = false, $api_fallback = true)
100 {
101 // Filter to allow custom geolocation of the IP address.
102 $country_code = apply_filters('ppress_geolocate_ip', false, $ip_address, $fallback, $api_fallback);
103
104 if (false !== $country_code) {
105 return array(
106 'country' => $country_code,
107 'state' => '',
108 'city' => '',
109 'postcode' => '',
110 );
111 }
112
113 if (empty($ip_address)) {
114 $ip_address = self::get_ip_address();
115 $country_code = self::get_country_code_from_headers();
116 }
117
118 /**
119 * Get geolocation filter.
120 *
121 * @param array $geolocation Geolocation data, including country, state, city, and postcode.
122 * @param string $ip_address IP Address.
123 */
124 $geolocation = apply_filters(
125 'ppress_get_geolocation',
126 array(
127 'country' => $country_code,
128 'state' => '',
129 'city' => '',
130 'postcode' => '',
131 ),
132 $ip_address
133 );
134
135 // If we still haven't found a country code, let's consider doing an API lookup.
136 if ('' === $geolocation['country'] && $api_fallback) {
137 $geolocation['country'] = self::geolocate_via_api($ip_address);
138 }
139
140 // It's possible that we're in a local environment, in which case the geolocation needs to be done from the
141 // external address.
142 if ('' === $geolocation['country'] && $fallback) {
143 $external_ip_address = self::get_external_ip_address();
144
145 // Only bother with this if the external IP differs.
146 if ('0.0.0.0' !== $external_ip_address && $external_ip_address !== $ip_address) {
147 return self::geolocate_ip($external_ip_address, false, $api_fallback);
148 }
149 }
150
151 return array(
152 'country' => $geolocation['country'],
153 'state' => $geolocation['state'],
154 'city' => $geolocation['city'],
155 'postcode' => $geolocation['postcode'],
156 );
157 }
158
159 /**
160 * Fetches the country code from the request headers, if one is available.
161 *
162 * @return string The country code pulled from the headers, or empty string if one was not found.
163 */
164 private static function get_country_code_from_headers()
165 {
166 $country_code = '';
167
168 $headers = array(
169 'MM_COUNTRY_CODE',
170 'GEOIP_COUNTRY_CODE',
171 'HTTP_CF_IPCOUNTRY',
172 'HTTP_X_COUNTRY_CODE',
173 );
174
175 foreach ($headers as $header) {
176 if (empty($_SERVER[$header])) {
177 continue;
178 }
179
180 $country_code = strtoupper(sanitize_text_field(wp_unslash($_SERVER[$header])));
181 break;
182 }
183
184 return $country_code;
185 }
186
187 /**
188 * Use APIs to Geolocate the user.
189 *
190 * Geolocation APIs can be added through the use of the ppress_geolocation_geoip_apis filter.
191 * Provide a name=>value pair for service-slug=>endpoint.
192 *
193 * If APIs are defined, one will be chosen at random to fulfil the request. After completing, the result
194 * will be cached in a transient.
195 *
196 * @param string $ip_address IP address.
197 *
198 * @return string
199 */
200 private static function geolocate_via_api($ip_address)
201 {
202 $country_code = get_transient('geoip_' . $ip_address);
203
204 if (false === $country_code) {
205 $geoip_services = apply_filters('ppress_geolocation_geoip_apis', self::$geoip_apis);
206
207 if (empty($geoip_services)) {
208 return '';
209 }
210
211 $geoip_services_keys = array_keys($geoip_services);
212
213 shuffle($geoip_services_keys);
214
215 foreach ($geoip_services_keys as $service_name) {
216 $service_endpoint = $geoip_services[$service_name];
217 $response = wp_safe_remote_get(sprintf($service_endpoint, $ip_address), array('timeout' => 2));
218
219 if ( ! is_wp_error($response) && $response['body']) {
220 switch ($service_name) {
221 case 'ipinfo.io':
222 $data = json_decode($response['body']);
223 $country_code = isset($data->country) ? $data->country : '';
224 break;
225 case 'ip-api.com':
226 $data = json_decode($response['body']);
227 $country_code = isset($data->countryCode) ? $data->countryCode : ''; // @codingStandardsIgnoreLine
228 break;
229 default:
230 $country_code = apply_filters('ppress_geolocation_geoip_response_' . $service_name, '', $response['body']);
231 break;
232 }
233
234 $country_code = sanitize_text_field(strtoupper($country_code));
235
236 if ($country_code) {
237 break;
238 }
239 }
240 }
241
242 set_transient('geoip_' . $ip_address, $country_code, DAY_IN_SECONDS);
243 }
244
245 return $country_code;
246 }
247 }