Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/wp-stats-manager/includes/wsm_admin_interface.php
+++ b/wp-stats-manager/includes/wsm_admin_interface.php
@@ -51,7 +51,7 @@
function wsm_upgrade_to_pro()
{
- jQuery('#wsm_modal').modal();
+ jQuery('#wsm-upgrade-modal').modal({ escapeClose: true, clickClose: true, showClose: false });
}
</script>
--- a/wp-stats-manager/includes/wsm_init.php
+++ b/wp-stats-manager/includes/wsm_init.php
@@ -41,6 +41,7 @@
add_filter('clean_url', array('wsmInitPlugin', WSM_PREFIX . '_async_scripts'), 11, 1);
add_action('wp_enqueue_scripts', array('wsmInitPlugin', WSM_PREFIX . '_front_script_style'));
add_action('admin_footer', array('wsmInitPlugin', WSM_PREFIX . '_setting_popup_func'));
+ add_action('wp_ajax_wsm_dismiss_upgrade_modal', array('wsmInitPlugin', WSM_PREFIX . '_dismiss_upgrade_modal'));
add_filter('script_loader_tag', WSM_PREFIX . '_add_async_defer_attribute', 10, 2);
//update_option(WSM_PREFIX.'KeepData',1);
@@ -199,14 +200,12 @@
if ($mypage != 'wsm_settings') {
$wsmAdminJavaScript .= self::wsm_allAjaxRequests();
- echo '<script type="text/javascript">
- jQuery(function(){
+ $inline_js = 'jQuery(function(){
var arrLiveStats=[];
- var WSM_PREFIX="' . WSM_PREFIX . '";
-
+ var WSM_PREFIX="' . esc_js( WSM_PREFIX ) . '";
jQuery(".if-js-closed").removeClass("if-js-closed").addClass("closed");
- ' . $wsmAdminJavaScript . '});
- </script>';
+ ' . $wsmAdminJavaScript . '});';
+ wp_add_inline_script( WSM_PREFIX . '-custom-admin-script', $inline_js );
}
}
@@ -642,6 +641,10 @@
}
static function wsm_getReferrerDetails()
{
+ if ( ! current_user_can( 'manage_options' ) ) {
+ wp_send_json_error( array( 'message' => __( 'You do not have permission to view this content.', 'wp-stats-manager' ) ), 403 );
+ wp_die();
+ }
$arrRequest = array();
$arrResponse = array();
if (isset($_REQUEST['requests'])) {
@@ -685,7 +688,10 @@
static function wsm_getDateWiseLocationDetail()
{
-
+ if ( ! current_user_can( 'manage_options' ) ) {
+ wp_send_json_error( array( 'message' => __( 'You do not have permission to view this content.', 'wp-stats-manager' ) ), 403 );
+ wp_die();
+ }
$arrRequest = array(
'city' => sanitize_text_field($_REQUEST['city']),
@@ -767,6 +773,10 @@
}
static function wsm_getContentUrlDayView()
{
+ if ( ! current_user_can( 'manage_options' ) ) {
+ wp_send_json_error( array( 'message' => __( 'You do not have permission to view this content.', 'wp-stats-manager' ) ), 403 );
+ wp_die();
+ }
$arrRequest = array();
$arrResponse = array();
@@ -846,6 +856,10 @@
}
static function wsm_getReferralOSDetails()
{
+ if ( ! current_user_can( 'manage_options' ) ) {
+ wp_send_json_error( array( 'message' => __( 'You do not have permission to view this content.', 'wp-stats-manager' ) ), 403 );
+ wp_die();
+ }
$arrRequest = array();
$arrResponse = array();
@@ -929,6 +943,10 @@
}
static function wsm_getReferrerUrlDetails()
{
+ if ( ! current_user_can( 'manage_options' ) ) {
+ wp_send_json_error( array( 'message' => __( 'You do not have permission to view this content.', 'wp-stats-manager' ) ), 403 );
+ wp_die();
+ }
$arrRequest = array();
$arrResponse = array();
@@ -1006,8 +1024,10 @@
static function wsm_getUOSummary()
{
-
-
+ if ( ! current_user_can( 'manage_options' ) ) {
+ wp_send_json_error( array( 'message' => __( 'You do not have permission to view this content.', 'wp-stats-manager' ) ), 403 );
+ wp_die();
+ }
$arrRequest = array();
$arrResponse = array();
@@ -1072,6 +1092,10 @@
}
static function wsm_getTimezoneByCountry()
{
+ if ( ! current_user_can( 'manage_options' ) ) {
+ wp_send_json_error( array( 'message' => __( 'You do not have permission to view this content.', 'wp-stats-manager' ) ), 403 );
+ wp_die();
+ }
$countryCode = (isset($_REQUEST['code']) && $_REQUEST['code'] != '') ? sanitize_text_field($_REQUEST['code']) : '';
echo wsmFnGetTimeZoneByCountry($countryCode);
wp_die();
@@ -1312,6 +1336,12 @@
add_action('admin_notices', array('wsmInitPlugin', WSM_PREFIX . '_viewError'));
if (isset($_GET['action']) && $_GET['action'] == 'fixed_db_issue' && !isset($_GET['success'])) {
+ if ( ! current_user_can( 'manage_options' ) ) {
+ wp_die( __( 'You do not have permission to perform this action.', 'wp-stats-manager' ), 403 );
+ }
+ if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'], 'wsm_fix_db_issue' ) ) {
+ wp_die( __( 'Security check failed. Please try again.', 'wp-stats-manager' ), 403 );
+ }
$wpdb->query('DROP TABLE IF EXISTS ' . self::$tablePrefix . '_pageViews');
$wpdb->query('DROP TABLE IF EXISTS ' . self::$tablePrefix . '_uniqueVisitors');
$wpdb->query('DROP TABLE IF EXISTS ' . self::$tablePrefix . '_bounceVisits');
@@ -1408,7 +1438,7 @@
if ($missing_views) {
?>
<p><?php echo sprintf(__('There is still %d tables are missing. Please click on below button to fix the issue.', 'wphr'), esc_html($missing_views)); ?></p>
- <p><a class="primary button button-primary" href="<?php echo admin_url('index.php?action=fixed_db_issue'); ?>"><?php _e('Fix now!', 'wphr'); ?></a></p>
+ <p><a class="primary button button-primary" href="<?php echo esc_url( wp_nonce_url( admin_url('index.php?action=fixed_db_issue'), 'wsm_fix_db_issue' ) ); ?>"><?php _e('Fix now!', 'wphr'); ?></a></p>
<?php
} else {
@@ -1419,7 +1449,7 @@
<p><?php _e('There is some of the tables are missing. Please click on below button to fix the issue.', 'wphr'); ?></p>
- <p><a class="primary button button-primary" href="<?php echo admin_url('index.php?action=fixed_db_issue'); ?>"><?php _e('Fix now!', 'wphr'); ?></a></p>
+ <p><a class="primary button button-primary" href="<?php echo esc_url( wp_nonce_url( admin_url('index.php?action=fixed_db_issue'), 'wsm_fix_db_issue' ) ); ?>"><?php _e('Fix now!', 'wphr'); ?></a></p>
<?php
}
}
@@ -2010,19 +2040,34 @@
static function wsm_setting_popup_func()
{
-
global $pagenow, $wsmRequestArray;
- $page = isset($wsmRequestArray['page']) && $wsmRequestArray['page'] != '' ? sanitize_text_field($wsmRequestArray['page']) : '';
+ $page = isset( $wsmRequestArray['page'] ) && $wsmRequestArray['page'] != '' ? sanitize_text_field( $wsmRequestArray['page'] ) : '';
- //wsm_traffic
+ if ( ! ( $pagenow == 'admin.php' && strpos( $page, WSM_PREFIX ) !== false ) ) {
+ return;
+ }
- if ($pagenow == 'admin.php' && (strpos($page, WSM_PREFIX) !== false)) {
+ // Record install time the first time the plugin page is visited
+ if ( ! get_option( 'wsm_upgrade_modal_install_time' ) ) {
+ add_option( 'wsm_upgrade_modal_install_time', time() );
+ }
+ // Always render the modal HTML so wsm_upgrade_to_pro() can open it on demand.
+ // The JS inside wsm_modal.php handles the 24h auto-open logic separately.
+ require_once WSM_DIR . '/includes/wsm_modal.php';
+ }
- require_once WSM_DIR . '/includes/wsm_modal.php';
- add_option('wsm_popup_status', 1);
+ static function wsm_dismiss_upgrade_modal()
+ {
+ if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'wsm_dismiss_upgrade' ) ) {
+ wp_send_json_error( 'Invalid nonce', 403 );
+ }
+ if ( ! current_user_can( 'manage_options' ) ) {
+ wp_send_json_error( 'Unauthorized', 403 );
}
+ update_option( 'wsm_upgrade_modal_dismissed', true );
+ wp_send_json_success();
}
--- a/wp-stats-manager/includes/wsm_modal.php
+++ b/wp-stats-manager/includes/wsm_modal.php
@@ -1,140 +1,130 @@
-<!-- Modal -->
+<?php if ( ! defined( 'ABSPATH' ) ) exit; ?>
<style>
-.img_block.wsm-head {
- width: 100%;
- height: 60px;
- border-bottom: 1px solid #f5f5f5;
- padding-bottom: 10px;
-}
-
-.img_block.wsm-head .wsm-head-left {
- float: left;
-}
-
-.img_block.wsm-head .wsm-head-right {
- float: right;
-
-}
-
-
-.img_block.wsm-head .wsm-head-right img {
- width: auto;
-}
-
-.wsm_hint{
- font-size:16px;
-
-}
-
-.wsm_hint b{
- color:red;
-
-
-}
-
-.left_side{
- float:left;
- display:inline;
- width:65%;
-
-}
-
-.right_side{
- float:right;
- display:inline;
- width:30%;
-
-}
-.list_features li{
- margin-left:20px;
- font-size:16px;
-}
-
-.wsm-head-left span.wsm-version-info {
- background-color: #D8ECF9;
- padding: 8px 20px;
- font-weight: 500;
- font-size: 15px;
-
-}
-
-.wsm-head-left span.wsm-version-info span {
- font-weight: 700;
-}
-
-.modal-body, h4, h3, p{
- margin:20px;
-}
-#wsm_modal{
-
- padding:30px;
- padding-left:0px;
- min-width:50% !important;
- z-index:999
-
-}
-
-@media (min-width: 768px) {
-
-
- .modal-sm {
- width: 300px;
- }
-}
-
-@media (min-width: 992px) {
- .modal-lg {
- width: 900px;
- }
-}
+#wsm-upgrade-modal{padding:0;min-width:480px;max-width:520px;border-radius:20px;overflow:hidden;border:none;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif}
+.wsm-hero{background:#0F1B2D;padding:32px 28px 26px;position:relative;overflow:hidden}
+.wsm-hero-glow1{position:absolute;top:-60px;right:-60px;width:200px;height:200px;border-radius:50%;background:#185FA5;opacity:0.25;pointer-events:none}
+.wsm-hero-glow2{position:absolute;bottom:-80px;left:-40px;width:160px;height:160px;border-radius:50%;background:#534AB7;opacity:0.2;pointer-events:none}
+.wsm-version-badge{display:inline-flex;align-items:center;gap:6px;background:rgba(83,74,183,0.3);border:1px solid rgba(83,74,183,0.6);color:#AFA9EC;font-size:11px;font-weight:500;padding:4px 10px;border-radius:20px;margin-bottom:16px;position:relative;z-index:1}
+.wsm-version-dot{width:6px;height:6px;border-radius:50%;background:#7F77DD;display:inline-block;flex-shrink:0}
+.wsm-hero-title{color:#fff;font-size:22px;font-weight:600;line-height:1.35;margin:0 0 8px;position:relative;z-index:1}
+.wsm-hero-title span{color:#7F77DD}
+.wsm-hero-sub{color:rgba(255,255,255,0.5);font-size:13px;line-height:1.6;margin:0;position:relative;z-index:1}
+.wsm-body{padding:22px 26px 26px;background:#fff}
+.wsm-offer-strip{display:flex;align-items:center;gap:10px;background:#FFF8EE;border:1px solid #EF9F27;border-radius:10px;padding:11px 14px;margin-bottom:20px}
+.wsm-offer-icon{font-size:18px;flex-shrink:0;line-height:1}
+.wsm-offer-left{flex:1}
+.wsm-offer-title{font-size:13px;font-weight:600;color:#633806;margin:0}
+.wsm-offer-sub{font-size:11px;color:#854F0B;margin:2px 0 0}
+.wsm-offer-badge{background:#E87722;color:#fff;font-size:12px;font-weight:600;padding:4px 10px;border-radius:6px;white-space:nowrap}
+.wsm-section-label{font-size:11px;font-weight:600;color:#888;letter-spacing:0.8px;text-transform:uppercase;margin:0 0 10px;display:block}
+.wsm-features{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:20px}
+.wsm-feat{display:flex;align-items:center;gap:8px;background:#F8F8FA;border:1px solid #EBEBED;border-radius:8px;padding:9px 11px}
+.wsm-feat-icon{width:22px;height:22px;border-radius:6px;background:#E6F1FB;display:flex;align-items:center;justify-content:center;flex-shrink:0}
+.wsm-feat-icon svg{display:block}
+.wsm-feat-text{font-size:12px;color:#555;line-height:1.3;margin:0}
+.wsm-social-proof{display:flex;align-items:center;gap:10px;padding:12px 14px;background:#F8F8FA;border-radius:10px;margin-bottom:20px;border:1px solid #EBEBED}
+.wsm-avatars{display:flex}
+.wsm-av{width:26px;height:26px;border-radius:50%;border:2px solid #fff;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:600;color:#fff;margin-left:-8px}
+.wsm-av:first-child{margin-left:0}
+.wsm-sp-text{flex:1;font-size:12px;color:#666}
+.wsm-sp-text strong{color:#222;font-weight:600;display:block}
+.wsm-stars{color:#EF9F27;font-size:11px;letter-spacing:1px}
+.wsm-btn-main{display:flex;width:100%;background:#185FA5;color:#fff;border:none;border-radius:10px;padding:14px;font-size:15px;font-weight:600;cursor:pointer;align-items:center;justify-content:center;gap:8px;margin-bottom:12px;text-decoration:none;box-sizing:border-box}
+.wsm-btn-main:hover{background:#0C447C;color:#fff}
+.wsm-btn-main svg{flex-shrink:0}
+.wsm-skip{display:block;text-align:center;font-size:12px;color:#999;cursor:pointer;background:none;border:none;width:100%;padding:4px 0;margin:0}
+.wsm-skip:hover{color:#555}
+.close-modal{display:none !important}
</style>
-<div id="wsm_modal" style="display:none" class="modal fade" tabindex="-1">
- <div class="modal-dialog">
- <div class="modal-content">
-
-
- <div class="img_block wsm-head">
- <div class="wsm-head-left">
- <div class="wsm-head-title">Visitor Statistics Premium</div>
- <span class="wsm-version-info"><span>NEW V </span>6.8</span>
- </div >
-
- </div>
-
- <p class="wsm_hint">
- Thanks for being a loyal Visitor Statistics Lite user. Upgrade to Visitor Statistics Pro and unlock all the awesome features. <b><br><br>For limited time, get 50% off your order + Free Addons</b>
- </p>
-
- <h3>Main Premium Features!</h3>
-
- <div class="modal-body">
- <!-- body start -->
- <div class="container-fluid">
- <div class="row">
- <div class="left_side">
- <ul class="list_features">
- <li>✅ Online users statistics</li>
- <li>✅ Visitor’s Country & City Recognition</li>
- <li>✅ Recent visitors by IP</li>
- <li>✅ Recent visitors on the map</li>
- <li>✅ More Advanced reporting</li>
- </ul>
- </div>
-
- <div class="right_side">
- <img width="100%" src="<?php echo WSM_URL;?>images/features.gif" />
- </div>
-
- <div class="modal-footer">
- <a href="https://www.plugins-market.com/product/visitor-statistics-pro/" target="_blank">
- <img width="200px" src="<?php echo WSM_URL;?>images/upgrade-button-orange.png" /></a>
- <br>
- <b style="color:green">Trusted by More than 10,000 Website Owner :)</b>
- </div>
- </div>
- </div>
- </div>
- </div><!-- /.modal-content -->
-</div><!-- /.modal-dialog -->
-<!-- /.modal -->
No newline at end of file
+<div id="wsm-upgrade-modal" style="display:none">
+ <div class="wsm-hero">
+ <div class="wsm-hero-glow1"></div>
+ <div class="wsm-hero-glow2"></div>
+ <div class="wsm-version-badge">
+ <span class="wsm-version-dot"></span>
+ New — Version 6.8
+ </div>
+ <h2 class="wsm-hero-title">Stop guessing.<br><span>Know exactly</span> who visits your site — and why.</h2>
+ <p class="wsm-hero-sub">Join 10,000+ website owners who turn raw traffic data into real growth every single day.</p>
+ </div>
+ <div class="wsm-body">
+ <div class="wsm-offer-strip">
+ <div class="wsm-offer-icon">⚡</div>
+ <div class="wsm-offer-left">
+ <p class="wsm-offer-title">Limited-time offer — ends soon</p>
+ <p class="wsm-offer-sub">50% off your upgrade + free addons included</p>
+ </div>
+ <div class="wsm-offer-badge">50% OFF</div>
+ </div>
+ <span class="wsm-section-label">What you unlock</span>
+ <div class="wsm-features">
+ <div class="wsm-feat">
+ <div class="wsm-feat-icon"><svg width="12" height="12" viewBox="0 0 12 12" fill="none"><circle cx="6" cy="6" r="4" stroke="#185FA5" stroke-width="1.2"/><circle cx="6" cy="6" r="1.5" fill="#185FA5"/></svg></div>
+ <p class="wsm-feat-text">Real-time online users</p>
+ </div>
+ <div class="wsm-feat">
+ <div class="wsm-feat-icon"><svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M2 9L5 6L7 8L10 3" stroke="#185FA5" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></div>
+ <p class="wsm-feat-text">Advanced reporting</p>
+ </div>
+ <div class="wsm-feat">
+ <div class="wsm-feat-icon"><svg width="12" height="12" viewBox="0 0 12 12" fill="none"><rect x="1" y="3" width="10" height="7" rx="1.5" stroke="#185FA5" stroke-width="1.2"/><path d="M4 3V2a2 2 0 014 0v1" stroke="#185FA5" stroke-width="1.2" stroke-linecap="round"/></svg></div>
+ <p class="wsm-feat-text">Visitor tracking by IP</p>
+ </div>
+ <div class="wsm-feat">
+ <div class="wsm-feat-icon"><svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M6 1C3.8 1 2 2.8 2 5c0 3 4 7 4 7s4-4 4-7c0-2.2-1.8-4-4-4z" stroke="#185FA5" stroke-width="1.2"/><circle cx="6" cy="5" r="1.2" fill="#185FA5"/></svg></div>
+ <p class="wsm-feat-text">Live visitor map</p>
+ </div>
+ <div class="wsm-feat">
+ <div class="wsm-feat-icon"><svg width="12" height="12" viewBox="0 0 12 12" fill="none"><circle cx="6" cy="4" r="2" stroke="#185FA5" stroke-width="1.2"/><path d="M2 10c0-2.2 1.8-4 4-4s4 1.8 4 4" stroke="#185FA5" stroke-width="1.2" stroke-linecap="round"/></svg></div>
+ <p class="wsm-feat-text">Country & city data</p>
+ </div>
+ <div class="wsm-feat">
+ <div class="wsm-feat-icon"><svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M10 3L5 8L2 5" stroke="#185FA5" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg></div>
+ <p class="wsm-feat-text">Priority support</p>
+ </div>
+ </div>
+ <div class="wsm-social-proof">
+ <div class="wsm-avatars">
+ <div class="wsm-av" style="background:#185FA5">A</div>
+ <div class="wsm-av" style="background:#534AB7">M</div>
+ <div class="wsm-av" style="background:#0F6E56">S</div>
+ <div class="wsm-av" style="background:#993C1D">R</div>
+ </div>
+ <div class="wsm-sp-text">
+ <strong>10,000+ website owners trust us</strong>
+ <span class="wsm-stars">★★★★★ Rated 5 stars</span>
+ </div>
+ </div>
+ <a href="https://www.plugins-market.com/product/visitor-statistics-pro/" target="_blank" class="wsm-btn-main">
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v9M4 8l4 4 4-4" stroke="#fff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M2 13h12" stroke="#fff" stroke-width="1.5" stroke-linecap="round"/></svg>
+ Upgrade Now — Get 50% Off
+ </a>
+ <button class="wsm-skip" id="wsm-dismiss-btn">Dismiss</button>
+ </div>
+</div>
+
+<script>
+jQuery(document).ready(function($){
+ <?php if ( ! get_option( 'wsm_upgrade_modal_dismissed', false ) ) : ?>
+ var wsmInstallTime = <?php echo (int) get_option( 'wsm_upgrade_modal_install_time', time() ); ?>;
+ var wsmNow = <?php echo time(); ?>;
+ var wsmElapsed = wsmNow - wsmInstallTime;
+
+ if( wsmElapsed >= 86400 ){
+ $('#wsm-upgrade-modal').modal({ escapeClose: true, clickClose: true, showClose: false });
+ }
+ <?php endif; ?>
+
+ function wsmDoD(){
+ $.modal.close();
+ $.post('<?php echo esc_js( admin_url("admin-ajax.php") ); ?>', {
+ action: 'wsm_dismiss_upgrade_modal',
+ nonce: '<?php echo esc_js( wp_create_nonce("wsm_dismiss_upgrade") ); ?>'
+ });
+ }
+
+ $('#wsm-dismiss-btn').on('click', function(){ wsmDoD(); });
+ $(document).on('modal:close', '#wsm-upgrade-modal', function(){ wsmDoD(); });
+});
+</script>
--- a/wp-stats-manager/includes/wsm_statistics.php
+++ b/wp-stats-manager/includes/wsm_statistics.php
@@ -2282,7 +2282,20 @@
'second' => $second
), $atts, WSM_PREFIX . '_showCurrentStats');
- $atts['id'] = preg_replace('/[^a-zA-Z0-9_-]/', '', $atts['id']);
+ $atts['id'] = preg_replace( '/[^a-zA-Z0-9_-]/', '', $atts['id'] );
+ $atts['title'] = sanitize_text_field( $atts['title'] );
+ $atts['type'] = sanitize_key( $atts['type'] );
+ $atts['condition'] = sanitize_key( $atts['condition'] );
+ $atts['from'] = sanitize_text_field( $atts['from'] );
+ $atts['to'] = sanitize_text_field( $atts['to'] );
+ $atts['first'] = sanitize_text_field( $atts['first'] );
+ $atts['second'] = sanitize_text_field( $atts['second'] );
+
+ // Apply esc_js() to all attributes interpolated into JavaScript strings (Wordfence recommendation)
+ foreach ( ['height', 'width', 'title', 'id'] as $key ) {
+ $atts[ $key ] = esc_js( $atts[ $key ] );
+ }
+
$arrChartStats = array();
$arrChartStatSecond = array();
$yMax = 0;
--- a/wp-stats-manager/wp-stats-manager.php
+++ b/wp-stats-manager/wp-stats-manager.php
@@ -3,7 +3,7 @@
* Plugin Name: WP Visitor Statistics (Real Time Traffic)
* Plugin URI: http://plugins-market.com/contact-us
* Description: This plugin will track the web analytics for each page and show various analytics report in admin panel as well as in front end.
- * Version: 8.4
+ * Version: 8.5
* Author: osamaesh
* Author URI: http://plugins-market.com/
* Developer: osamaesh