Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 30 additions & 62 deletions inc/class-wpoau-active-users.php
Original file line number Diff line number Diff line change
Expand Up @@ -242,17 +242,21 @@ public function wpoau_get_user_ip() {
}

/**
* Resolve a country name from an IP address, with 24-hour caching.
* Fetch and cache full IP geolocation data (country, country code, timezone) from a single
* ipwho.is lookup, so country/timezone/country-code all share one cached HTTPS request instead
* of hitting three separate endpoints (ipwho.is was already used for country; the other two
* previously called ip-api.com over plain HTTP, whose free tier also forbids commercial use --
* a conflict with this plugin's advertised WooCommerce support).
*
* @param string $ip IP address.
* @return string
* @return array|null Decoded API response, or null on failure/unknown IP.
*/
public function wpoau_get_user_country( $ip ) {
protected function wpoau_get_ip_geodata( $ip ) {
if ( 'Unknown' === $ip || empty( $ip ) ) {
return 'Unknown';
return null;
}

$transient_key = 'wpoau_country_name_' . md5( $ip );
$transient_key = 'wpoau_geodata_' . md5( $ip );
$cached = get_transient( $transient_key );
if ( false !== $cached ) {
return $cached;
Expand All @@ -261,53 +265,43 @@ public function wpoau_get_user_country( $ip ) {
$response = wp_remote_get( "https://ipwho.is/{$ip}" );

if ( is_wp_error( $response ) ) {
return 'Unknown';
return null;
}

$data = json_decode( wp_remote_retrieve_body( $response ), true );

if ( ! is_array( $data ) || ! $data['success'] ) {
return 'Unknown';
if ( ! is_array( $data ) || empty( $data['success'] ) ) {
return null;
}

$country = $data['country'] ?? 'Unknown';
set_transient( $transient_key, $country, 24 * HOUR_IN_SECONDS );
set_transient( $transient_key, $data, 24 * HOUR_IN_SECONDS );
$this->wpoau_track_transient_key( $transient_key );

return $country;
return $data;
}

/**
* Resolve a timezone from an IP address, with 24-hour caching.
* Resolve a country name from an IP address, with 24-hour caching.
*
* @param string $ip IP address.
* @return string
*/
public function wpoau_get_user_timezone( $ip ) {
if ( 'Unknown' === $ip ) {
return 'Unknown';
}

$transient_key = 'wpoau_timezone_' . md5( $ip );
$cached = get_transient( $transient_key );
if ( false !== $cached ) {
return $cached;
}

$response = wp_remote_get( "http://ip-api.com/json/{$ip}?fields=timezone" );

if ( is_wp_error( $response ) ) {
return 'Unknown';
}
public function wpoau_get_user_country( $ip ) {
$data = $this->wpoau_get_ip_geodata( $ip );

$data = json_decode( wp_remote_retrieve_body( $response ), true );
$timezone = isset( $data['timezone'] ) ? $data['timezone'] : 'Unknown';
return ! empty( $data['country'] ) ? $data['country'] : 'Unknown';
}

// Cache for 24 hours.
set_transient( $transient_key, $timezone, 24 * HOUR_IN_SECONDS );
$this->wpoau_track_transient_key( $transient_key );
/**
* Resolve a timezone from an IP address, with 24-hour caching.
*
* @param string $ip IP address.
* @return string
*/
public function wpoau_get_user_timezone( $ip ) {
$data = $this->wpoau_get_ip_geodata( $ip );

return $timezone;
return ! empty( $data['timezone']['id'] ) ? $data['timezone']['id'] : 'Unknown';
}

/**
Expand All @@ -317,34 +311,8 @@ public function wpoau_get_user_timezone( $ip ) {
* @return string
*/
public function wpoau_get_user_country_code( $ip ) {
if ( 'Unknown' === $ip ) {
return 'xx';
}

$transient_key = 'wpoau_country_' . md5( $ip ); // Prevent long key issues.

// Try getting from transient.
$cached_code = get_transient( $transient_key );
if ( false !== $cached_code ) {
return $cached_code;
}

// Fetch from API.
$response = wp_remote_get( "http://ip-api.com/json/{$ip}?fields=countryCode" );

if ( is_wp_error( $response ) ) {
return 'xx';
}

$body = wp_remote_retrieve_body( $response );
$data = json_decode( $body, true );

$code = isset( $data['countryCode'] ) ? strtolower( $data['countryCode'] ) : 'xx';

// Cache it for 24 hours.
set_transient( $transient_key, $code, 24 * HOUR_IN_SECONDS );
$this->wpoau_track_transient_key( $transient_key );
$data = $this->wpoau_get_ip_geodata( $ip );

return $code;
return ! empty( $data['country_code'] ) ? strtolower( $data['country_code'] ) : 'xx';
}
}
6 changes: 4 additions & 2 deletions online-active-users.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
* Plugin URI: https://wordpress.org/plugins/online-active-users/
* Description: Monitor and display real-time online users and last seen status on your WordPress site with Online Active Users plugin.
* Tags: online users, active users, online active users, real-time users, user activity
* Version: 3.4.2
* Version: 3.4.3
* Requires at least: 6.3
* Requires PHP: 8.0
* Author: Webizito
* Author URI: http://webizito.com/
* Contributors: valani9099
Expand All @@ -32,7 +34,7 @@
}

if ( ! defined( 'WPOAU_VERSION' ) ) {
define( 'WPOAU_VERSION', '3.4.1' );
define( 'WPOAU_VERSION', '3.4.3' );
}

// class-wpoau-active-users.php replaces the old inc/webi-functions.php (removed): both defined the
Expand Down
2 changes: 1 addition & 1 deletion phpstan-bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
define( 'WPOAU_PLUGIN_FILE', __DIR__ . '/online-active-users.php' );
}
if ( ! defined( 'WPOAU_VERSION' ) ) {
define( 'WPOAU_VERSION', '3.4.1' );
define( 'WPOAU_VERSION', '3.4.3' );
}
41 changes: 37 additions & 4 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ Contributors: valani9099, alkesh7
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=APRNBJUZHRP7G
Tags: online users, active users, online active users, real-time users, user activity
Requires at least: 6.3
Tested up to: 7.0
Stable tag: 3.4.2
Requires PHP: 7.3
Tested up to: 7.1
Stable tag: 3.4.3
Requires PHP: 8.0
License: GPLv3 or later
License URI: https://www.gnu.org/licenses/gpl-3.0.html
Plugin Name: Online Active Users
Expand All @@ -14,7 +14,7 @@ Plugin URI: https://wordpress.org/plugins/online-active-users/
Author: Webizito
Author URI: http://webizito.com/
Text Domain: online-active-users
Version: 3.4.2
Version: 3.4.3

Online Active Users is a lightweight, powerful plugin to monitor and display how many users are currently online active on your WordPress website.

Expand Down Expand Up @@ -94,6 +94,29 @@ We are committed to providing ongoing updates and new features based on user fee
* There are several ways to limit the number of active users on your WordPress website, such as using plugins like WP Limit Login Attempts or Limit Login Attempts Reloaded. These plugins allow you to set limits on the number of login attempts, which can help prevent brute-force attacks and limit the number of active users on your site.


== Third-Party Services ==

This plugin connects to external services to enrich the "Online Active Users" admin list table with an approximate country, timezone, and country flag for each currently-online user, based on their IP address.

**IP geolocation (country, timezone, country code)**
* Service: ipwho.is (by IPWHOIS.io)
* When: once per unique IP address, cached for 24 hours, whenever a logged-in user's status is recorded.
* Data sent: the visiting user's IP address, sent as part of the request URL. No other personal data is sent.
* Terms of Service: https://ipwhois.io/terms
* Privacy Policy: https://ipwhois.io/privacy

**Public IP lookup (local/development environments only)**
* Service: ipify (https://www.ipify.org)
* When: only as a fallback, when the site is running on localhost (IP resolves to 127.0.0.1 or ::1), to resolve a public IP for display purposes.
* Data sent: no parameters are sent; the request has no request body or query data.

**Country flag icons**
* Service: flagcdn.com
* When: whenever the "Online Active Users" admin list table is displayed, to load a small flag image per country.
* Data sent: the resolved two-letter country code, sent as part of the image URL requested by the administrator's browser.

None of these services are used for advertising, tracking, or analytics; they are used only to display geolocation context to site administrators.

== Screenshots ==

1. Admin - Users Pages - User Online Status
Expand Down Expand Up @@ -193,6 +216,13 @@ We are committed to providing ongoing updates and new features based on user fee
= 3.4.2 =
* Fix some bug.

= 3.4.3 =
* Fixed a `Requires PHP` mismatch left over from a botched merge (readme.txt said 7.3, composer.json said 8.0); both the plugin header and readme.txt now correctly state 8.0.
* Added `Requires at least` and `Requires PHP` to the plugin's own header, not just readme.txt.
* Removed calls to ip-api.com (its free tier prohibits commercial use, conflicting with this plugin's WooCommerce support, and was requested over plain HTTP); country, country code, and timezone are now all resolved from a single cached HTTPS call to ipwho.is.
* Added a Third-Party Services section to readme.txt disclosing all external services this plugin calls.
* Verified WordPress 7.1 compatibility; bumped Tested up to.


== Upgrade Notice ==

Expand Down Expand Up @@ -277,3 +307,6 @@ We are committed to providing ongoing updates and new features based on user fee

= 3.4.2 =
* Fix some bug.

= 3.4.3 =
* Fixed Requires PHP mismatch, added Third-Party Services disclosure, and dropped a non-commercial-only geolocation provider. Upgrade recommended.