![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/mets.corals.io/wp-content/plugins/wp-user-avatar/src/Classes/ |
<?php namespace ProfilePress\Core\Classes; class Geolocation { /** * API endpoints for looking up user IP address. * * @var array */ private static $ip_lookup_apis = array( 'ipify' => 'http://api.ipify.org/', 'ipecho' => 'http://ipecho.net/plain', 'ident' => 'http://ident.me', 'whatismyipaddress' => 'http://bot.whatismyipaddress.com', ); /** * API endpoints for geolocating an IP address * * @var array */ private static $geoip_apis = array( 'ipinfo.io' => 'https://ipinfo.io/%s/json', 'ip-api.com' => 'http://ip-api.com/json/%s', ); /** * Get current user IP Address. * * @return string */ public static function get_ip_address() { if (isset($_SERVER['HTTP_X_REAL_IP'])) { return sanitize_text_field(wp_unslash($_SERVER['HTTP_X_REAL_IP'])); } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { // Proxy servers can send through this header like this: X-Forwarded-For: client1, proxy1, proxy2 // Make sure we always only send through the first IP in the list which should always be the client IP. return (string)rest_is_ip_address(trim(current(preg_split('/,/', sanitize_text_field(wp_unslash($_SERVER['HTTP_X_FORWARDED_FOR'])))))); } elseif (isset($_SERVER['REMOTE_ADDR'])) { return sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])); } return ''; } /** * Get user IP Address using an external service. * This can be used as a fallback for users on localhost where * get_ip_address() will be a local IP and non-geolocatable. * * @return string */ public static function get_external_ip_address() { $external_ip_address = '0.0.0.0'; if ('' !== self::get_ip_address()) { $transient_name = 'external_ip_address_' . self::get_ip_address(); $external_ip_address = get_transient($transient_name); } if (false === $external_ip_address) { $external_ip_address = '0.0.0.0'; $ip_lookup_services = apply_filters('ppress_geolocation_ip_lookup_apis', self::$ip_lookup_apis); $ip_lookup_services_keys = array_keys($ip_lookup_services); shuffle($ip_lookup_services_keys); foreach ($ip_lookup_services_keys as $service_name) { $service_endpoint = $ip_lookup_services[$service_name]; $response = wp_safe_remote_get($service_endpoint, array('timeout' => 2)); if ( ! is_wp_error($response) && rest_is_ip_address($response['body'])) { $external_ip_address = apply_filters('ppress_geolocation_ip_lookup_api_response', ppress_clean($response['body']), $service_name); break; } } if (isset($transient_name)) { set_transient($transient_name, $external_ip_address, DAY_IN_SECONDS); } } return $external_ip_address; } /** * Geolocate an IP address. * * @param string $ip_address IP Address. * @param bool $fallback If true, fallbacks to alternative IP detection (can be slower). * @param bool $api_fallback If true, uses geolocation APIs if the database file doesn't exist (can be slower). * * @return array */ public static function geolocate_ip($ip_address = '', $fallback = false, $api_fallback = true) { // Filter to allow custom geolocation of the IP address. $country_code = apply_filters('ppress_geolocate_ip', false, $ip_address, $fallback, $api_fallback); if (false !== $country_code) { return array( 'country' => $country_code, 'state' => '', 'city' => '', 'postcode' => '', ); } if (empty($ip_address)) { $ip_address = self::get_ip_address(); $country_code = self::get_country_code_from_headers(); } /** * Get geolocation filter. * * @param array $geolocation Geolocation data, including country, state, city, and postcode. * @param string $ip_address IP Address. */ $geolocation = apply_filters( 'ppress_get_geolocation', array( 'country' => $country_code, 'state' => '', 'city' => '', 'postcode' => '', ), $ip_address ); // If we still haven't found a country code, let's consider doing an API lookup. if ('' === $geolocation['country'] && $api_fallback) { $geolocation['country'] = self::geolocate_via_api($ip_address); } // It's possible that we're in a local environment, in which case the geolocation needs to be done from the // external address. if ('' === $geolocation['country'] && $fallback) { $external_ip_address = self::get_external_ip_address(); // Only bother with this if the external IP differs. if ('0.0.0.0' !== $external_ip_address && $external_ip_address !== $ip_address) { return self::geolocate_ip($external_ip_address, false, $api_fallback); } } return array( 'country' => $geolocation['country'], 'state' => $geolocation['state'], 'city' => $geolocation['city'], 'postcode' => $geolocation['postcode'], ); } /** * Fetches the country code from the request headers, if one is available. * * @return string The country code pulled from the headers, or empty string if one was not found. */ private static function get_country_code_from_headers() { $country_code = ''; $headers = array( 'MM_COUNTRY_CODE', 'GEOIP_COUNTRY_CODE', 'HTTP_CF_IPCOUNTRY', 'HTTP_X_COUNTRY_CODE', ); foreach ($headers as $header) { if (empty($_SERVER[$header])) { continue; } $country_code = strtoupper(sanitize_text_field(wp_unslash($_SERVER[$header]))); break; } return $country_code; } /** * Use APIs to Geolocate the user. * * Geolocation APIs can be added through the use of the ppress_geolocation_geoip_apis filter. * Provide a name=>value pair for service-slug=>endpoint. * * If APIs are defined, one will be chosen at random to fulfil the request. After completing, the result * will be cached in a transient. * * @param string $ip_address IP address. * * @return string */ private static function geolocate_via_api($ip_address) { $country_code = get_transient('geoip_' . $ip_address); if (false === $country_code) { $geoip_services = apply_filters('ppress_geolocation_geoip_apis', self::$geoip_apis); if (empty($geoip_services)) { return ''; } $geoip_services_keys = array_keys($geoip_services); shuffle($geoip_services_keys); foreach ($geoip_services_keys as $service_name) { $service_endpoint = $geoip_services[$service_name]; $response = wp_safe_remote_get(sprintf($service_endpoint, $ip_address), array('timeout' => 2)); if ( ! is_wp_error($response) && $response['body']) { switch ($service_name) { case 'ipinfo.io': $data = json_decode($response['body']); $country_code = isset($data->country) ? $data->country : ''; break; case 'ip-api.com': $data = json_decode($response['body']); $country_code = isset($data->countryCode) ? $data->countryCode : ''; // @codingStandardsIgnoreLine break; default: $country_code = apply_filters('ppress_geolocation_geoip_response_' . $service_name, '', $response['body']); break; } $country_code = sanitize_text_field(strtoupper($country_code)); if ($country_code) { break; } } } set_transient('geoip_' . $ip_address, $country_code, DAY_IN_SECONDS); } return $country_code; } }